blob: 6e48e580555ee3bd456fb8e3ed91c7a21fb70896 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovandd135242010-07-13 11:57:12 -030058#define VERSION "2.15"
Marcel Holtmann44dd46d2009-05-02 19:09:01 -070059
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020060int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010063static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030065static struct workqueue_struct *_busy_wq;
66
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020067struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070068 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069};
70
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030071static void l2cap_busy_work(struct work_struct *work);
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073static void l2cap_sock_close(struct sock *sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
75static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
76 u8 code, u8 ident, u16 dlen, void *data);
77
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030078static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
79
Linus Torvalds1da177e2005-04-16 15:20:36 -070080/* ---- L2CAP timers ---- */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020081void l2cap_sock_set_timer(struct sock *sk, long timeout)
Andrei Emeltchenko940a9ee2010-11-03 12:32:45 +020082{
83 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
84 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
85}
86
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -020087void l2cap_sock_clear_timer(struct sock *sk)
Andrei Emeltchenko940a9ee2010-11-03 12:32:45 +020088{
89 BT_DBG("sock %p state %d", sk, sk->sk_state);
90 sk_stop_timer(sk, &sk->sk_timer);
91}
92
Marcel Holtmann01394182006-07-03 10:02:46 +020093/* ---- L2CAP channels ---- */
94static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
95{
96 struct sock *s;
97 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
98 if (l2cap_pi(s)->dcid == cid)
99 break;
100 }
101 return s;
102}
103
104static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
105{
106 struct sock *s;
107 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
108 if (l2cap_pi(s)->scid == cid)
109 break;
110 }
111 return s;
112}
113
114/* Find channel with given SCID.
115 * Returns locked socket */
116static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
117{
118 struct sock *s;
119 read_lock(&l->lock);
120 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300121 if (s)
122 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200123 read_unlock(&l->lock);
124 return s;
125}
126
127static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
128{
129 struct sock *s;
130 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
131 if (l2cap_pi(s)->ident == ident)
132 break;
133 }
134 return s;
135}
136
137static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
138{
139 struct sock *s;
140 read_lock(&l->lock);
141 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300142 if (s)
143 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200144 read_unlock(&l->lock);
145 return s;
146}
147
148static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
149{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300150 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200151
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300152 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300153 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200154 return cid;
155 }
156
157 return 0;
158}
159
160static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
161{
162 sock_hold(sk);
163
164 if (l->head)
165 l2cap_pi(l->head)->prev_c = sk;
166
167 l2cap_pi(sk)->next_c = l->head;
168 l2cap_pi(sk)->prev_c = NULL;
169 l->head = sk;
170}
171
172static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
173{
174 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
175
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200176 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200177 if (sk == l->head)
178 l->head = next;
179
180 if (next)
181 l2cap_pi(next)->prev_c = prev;
182 if (prev)
183 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200184 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200185
186 __sock_put(sk);
187}
188
189static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
190{
191 struct l2cap_chan_list *l = &conn->chan_list;
192
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300193 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
194 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200195
Marcel Holtmann2950f212009-02-12 14:02:50 +0100196 conn->disc_reason = 0x13;
197
Marcel Holtmann01394182006-07-03 10:02:46 +0200198 l2cap_pi(sk)->conn = conn;
199
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300200 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200201 /* Alloc CID for connection-oriented socket */
202 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
203 } else if (sk->sk_type == SOCK_DGRAM) {
204 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300205 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
206 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200207 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
208 } else {
209 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
211 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200212 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
213 }
214
215 __l2cap_chan_link(l, sk);
216
217 if (parent)
218 bt_accept_enqueue(parent, sk);
219}
220
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900221/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200222 * Must be called on the locked socket. */
223static void l2cap_chan_del(struct sock *sk, int err)
224{
225 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
226 struct sock *parent = bt_sk(sk)->parent;
227
228 l2cap_sock_clear_timer(sk);
229
230 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
231
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900232 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200233 /* Unlink from channel list */
234 l2cap_chan_unlink(&conn->chan_list, sk);
235 l2cap_pi(sk)->conn = NULL;
236 hci_conn_put(conn->hcon);
237 }
238
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200239 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200240 sock_set_flag(sk, SOCK_ZAPPED);
241
242 if (err)
243 sk->sk_err = err;
244
245 if (parent) {
246 bt_accept_unlink(sk);
247 parent->sk_data_ready(parent, 0);
248 } else
249 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300250
251 skb_queue_purge(TX_QUEUE(sk));
252
253 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
254 struct srej_list *l, *tmp;
255
256 del_timer(&l2cap_pi(sk)->retrans_timer);
257 del_timer(&l2cap_pi(sk)->monitor_timer);
258 del_timer(&l2cap_pi(sk)->ack_timer);
259
260 skb_queue_purge(SREJ_QUEUE(sk));
261 skb_queue_purge(BUSY_QUEUE(sk));
262
263 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
264 list_del(&l->list);
265 kfree(l);
266 }
267 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200268}
269
Johan Hedberg8556edd32011-01-19 12:06:50 +0530270static inline u8 l2cap_get_auth_type(struct sock *sk)
271{
272 if (sk->sk_type == SOCK_RAW) {
273 switch (l2cap_pi(sk)->sec_level) {
274 case BT_SECURITY_HIGH:
275 return HCI_AT_DEDICATED_BONDING_MITM;
276 case BT_SECURITY_MEDIUM:
277 return HCI_AT_DEDICATED_BONDING;
278 default:
279 return HCI_AT_NO_BONDING;
280 }
281 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
282 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
283 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
284
285 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
286 return HCI_AT_NO_BONDING_MITM;
287 else
288 return HCI_AT_NO_BONDING;
289 } else {
290 switch (l2cap_pi(sk)->sec_level) {
291 case BT_SECURITY_HIGH:
292 return HCI_AT_GENERAL_BONDING_MITM;
293 case BT_SECURITY_MEDIUM:
294 return HCI_AT_GENERAL_BONDING;
295 default:
296 return HCI_AT_NO_BONDING;
297 }
298 }
299}
300
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100302static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200303{
304 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100305 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306
Johan Hedberg8556edd32011-01-19 12:06:50 +0530307 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100308
309 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
310 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200311}
312
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200313u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200314{
315 u8 id;
316
317 /* Get next available identificator.
318 * 1 - 128 are used by kernel.
319 * 129 - 199 are reserved.
320 * 200 - 254 are used by utilities like l2ping, etc.
321 */
322
323 spin_lock_bh(&conn->lock);
324
325 if (++conn->tx_ident > 128)
326 conn->tx_ident = 1;
327
328 id = conn->tx_ident;
329
330 spin_unlock_bh(&conn->lock);
331
332 return id;
333}
334
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200335void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200336{
337 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200338 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200339
340 BT_DBG("code 0x%2.2x", code);
341
342 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300343 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200344
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200345 if (lmp_no_flush_capable(conn->hcon->hdev))
346 flags = ACL_START_NO_FLUSH;
347 else
348 flags = ACL_START;
349
350 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200351}
352
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300353static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300354{
355 struct sk_buff *skb;
356 struct l2cap_hdr *lh;
357 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300358 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300359 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200360 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300362 if (sk->sk_state != BT_CONNECTED)
363 return;
364
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300365 if (pi->fcs == L2CAP_FCS_CRC16)
366 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367
368 BT_DBG("pi %p, control 0x%2.2x", pi, control);
369
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300370 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300371 control |= L2CAP_CTRL_FRAME_TYPE;
372
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300373 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
374 control |= L2CAP_CTRL_FINAL;
375 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
376 }
377
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300378 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
379 control |= L2CAP_CTRL_POLL;
380 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
381 }
382
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300383 skb = bt_skb_alloc(count, GFP_ATOMIC);
384 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300385 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300386
387 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300389 lh->cid = cpu_to_le16(pi->dcid);
390 put_unaligned_le16(control, skb_put(skb, 2));
391
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300392 if (pi->fcs == L2CAP_FCS_CRC16) {
393 u16 fcs = crc16(0, (u8 *)lh, count - 2);
394 put_unaligned_le16(fcs, skb_put(skb, 2));
395 }
396
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200397 if (lmp_no_flush_capable(conn->hcon->hdev))
398 flags = ACL_START_NO_FLUSH;
399 else
400 flags = ACL_START;
401
402 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300403}
404
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300405static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300406{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300407 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300408 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300409 pi->conn_state |= L2CAP_CONN_RNR_SENT;
410 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300411 control |= L2CAP_SUPER_RCV_READY;
412
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300413 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
414
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300415 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300416}
417
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300418static inline int __l2cap_no_conn_pending(struct sock *sk)
419{
420 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
421}
422
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200423static void l2cap_do_start(struct sock *sk)
424{
425 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
426
427 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100428 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
429 return;
430
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300431 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200432 struct l2cap_conn_req req;
433 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
434 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200436 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300437 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200438
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200439 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200440 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200441 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200442 } else {
443 struct l2cap_info_req req;
444 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
445
446 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
447 conn->info_ident = l2cap_get_ident(conn);
448
449 mod_timer(&conn->info_timer, jiffies +
450 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
451
452 l2cap_send_cmd(conn, conn->info_ident,
453 L2CAP_INFO_REQ, sizeof(req), &req);
454 }
455}
456
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300457static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
458{
459 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300460 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300461 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
462
463 switch (mode) {
464 case L2CAP_MODE_ERTM:
465 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
466 case L2CAP_MODE_STREAMING:
467 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
468 default:
469 return 0x00;
470 }
471}
472
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300473static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300474{
475 struct l2cap_disconn_req req;
476
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300477 if (!conn)
478 return;
479
480 skb_queue_purge(TX_QUEUE(sk));
481
482 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
483 del_timer(&l2cap_pi(sk)->retrans_timer);
484 del_timer(&l2cap_pi(sk)->monitor_timer);
485 del_timer(&l2cap_pi(sk)->ack_timer);
486 }
487
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
489 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
490 l2cap_send_cmd(conn, l2cap_get_ident(conn),
491 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300492
493 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300494 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495}
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498static void l2cap_conn_start(struct l2cap_conn *conn)
499{
500 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300501 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200502 struct sock *sk;
503
504 BT_DBG("conn %p", conn);
505
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300506 INIT_LIST_HEAD(&del.list);
507
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200508 read_lock(&l->lock);
509
510 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
511 bh_lock_sock(sk);
512
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300513 if (sk->sk_type != SOCK_SEQPACKET &&
514 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200515 bh_unlock_sock(sk);
516 continue;
517 }
518
519 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300521
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300522 if (!l2cap_check_security(sk) ||
523 !__l2cap_no_conn_pending(sk)) {
524 bh_unlock_sock(sk);
525 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200526 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300527
528 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
529 conn->feat_mask)
530 && l2cap_pi(sk)->conf_state &
531 L2CAP_CONF_STATE2_DEVICE) {
532 tmp1 = kzalloc(sizeof(struct sock_del_list),
533 GFP_ATOMIC);
534 tmp1->sk = sk;
535 list_add_tail(&tmp1->list, &del.list);
536 bh_unlock_sock(sk);
537 continue;
538 }
539
540 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
541 req.psm = l2cap_pi(sk)->psm;
542
543 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
544 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
545
546 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
547 L2CAP_CONN_REQ, sizeof(req), &req);
548
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200549 } else if (sk->sk_state == BT_CONNECT2) {
550 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300551 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200552 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
553 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
554
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100555 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100556 if (bt_sk(sk)->defer_setup) {
557 struct sock *parent = bt_sk(sk)->parent;
558 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
559 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
560 parent->sk_data_ready(parent, 0);
561
562 } else {
563 sk->sk_state = BT_CONFIG;
564 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
565 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
566 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200567 } else {
568 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
569 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
570 }
571
572 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
573 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300574
575 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
576 rsp.result != L2CAP_CR_SUCCESS) {
577 bh_unlock_sock(sk);
578 continue;
579 }
580
581 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
582 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
583 l2cap_build_conf_req(sk, buf), buf);
584 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200585 }
586
587 bh_unlock_sock(sk);
588 }
589
590 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300591
592 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
593 bh_lock_sock(tmp1->sk);
594 __l2cap_sock_close(tmp1->sk, ECONNRESET);
595 bh_unlock_sock(tmp1->sk);
596 list_del(&tmp1->list);
597 kfree(tmp1);
598 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200599}
600
601static void l2cap_conn_ready(struct l2cap_conn *conn)
602{
603 struct l2cap_chan_list *l = &conn->chan_list;
604 struct sock *sk;
605
606 BT_DBG("conn %p", conn);
607
608 read_lock(&l->lock);
609
610 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
611 bh_lock_sock(sk);
612
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300613 if (sk->sk_type != SOCK_SEQPACKET &&
614 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200615 l2cap_sock_clear_timer(sk);
616 sk->sk_state = BT_CONNECTED;
617 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200618 } else if (sk->sk_state == BT_CONNECT)
619 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200620
621 bh_unlock_sock(sk);
622 }
623
624 read_unlock(&l->lock);
625}
626
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200627/* Notify sockets that we cannot guaranty reliability anymore */
628static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
629{
630 struct l2cap_chan_list *l = &conn->chan_list;
631 struct sock *sk;
632
633 BT_DBG("conn %p", conn);
634
635 read_lock(&l->lock);
636
637 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100638 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200639 sk->sk_err = err;
640 }
641
642 read_unlock(&l->lock);
643}
644
645static void l2cap_info_timeout(unsigned long arg)
646{
647 struct l2cap_conn *conn = (void *) arg;
648
Marcel Holtmann984947d2009-02-06 23:35:19 +0100649 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100650 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100651
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200652 l2cap_conn_start(conn);
653}
654
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
656{
Marcel Holtmann01394182006-07-03 10:02:46 +0200657 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Marcel Holtmann01394182006-07-03 10:02:46 +0200659 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 return conn;
661
Marcel Holtmann01394182006-07-03 10:02:46 +0200662 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
663 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
666 hcon->l2cap_data = conn;
667 conn->hcon = hcon;
668
Marcel Holtmann01394182006-07-03 10:02:46 +0200669 BT_DBG("hcon %p conn %p", hcon, conn);
670
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 conn->mtu = hcon->hdev->acl_mtu;
672 conn->src = &hcon->hdev->bdaddr;
673 conn->dst = &hcon->dst;
674
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200675 conn->feat_mask = 0;
676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 spin_lock_init(&conn->lock);
678 rwlock_init(&conn->chan_list.lock);
679
Dave Young45054dc2009-10-18 20:28:30 +0000680 setup_timer(&conn->info_timer, l2cap_info_timeout,
681 (unsigned long) conn);
682
Marcel Holtmann2950f212009-02-12 14:02:50 +0100683 conn->disc_reason = 0x13;
684
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 return conn;
686}
687
Marcel Holtmann01394182006-07-03 10:02:46 +0200688static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Marcel Holtmann01394182006-07-03 10:02:46 +0200690 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 struct sock *sk;
692
Marcel Holtmann01394182006-07-03 10:02:46 +0200693 if (!conn)
694 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
696 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
697
Wei Yongjun7585b972009-02-25 18:29:52 +0800698 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
700 /* Kill channels */
701 while ((sk = conn->chan_list.head)) {
702 bh_lock_sock(sk);
703 l2cap_chan_del(sk, err);
704 bh_unlock_sock(sk);
705 l2cap_sock_kill(sk);
706 }
707
Dave Young8e8440f2008-03-03 12:18:55 -0800708 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
709 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 hcon->l2cap_data = NULL;
712 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
715static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
716{
717 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200718 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200720 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721}
722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725/* Find socket with psm and source bdaddr.
726 * Returns closest match.
727 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000728static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729{
730 struct sock *sk = NULL, *sk1 = NULL;
731 struct hlist_node *node;
732
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000733 read_lock(&l2cap_sk_list.lock);
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 sk_for_each(sk, node, &l2cap_sk_list.head) {
736 if (state && sk->sk_state != state)
737 continue;
738
739 if (l2cap_pi(sk)->psm == psm) {
740 /* Exact match. */
741 if (!bacmp(&bt_sk(sk)->src, src))
742 break;
743
744 /* Closest match */
745 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
746 sk1 = sk;
747 }
748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000751
752 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755static void l2cap_sock_cleanup_listen(struct sock *parent)
756{
757 struct sock *sk;
758
759 BT_DBG("parent %p", parent);
760
761 /* Close not yet accepted channels */
762 while ((sk = bt_accept_dequeue(parent, NULL)))
763 l2cap_sock_close(sk);
764
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200765 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 sock_set_flag(parent, SOCK_ZAPPED);
767}
768
769/* Kill socket (only if zapped and orphan)
770 * Must be called on unlocked socket.
771 */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200772void l2cap_sock_kill(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773{
774 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
775 return;
776
777 BT_DBG("sk %p state %d", sk, sk->sk_state);
778
779 /* Kill poor orphan */
780 bt_sock_unlink(&l2cap_sk_list, sk);
781 sock_set_flag(sk, SOCK_DEAD);
782 sock_put(sk);
783}
784
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200785void __l2cap_sock_close(struct sock *sk, int reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
787 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
788
789 switch (sk->sk_state) {
790 case BT_LISTEN:
791 l2cap_sock_cleanup_listen(sk);
792 break;
793
794 case BT_CONNECTED:
795 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300796 if (sk->sk_type == SOCK_SEQPACKET ||
797 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300801 l2cap_send_disconn_req(conn, sk, reason);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200802 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 break;
805
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100806 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300807 if (sk->sk_type == SOCK_SEQPACKET ||
808 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100809 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
810 struct l2cap_conn_rsp rsp;
811 __u16 result;
812
813 if (bt_sk(sk)->defer_setup)
814 result = L2CAP_CR_SEC_BLOCK;
815 else
816 result = L2CAP_CR_BAD_PSM;
Bao Liange733fb62011-01-29 21:39:37 +0800817 sk->sk_state = BT_DISCONN;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100818
819 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
820 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
821 rsp.result = cpu_to_le16(result);
822 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
823 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
824 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
825 } else
826 l2cap_chan_del(sk, reason);
827 break;
828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 case BT_CONNECT:
830 case BT_DISCONN:
831 l2cap_chan_del(sk, reason);
832 break;
833
834 default:
835 sock_set_flag(sk, SOCK_ZAPPED);
836 break;
837 }
838}
839
840/* Must be called on unlocked socket. */
841static void l2cap_sock_close(struct sock *sk)
842{
843 l2cap_sock_clear_timer(sk);
844 lock_sock(sk);
845 __l2cap_sock_close(sk, ECONNRESET);
846 release_sock(sk);
847 l2cap_sock_kill(sk);
848}
849
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200850int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
852 bdaddr_t *src = &bt_sk(sk)->src;
853 bdaddr_t *dst = &bt_sk(sk)->dst;
854 struct l2cap_conn *conn;
855 struct hci_conn *hcon;
856 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200857 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200858 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100860 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
861 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300863 hdev = hci_get_route(dst, src);
864 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 return -EHOSTUNREACH;
866
867 hci_dev_lock_bh(hdev);
868
869 err = -ENOMEM;
870
Johan Hedberg8556edd32011-01-19 12:06:50 +0530871 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200872
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100873 hcon = hci_connect(hdev, ACL_LINK, dst,
874 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 if (!hcon)
876 goto done;
877
878 conn = l2cap_conn_add(hcon, 0);
879 if (!conn) {
880 hci_conn_put(hcon);
881 goto done;
882 }
883
884 err = 0;
885
886 /* Update source addr of the socket */
887 bacpy(src, conn->src);
888
889 l2cap_chan_add(conn, sk, NULL);
890
891 sk->sk_state = BT_CONNECT;
892 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
893
894 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300895 if (sk->sk_type != SOCK_SEQPACKET &&
896 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530898 if (l2cap_check_security(sk))
899 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200900 } else
901 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
903
904done:
905 hci_dev_unlock_bh(hdev);
906 hci_dev_put(hdev);
907 return err;
908}
909
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200910int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300911{
912 DECLARE_WAITQUEUE(wait, current);
913 int err = 0;
914 int timeo = HZ/5;
915
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200916 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300917 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
918 set_current_state(TASK_INTERRUPTIBLE);
919
920 if (!timeo)
921 timeo = HZ/5;
922
923 if (signal_pending(current)) {
924 err = sock_intr_errno(timeo);
925 break;
926 }
927
928 release_sock(sk);
929 timeo = schedule_timeout(timeo);
930 lock_sock(sk);
931
932 err = sock_error(sk);
933 if (err)
934 break;
935 }
936 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200937 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300938 return err;
939}
940
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300941static void l2cap_monitor_timeout(unsigned long arg)
942{
943 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300944
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300945 BT_DBG("sk %p", sk);
946
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300947 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300948 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300949 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200950 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300951 return;
952 }
953
954 l2cap_pi(sk)->retry_count++;
955 __mod_monitor_timer();
956
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300957 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300958 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959}
960
961static void l2cap_retrans_timeout(unsigned long arg)
962{
963 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300964
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300965 BT_DBG("sk %p", sk);
966
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300967 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300968 l2cap_pi(sk)->retry_count = 1;
969 __mod_monitor_timer();
970
971 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
972
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300973 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300974 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300975}
976
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300977static void l2cap_drop_acked_frames(struct sock *sk)
978{
979 struct sk_buff *skb;
980
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300981 while ((skb = skb_peek(TX_QUEUE(sk))) &&
982 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300983 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
984 break;
985
986 skb = skb_dequeue(TX_QUEUE(sk));
987 kfree_skb(skb);
988
989 l2cap_pi(sk)->unacked_frames--;
990 }
991
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300992 if (!l2cap_pi(sk)->unacked_frames)
993 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300994}
995
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300996static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300997{
998 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200999 struct hci_conn *hcon = pi->conn->hcon;
1000 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001001
1002 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1003
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001004 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1005 flags = ACL_START_NO_FLUSH;
1006 else
1007 flags = ACL_START;
1008
1009 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010}
1011
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001012static void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001013{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001014 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001015 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001016 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001017
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001018 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1019 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001020 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001021 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001022
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001023 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001024 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1025 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001026 }
1027
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001028 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029
1030 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001031 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001032}
1033
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001034static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001035{
1036 struct l2cap_pinfo *pi = l2cap_pi(sk);
1037 struct sk_buff *skb, *tx_skb;
1038 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001039
1040 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001041 if (!skb)
1042 return;
1043
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001044 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001045 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001046 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001048 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1049 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001050
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001051 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001053 if (pi->remote_max_tx &&
1054 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001055 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 return;
1057 }
1058
1059 tx_skb = skb_clone(skb, GFP_ATOMIC);
1060 bt_cb(skb)->retries++;
1061 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001062
1063 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1064 control |= L2CAP_CTRL_FINAL;
1065 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1066 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001067
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1069 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001070
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1072
1073 if (pi->fcs == L2CAP_FCS_CRC16) {
1074 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1075 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1076 }
1077
1078 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001079}
1080
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001081static int l2cap_ertm_send(struct sock *sk)
1082{
1083 struct sk_buff *skb, *tx_skb;
1084 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001085 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001086 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001087
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001088 if (sk->sk_state != BT_CONNECTED)
1089 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001090
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001091 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001092
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001093 if (pi->remote_max_tx &&
1094 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001095 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001096 break;
1097 }
1098
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001099 tx_skb = skb_clone(skb, GFP_ATOMIC);
1100
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001101 bt_cb(skb)->retries++;
1102
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001104 control &= L2CAP_CTRL_SAR;
1105
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001106 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1107 control |= L2CAP_CTRL_FINAL;
1108 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1109 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001110 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1112 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1113
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001115 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001116 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1117 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1118 }
1119
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001120 l2cap_do_send(sk, tx_skb);
1121
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001122 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001123
1124 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1125 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1126
1127 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001128 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001129
1130 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1131 sk->sk_send_head = NULL;
1132 else
1133 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001134
1135 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136 }
1137
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001138 return nsent;
1139}
1140
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001141static int l2cap_retransmit_frames(struct sock *sk)
1142{
1143 struct l2cap_pinfo *pi = l2cap_pi(sk);
1144 int ret;
1145
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001146 if (!skb_queue_empty(TX_QUEUE(sk)))
1147 sk->sk_send_head = TX_QUEUE(sk)->next;
1148
1149 pi->next_tx_seq = pi->expected_ack_seq;
1150 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001151 return ret;
1152}
1153
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001154static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001155{
1156 struct sock *sk = (struct sock *)pi;
1157 u16 control = 0;
1158
1159 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1160
1161 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1162 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001163 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001164 l2cap_send_sframe(pi, control);
1165 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001166 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001167
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001168 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001169 return;
1170
1171 control |= L2CAP_SUPER_RCV_READY;
1172 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001173}
1174
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001175static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001176{
1177 struct srej_list *tail;
1178 u16 control;
1179
1180 control = L2CAP_SUPER_SELECT_REJECT;
1181 control |= L2CAP_CTRL_FINAL;
1182
1183 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1184 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1185
1186 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001187}
1188
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001189static 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 -07001190{
1191 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001192 struct sk_buff **frag;
1193 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001195 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001196 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198 sent += count;
1199 len -= count;
1200
1201 /* Continuation fragments (no L2CAP header) */
1202 frag = &skb_shinfo(skb)->frag_list;
1203 while (len) {
1204 count = min_t(unsigned int, conn->mtu, len);
1205
1206 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1207 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001208 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1210 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
1212 sent += count;
1213 len -= count;
1214
1215 frag = &(*frag)->next;
1216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001219}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001221static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1222{
1223 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1224 struct sk_buff *skb;
1225 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1226 struct l2cap_hdr *lh;
1227
1228 BT_DBG("sk %p len %d", sk, (int)len);
1229
1230 count = min_t(unsigned int, (conn->mtu - hlen), len);
1231 skb = bt_skb_send_alloc(sk, count + hlen,
1232 msg->msg_flags & MSG_DONTWAIT, &err);
1233 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001234 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235
1236 /* Create L2CAP header */
1237 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1238 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1239 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1240 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1241
1242 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1243 if (unlikely(err < 0)) {
1244 kfree_skb(skb);
1245 return ERR_PTR(err);
1246 }
1247 return skb;
1248}
1249
1250static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1251{
1252 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1253 struct sk_buff *skb;
1254 int err, count, hlen = L2CAP_HDR_SIZE;
1255 struct l2cap_hdr *lh;
1256
1257 BT_DBG("sk %p len %d", sk, (int)len);
1258
1259 count = min_t(unsigned int, (conn->mtu - hlen), len);
1260 skb = bt_skb_send_alloc(sk, count + hlen,
1261 msg->msg_flags & MSG_DONTWAIT, &err);
1262 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001263 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001264
1265 /* Create L2CAP header */
1266 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1267 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1268 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1269
1270 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1271 if (unlikely(err < 0)) {
1272 kfree_skb(skb);
1273 return ERR_PTR(err);
1274 }
1275 return skb;
1276}
1277
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001278static struct 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 -03001279{
1280 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1281 struct sk_buff *skb;
1282 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1283 struct l2cap_hdr *lh;
1284
1285 BT_DBG("sk %p len %d", sk, (int)len);
1286
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001287 if (!conn)
1288 return ERR_PTR(-ENOTCONN);
1289
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001290 if (sdulen)
1291 hlen += 2;
1292
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001293 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1294 hlen += 2;
1295
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001296 count = min_t(unsigned int, (conn->mtu - hlen), len);
1297 skb = bt_skb_send_alloc(sk, count + hlen,
1298 msg->msg_flags & MSG_DONTWAIT, &err);
1299 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001300 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301
1302 /* Create L2CAP header */
1303 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1304 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1305 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1306 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001307 if (sdulen)
1308 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001309
1310 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1311 if (unlikely(err < 0)) {
1312 kfree_skb(skb);
1313 return ERR_PTR(err);
1314 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001315
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001316 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1317 put_unaligned_le16(0, skb_put(skb, 2));
1318
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001319 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001320 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321}
1322
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001323static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1324{
1325 struct l2cap_pinfo *pi = l2cap_pi(sk);
1326 struct sk_buff *skb;
1327 struct sk_buff_head sar_queue;
1328 u16 control;
1329 size_t size = 0;
1330
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001331 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001332 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001333 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001334 if (IS_ERR(skb))
1335 return PTR_ERR(skb);
1336
1337 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001338 len -= pi->remote_mps;
1339 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001340
1341 while (len > 0) {
1342 size_t buflen;
1343
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001344 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001345 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001346 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001348 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349 buflen = len;
1350 }
1351
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001352 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353 if (IS_ERR(skb)) {
1354 skb_queue_purge(&sar_queue);
1355 return PTR_ERR(skb);
1356 }
1357
1358 __skb_queue_tail(&sar_queue, skb);
1359 len -= buflen;
1360 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001361 }
1362 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1363 if (sk->sk_send_head == NULL)
1364 sk->sk_send_head = sar_queue.next;
1365
1366 return size;
1367}
1368
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001369int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
1371 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001372 struct l2cap_pinfo *pi = l2cap_pi(sk);
1373 struct sk_buff *skb;
1374 u16 control;
1375 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
1377 BT_DBG("sock %p, sk %p", sock, sk);
1378
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001379 err = sock_error(sk);
1380 if (err)
1381 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
1383 if (msg->msg_flags & MSG_OOB)
1384 return -EOPNOTSUPP;
1385
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 lock_sock(sk);
1387
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001388 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001390 goto done;
1391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001393 /* Connectionless channel */
1394 if (sk->sk_type == SOCK_DGRAM) {
1395 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001396 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001397 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001398 } else {
1399 l2cap_do_send(sk, skb);
1400 err = len;
1401 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001402 goto done;
1403 }
1404
1405 switch (pi->mode) {
1406 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001407 /* Check outgoing MTU */
1408 if (len > pi->omtu) {
João Paulo Rechi Vitaf9dd11b2010-06-22 13:56:24 -03001409 err = -EMSGSIZE;
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001410 goto done;
1411 }
1412
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001413 /* Create a basic PDU */
1414 skb = l2cap_create_basic_pdu(sk, msg, len);
1415 if (IS_ERR(skb)) {
1416 err = PTR_ERR(skb);
1417 goto done;
1418 }
1419
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001420 l2cap_do_send(sk, skb);
1421 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422 break;
1423
1424 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001425 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001426 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001427 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001429 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001430 if (IS_ERR(skb)) {
1431 err = PTR_ERR(skb);
1432 goto done;
1433 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001434 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001435
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001436 if (sk->sk_send_head == NULL)
1437 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001438
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001440 /* Segment SDU into multiples PDUs */
1441 err = l2cap_sar_segment_sdu(sk, msg, len);
1442 if (err < 0)
1443 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001444 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001445
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001446 if (pi->mode == L2CAP_MODE_STREAMING) {
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001447 l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001448 } else {
David Sterba45719282011-01-14 14:59:44 +01001449 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1450 (pi->conn_state & L2CAP_CONN_WAIT_F)) {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001451 err = len;
1452 break;
1453 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001454 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001455 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001456
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001457 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001458 err = len;
1459 break;
1460
1461 default:
1462 BT_DBG("bad state %1.1x", pi->mode);
João Paulo Rechi Vitabc766db22010-06-22 13:56:25 -03001463 err = -EBADFD;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001464 }
1465
1466done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 release_sock(sk);
1468 return err;
1469}
1470
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471static void l2cap_chan_ready(struct sock *sk)
1472{
1473 struct sock *parent = bt_sk(sk)->parent;
1474
1475 BT_DBG("sk %p, parent %p", sk, parent);
1476
1477 l2cap_pi(sk)->conf_state = 0;
1478 l2cap_sock_clear_timer(sk);
1479
1480 if (!parent) {
1481 /* Outgoing channel.
1482 * Wake up socket sleeping on connect.
1483 */
1484 sk->sk_state = BT_CONNECTED;
1485 sk->sk_state_change(sk);
1486 } else {
1487 /* Incoming channel.
1488 * Wake up socket sleeping on accept.
1489 */
1490 parent->sk_data_ready(parent, 0);
1491 }
1492}
1493
1494/* Copy frame to all raw sockets on that connection */
1495static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1496{
1497 struct l2cap_chan_list *l = &conn->chan_list;
1498 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001499 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501 BT_DBG("conn %p", conn);
1502
1503 read_lock(&l->lock);
1504 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1505 if (sk->sk_type != SOCK_RAW)
1506 continue;
1507
1508 /* Don't send frame to the socket it came from */
1509 if (skb->sk == sk)
1510 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001511 nskb = skb_clone(skb, GFP_ATOMIC);
1512 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 continue;
1514
1515 if (sock_queue_rcv_skb(sk, nskb))
1516 kfree_skb(nskb);
1517 }
1518 read_unlock(&l->lock);
1519}
1520
1521/* ---- L2CAP signalling commands ---- */
1522static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1523 u8 code, u8 ident, u16 dlen, void *data)
1524{
1525 struct sk_buff *skb, **frag;
1526 struct l2cap_cmd_hdr *cmd;
1527 struct l2cap_hdr *lh;
1528 int len, count;
1529
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001530 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1531 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
1533 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1534 count = min_t(unsigned int, conn->mtu, len);
1535
1536 skb = bt_skb_alloc(count, GFP_ATOMIC);
1537 if (!skb)
1538 return NULL;
1539
1540 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001541 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03001542 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
1544 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1545 cmd->code = code;
1546 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001547 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
1549 if (dlen) {
1550 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1551 memcpy(skb_put(skb, count), data, count);
1552 data += count;
1553 }
1554
1555 len -= skb->len;
1556
1557 /* Continuation fragments (no L2CAP header) */
1558 frag = &skb_shinfo(skb)->frag_list;
1559 while (len) {
1560 count = min_t(unsigned int, conn->mtu, len);
1561
1562 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1563 if (!*frag)
1564 goto fail;
1565
1566 memcpy(skb_put(*frag, count), data, count);
1567
1568 len -= count;
1569 data += count;
1570
1571 frag = &(*frag)->next;
1572 }
1573
1574 return skb;
1575
1576fail:
1577 kfree_skb(skb);
1578 return NULL;
1579}
1580
1581static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1582{
1583 struct l2cap_conf_opt *opt = *ptr;
1584 int len;
1585
1586 len = L2CAP_CONF_OPT_SIZE + opt->len;
1587 *ptr += len;
1588
1589 *type = opt->type;
1590 *olen = opt->len;
1591
1592 switch (opt->len) {
1593 case 1:
1594 *val = *((u8 *) opt->val);
1595 break;
1596
1597 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001598 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 break;
1600
1601 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001602 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 break;
1604
1605 default:
1606 *val = (unsigned long) opt->val;
1607 break;
1608 }
1609
1610 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1611 return len;
1612}
1613
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1615{
1616 struct l2cap_conf_opt *opt = *ptr;
1617
1618 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1619
1620 opt->type = type;
1621 opt->len = len;
1622
1623 switch (len) {
1624 case 1:
1625 *((u8 *) opt->val) = val;
1626 break;
1627
1628 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001629 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 break;
1631
1632 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001633 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 break;
1635
1636 default:
1637 memcpy(opt->val, (void *) val, len);
1638 break;
1639 }
1640
1641 *ptr += L2CAP_CONF_OPT_SIZE + len;
1642}
1643
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001644static void l2cap_ack_timeout(unsigned long arg)
1645{
1646 struct sock *sk = (void *) arg;
1647
1648 bh_lock_sock(sk);
1649 l2cap_send_ack(l2cap_pi(sk));
1650 bh_unlock_sock(sk);
1651}
1652
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001653static inline void l2cap_ertm_init(struct sock *sk)
1654{
1655 l2cap_pi(sk)->expected_ack_seq = 0;
1656 l2cap_pi(sk)->unacked_frames = 0;
1657 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001658 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001659 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001660
1661 setup_timer(&l2cap_pi(sk)->retrans_timer,
1662 l2cap_retrans_timeout, (unsigned long) sk);
1663 setup_timer(&l2cap_pi(sk)->monitor_timer,
1664 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001665 setup_timer(&l2cap_pi(sk)->ack_timer,
1666 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001667
1668 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001669 __skb_queue_head_init(BUSY_QUEUE(sk));
1670
1671 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001672
1673 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001674}
1675
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001676static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1677{
1678 switch (mode) {
1679 case L2CAP_MODE_STREAMING:
1680 case L2CAP_MODE_ERTM:
1681 if (l2cap_mode_supported(mode, remote_feat_mask))
1682 return mode;
1683 /* fall through */
1684 default:
1685 return L2CAP_MODE_BASIC;
1686 }
1687}
1688
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001689int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690{
1691 struct l2cap_pinfo *pi = l2cap_pi(sk);
1692 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001693 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 void *ptr = req->data;
1695
1696 BT_DBG("sk %p", sk);
1697
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001698 if (pi->num_conf_req || pi->num_conf_rsp)
1699 goto done;
1700
1701 switch (pi->mode) {
1702 case L2CAP_MODE_STREAMING:
1703 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001704 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001705 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001706
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001707 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001708 default:
1709 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1710 break;
1711 }
1712
1713done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001714 if (pi->imtu != L2CAP_DEFAULT_MTU)
1715 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1716
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001717 switch (pi->mode) {
1718 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001719 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1720 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1721 break;
1722
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001723 rfc.mode = L2CAP_MODE_BASIC;
1724 rfc.txwin_size = 0;
1725 rfc.max_transmit = 0;
1726 rfc.retrans_timeout = 0;
1727 rfc.monitor_timeout = 0;
1728 rfc.max_pdu_size = 0;
1729
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001730 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1731 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001732 break;
1733
1734 case L2CAP_MODE_ERTM:
1735 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001736 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001737 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001738 rfc.retrans_timeout = 0;
1739 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001740 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001741 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001742 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001743
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001744 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1745 (unsigned long) &rfc);
1746
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1748 break;
1749
1750 if (pi->fcs == L2CAP_FCS_NONE ||
1751 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1752 pi->fcs = L2CAP_FCS_NONE;
1753 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1754 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001755 break;
1756
1757 case L2CAP_MODE_STREAMING:
1758 rfc.mode = L2CAP_MODE_STREAMING;
1759 rfc.txwin_size = 0;
1760 rfc.max_transmit = 0;
1761 rfc.retrans_timeout = 0;
1762 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001763 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001764 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001765 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001766
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001767 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1768 (unsigned long) &rfc);
1769
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001770 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1771 break;
1772
1773 if (pi->fcs == L2CAP_FCS_NONE ||
1774 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1775 pi->fcs = L2CAP_FCS_NONE;
1776 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1777 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001778 break;
1779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
1781 /* FIXME: Need actual value of the flush timeout */
1782 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
1783 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
1784
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001785 req->dcid = cpu_to_le16(pi->dcid);
1786 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
1788 return ptr - data;
1789}
1790
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001791static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792{
1793 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001794 struct l2cap_conf_rsp *rsp = data;
1795 void *ptr = rsp->data;
1796 void *req = pi->conf_req;
1797 int len = pi->conf_len;
1798 int type, hint, olen;
1799 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001800 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001801 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001802 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001804 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001805
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001806 while (len >= L2CAP_CONF_OPT_SIZE) {
1807 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001809 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001810 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001811
1812 switch (type) {
1813 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001814 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001815 break;
1816
1817 case L2CAP_CONF_FLUSH_TO:
1818 pi->flush_to = val;
1819 break;
1820
1821 case L2CAP_CONF_QOS:
1822 break;
1823
Marcel Holtmann6464f352007-10-20 13:39:51 +02001824 case L2CAP_CONF_RFC:
1825 if (olen == sizeof(rfc))
1826 memcpy(&rfc, (void *) val, olen);
1827 break;
1828
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001829 case L2CAP_CONF_FCS:
1830 if (val == L2CAP_FCS_NONE)
1831 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1832
1833 break;
1834
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001835 default:
1836 if (hint)
1837 break;
1838
1839 result = L2CAP_CONF_UNKNOWN;
1840 *((u8 *) ptr++) = type;
1841 break;
1842 }
1843 }
1844
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001845 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001846 goto done;
1847
1848 switch (pi->mode) {
1849 case L2CAP_MODE_STREAMING:
1850 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001851 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1852 pi->mode = l2cap_select_mode(rfc.mode,
1853 pi->conn->feat_mask);
1854 break;
1855 }
1856
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001857 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001858 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001859
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001860 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001861 }
1862
1863done:
1864 if (pi->mode != rfc.mode) {
1865 result = L2CAP_CONF_UNACCEPT;
1866 rfc.mode = pi->mode;
1867
1868 if (pi->num_conf_rsp == 1)
1869 return -ECONNREFUSED;
1870
1871 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1872 sizeof(rfc), (unsigned long) &rfc);
1873 }
1874
1875
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001876 if (result == L2CAP_CONF_SUCCESS) {
1877 /* Configure output options and let the other side know
1878 * which ones we don't like. */
1879
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001880 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1881 result = L2CAP_CONF_UNACCEPT;
1882 else {
1883 pi->omtu = mtu;
1884 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1885 }
1886 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001887
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001888 switch (rfc.mode) {
1889 case L2CAP_MODE_BASIC:
1890 pi->fcs = L2CAP_FCS_NONE;
1891 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1892 break;
1893
1894 case L2CAP_MODE_ERTM:
1895 pi->remote_tx_win = rfc.txwin_size;
1896 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001897
1898 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1899 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001900
1901 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001902
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001903 rfc.retrans_timeout =
1904 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1905 rfc.monitor_timeout =
1906 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001907
1908 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001909
1910 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1911 sizeof(rfc), (unsigned long) &rfc);
1912
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001913 break;
1914
1915 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001916 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1917 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001918
1919 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920
1921 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001922
1923 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1924 sizeof(rfc), (unsigned long) &rfc);
1925
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001926 break;
1927
1928 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001929 result = L2CAP_CONF_UNACCEPT;
1930
1931 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001932 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001933 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001934
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001935 if (result == L2CAP_CONF_SUCCESS)
1936 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1937 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001938 rsp->scid = cpu_to_le16(pi->dcid);
1939 rsp->result = cpu_to_le16(result);
1940 rsp->flags = cpu_to_le16(0x0000);
1941
1942 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943}
1944
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001945static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1946{
1947 struct l2cap_pinfo *pi = l2cap_pi(sk);
1948 struct l2cap_conf_req *req = data;
1949 void *ptr = req->data;
1950 int type, olen;
1951 unsigned long val;
1952 struct l2cap_conf_rfc rfc;
1953
1954 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1955
1956 while (len >= L2CAP_CONF_OPT_SIZE) {
1957 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1958
1959 switch (type) {
1960 case L2CAP_CONF_MTU:
1961 if (val < L2CAP_DEFAULT_MIN_MTU) {
1962 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001963 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001964 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001965 pi->imtu = val;
1966 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001967 break;
1968
1969 case L2CAP_CONF_FLUSH_TO:
1970 pi->flush_to = val;
1971 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1972 2, pi->flush_to);
1973 break;
1974
1975 case L2CAP_CONF_RFC:
1976 if (olen == sizeof(rfc))
1977 memcpy(&rfc, (void *)val, olen);
1978
1979 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1980 rfc.mode != pi->mode)
1981 return -ECONNREFUSED;
1982
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001983 pi->fcs = 0;
1984
1985 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1986 sizeof(rfc), (unsigned long) &rfc);
1987 break;
1988 }
1989 }
1990
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001991 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1992 return -ECONNREFUSED;
1993
1994 pi->mode = rfc.mode;
1995
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001996 if (*result == L2CAP_CONF_SUCCESS) {
1997 switch (rfc.mode) {
1998 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001999 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2000 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002001 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002002 break;
2003 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002004 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002005 }
2006 }
2007
2008 req->dcid = cpu_to_le16(pi->dcid);
2009 req->flags = cpu_to_le16(0x0000);
2010
2011 return ptr - data;
2012}
2013
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002014static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015{
2016 struct l2cap_conf_rsp *rsp = data;
2017 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002019 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002021 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002022 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002023 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
2025 return ptr - data;
2026}
2027
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002028static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2029{
2030 struct l2cap_pinfo *pi = l2cap_pi(sk);
2031 int type, olen;
2032 unsigned long val;
2033 struct l2cap_conf_rfc rfc;
2034
2035 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2036
2037 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2038 return;
2039
2040 while (len >= L2CAP_CONF_OPT_SIZE) {
2041 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2042
2043 switch (type) {
2044 case L2CAP_CONF_RFC:
2045 if (olen == sizeof(rfc))
2046 memcpy(&rfc, (void *)val, olen);
2047 goto done;
2048 }
2049 }
2050
2051done:
2052 switch (rfc.mode) {
2053 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002054 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2055 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002056 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2057 break;
2058 case L2CAP_MODE_STREAMING:
2059 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2060 }
2061}
2062
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002063static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2064{
2065 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2066
2067 if (rej->reason != 0x0000)
2068 return 0;
2069
2070 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2071 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002072 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002073
2074 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002075 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002076
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002077 l2cap_conn_start(conn);
2078 }
2079
2080 return 0;
2081}
2082
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2084{
2085 struct l2cap_chan_list *list = &conn->chan_list;
2086 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2087 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002088 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002089 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090
2091 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002092 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
2094 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2095
2096 /* Check if we have socket listening on psm */
2097 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2098 if (!parent) {
2099 result = L2CAP_CR_BAD_PSM;
2100 goto sendresp;
2101 }
2102
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002103 bh_lock_sock(parent);
2104
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002105 /* Check if the ACL is secure enough (if not SDP) */
2106 if (psm != cpu_to_le16(0x0001) &&
2107 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002108 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002109 result = L2CAP_CR_SEC_BLOCK;
2110 goto response;
2111 }
2112
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 result = L2CAP_CR_NO_MEM;
2114
2115 /* Check for backlog size */
2116 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002117 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 goto response;
2119 }
2120
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002121 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 if (!sk)
2123 goto response;
2124
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002125 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
2127 /* Check if we already have channel with that dcid */
2128 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002129 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 sock_set_flag(sk, SOCK_ZAPPED);
2131 l2cap_sock_kill(sk);
2132 goto response;
2133 }
2134
2135 hci_conn_hold(conn->hcon);
2136
2137 l2cap_sock_init(sk, parent);
2138 bacpy(&bt_sk(sk)->src, conn->src);
2139 bacpy(&bt_sk(sk)->dst, conn->dst);
2140 l2cap_pi(sk)->psm = psm;
2141 l2cap_pi(sk)->dcid = scid;
2142
2143 __l2cap_chan_add(conn, sk, parent);
2144 dcid = l2cap_pi(sk)->scid;
2145
2146 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 l2cap_pi(sk)->ident = cmd->ident;
2149
Marcel Holtmann984947d2009-02-06 23:35:19 +01002150 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002151 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002152 if (bt_sk(sk)->defer_setup) {
2153 sk->sk_state = BT_CONNECT2;
2154 result = L2CAP_CR_PEND;
2155 status = L2CAP_CS_AUTHOR_PEND;
2156 parent->sk_data_ready(parent, 0);
2157 } else {
2158 sk->sk_state = BT_CONFIG;
2159 result = L2CAP_CR_SUCCESS;
2160 status = L2CAP_CS_NO_INFO;
2161 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002162 } else {
2163 sk->sk_state = BT_CONNECT2;
2164 result = L2CAP_CR_PEND;
2165 status = L2CAP_CS_AUTHEN_PEND;
2166 }
2167 } else {
2168 sk->sk_state = BT_CONNECT2;
2169 result = L2CAP_CR_PEND;
2170 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 }
2172
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002173 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174
2175response:
2176 bh_unlock_sock(parent);
2177
2178sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002179 rsp.scid = cpu_to_le16(scid);
2180 rsp.dcid = cpu_to_le16(dcid);
2181 rsp.result = cpu_to_le16(result);
2182 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002184
2185 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2186 struct l2cap_info_req info;
2187 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2188
2189 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2190 conn->info_ident = l2cap_get_ident(conn);
2191
2192 mod_timer(&conn->info_timer, jiffies +
2193 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2194
2195 l2cap_send_cmd(conn, conn->info_ident,
2196 L2CAP_INFO_REQ, sizeof(info), &info);
2197 }
2198
Nathan Holsteind793fe82010-10-15 11:54:02 -04002199 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002200 result == L2CAP_CR_SUCCESS) {
2201 u8 buf[128];
2202 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2203 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2204 l2cap_build_conf_req(sk, buf), buf);
2205 l2cap_pi(sk)->num_conf_req++;
2206 }
2207
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 return 0;
2209}
2210
2211static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2212{
2213 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2214 u16 scid, dcid, result, status;
2215 struct sock *sk;
2216 u8 req[128];
2217
2218 scid = __le16_to_cpu(rsp->scid);
2219 dcid = __le16_to_cpu(rsp->dcid);
2220 result = __le16_to_cpu(rsp->result);
2221 status = __le16_to_cpu(rsp->status);
2222
2223 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2224
2225 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002226 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2227 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002228 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002230 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2231 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002232 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 }
2234
2235 switch (result) {
2236 case L2CAP_CR_SUCCESS:
2237 sk->sk_state = BT_CONFIG;
2238 l2cap_pi(sk)->ident = 0;
2239 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002240 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2241
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002242 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2243 break;
2244
2245 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2246
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2248 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002249 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 break;
2251
2252 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002253 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 break;
2255
2256 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002257 /* don't delete l2cap channel if sk is owned by user */
2258 if (sock_owned_by_user(sk)) {
2259 sk->sk_state = BT_DISCONN;
2260 l2cap_sock_clear_timer(sk);
2261 l2cap_sock_set_timer(sk, HZ / 5);
2262 break;
2263 }
2264
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 l2cap_chan_del(sk, ECONNREFUSED);
2266 break;
2267 }
2268
2269 bh_unlock_sock(sk);
2270 return 0;
2271}
2272
Mat Martineau8c462b62010-08-24 15:35:42 -07002273static inline void set_default_fcs(struct l2cap_pinfo *pi)
2274{
2275 /* FCS is enabled only in ERTM or streaming mode, if one or both
2276 * sides request it.
2277 */
2278 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2279 pi->fcs = L2CAP_FCS_NONE;
2280 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2281 pi->fcs = L2CAP_FCS_CRC16;
2282}
2283
Al Viro88219a02007-07-29 00:17:25 -07002284static 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 -07002285{
2286 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2287 u16 dcid, flags;
2288 u8 rsp[64];
2289 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002290 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
2292 dcid = __le16_to_cpu(req->dcid);
2293 flags = __le16_to_cpu(req->flags);
2294
2295 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2296
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002297 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2298 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 return -ENOENT;
2300
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002301 if (sk->sk_state != BT_CONFIG) {
2302 struct l2cap_cmd_rej rej;
2303
2304 rej.reason = cpu_to_le16(0x0002);
2305 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2306 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002307 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002308 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002309
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002310 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002311 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002312 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2313 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2314 l2cap_build_conf_rsp(sk, rsp,
2315 L2CAP_CONF_REJECT, flags), rsp);
2316 goto unlock;
2317 }
2318
2319 /* Store config. */
2320 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2321 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
2323 if (flags & 0x0001) {
2324 /* Incomplete config. Send empty response. */
2325 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002326 l2cap_build_conf_rsp(sk, rsp,
2327 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 goto unlock;
2329 }
2330
2331 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002332 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002333 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002334 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002338 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002339 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002340
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002341 /* Reset config buffer. */
2342 l2cap_pi(sk)->conf_len = 0;
2343
Marcel Holtmann876d9482007-10-20 13:35:42 +02002344 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2345 goto unlock;
2346
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002348 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002349
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002351
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002352 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002353 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002354 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002355 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2356 l2cap_ertm_init(sk);
2357
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002359 goto unlock;
2360 }
2361
2362 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002363 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002364 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002366 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002367 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 }
2369
2370unlock:
2371 bh_unlock_sock(sk);
2372 return 0;
2373}
2374
2375static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2376{
2377 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2378 u16 scid, flags, result;
2379 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002380 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
2382 scid = __le16_to_cpu(rsp->scid);
2383 flags = __le16_to_cpu(rsp->flags);
2384 result = __le16_to_cpu(rsp->result);
2385
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002386 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2387 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002389 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2390 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 return 0;
2392
2393 switch (result) {
2394 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002395 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 break;
2397
2398 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002399 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400 char req[64];
2401
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002402 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002403 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002404 goto done;
2405 }
2406
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002407 /* throw out any old stored conf requests */
2408 result = L2CAP_CONF_SUCCESS;
2409 len = l2cap_parse_conf_rsp(sk, rsp->data,
2410 len, req, &result);
2411 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002412 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002413 goto done;
2414 }
2415
2416 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2417 L2CAP_CONF_REQ, len, req);
2418 l2cap_pi(sk)->num_conf_req++;
2419 if (result != L2CAP_CONF_SUCCESS)
2420 goto done;
2421 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 }
2423
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002424 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002425 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002427 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 goto done;
2429 }
2430
2431 if (flags & 0x01)
2432 goto done;
2433
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2435
2436 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002437 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002438
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002440 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002441 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002442 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002443 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2444 l2cap_ertm_init(sk);
2445
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 l2cap_chan_ready(sk);
2447 }
2448
2449done:
2450 bh_unlock_sock(sk);
2451 return 0;
2452}
2453
2454static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2455{
2456 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2457 struct l2cap_disconn_rsp rsp;
2458 u16 dcid, scid;
2459 struct sock *sk;
2460
2461 scid = __le16_to_cpu(req->scid);
2462 dcid = __le16_to_cpu(req->dcid);
2463
2464 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2465
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002466 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2467 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 return 0;
2469
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002470 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2471 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2473
2474 sk->sk_shutdown = SHUTDOWN_MASK;
2475
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002476 /* don't delete l2cap channel if sk is owned by user */
2477 if (sock_owned_by_user(sk)) {
2478 sk->sk_state = BT_DISCONN;
2479 l2cap_sock_clear_timer(sk);
2480 l2cap_sock_set_timer(sk, HZ / 5);
2481 bh_unlock_sock(sk);
2482 return 0;
2483 }
2484
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 l2cap_chan_del(sk, ECONNRESET);
2486 bh_unlock_sock(sk);
2487
2488 l2cap_sock_kill(sk);
2489 return 0;
2490}
2491
2492static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2493{
2494 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2495 u16 dcid, scid;
2496 struct sock *sk;
2497
2498 scid = __le16_to_cpu(rsp->scid);
2499 dcid = __le16_to_cpu(rsp->dcid);
2500
2501 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2502
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002503 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2504 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 return 0;
2506
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002507 /* don't delete l2cap channel if sk is owned by user */
2508 if (sock_owned_by_user(sk)) {
2509 sk->sk_state = BT_DISCONN;
2510 l2cap_sock_clear_timer(sk);
2511 l2cap_sock_set_timer(sk, HZ / 5);
2512 bh_unlock_sock(sk);
2513 return 0;
2514 }
2515
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 l2cap_chan_del(sk, 0);
2517 bh_unlock_sock(sk);
2518
2519 l2cap_sock_kill(sk);
2520 return 0;
2521}
2522
2523static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2524{
2525 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 u16 type;
2527
2528 type = __le16_to_cpu(req->type);
2529
2530 BT_DBG("type 0x%4.4x", type);
2531
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002532 if (type == L2CAP_IT_FEAT_MASK) {
2533 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002534 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002535 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2536 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2537 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002538 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002539 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2540 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002541 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002542 l2cap_send_cmd(conn, cmd->ident,
2543 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002544 } else if (type == L2CAP_IT_FIXED_CHAN) {
2545 u8 buf[12];
2546 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2547 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2548 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2549 memcpy(buf + 4, l2cap_fixed_chan, 8);
2550 l2cap_send_cmd(conn, cmd->ident,
2551 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002552 } else {
2553 struct l2cap_info_rsp rsp;
2554 rsp.type = cpu_to_le16(type);
2555 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2556 l2cap_send_cmd(conn, cmd->ident,
2557 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
2560 return 0;
2561}
2562
2563static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2564{
2565 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2566 u16 type, result;
2567
2568 type = __le16_to_cpu(rsp->type);
2569 result = __le16_to_cpu(rsp->result);
2570
2571 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2572
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002573 del_timer(&conn->info_timer);
2574
Ville Tervoadb08ed2010-08-04 09:43:33 +03002575 if (result != L2CAP_IR_SUCCESS) {
2576 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2577 conn->info_ident = 0;
2578
2579 l2cap_conn_start(conn);
2580
2581 return 0;
2582 }
2583
Marcel Holtmann984947d2009-02-06 23:35:19 +01002584 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002585 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002586
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002587 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002588 struct l2cap_info_req req;
2589 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2590
2591 conn->info_ident = l2cap_get_ident(conn);
2592
2593 l2cap_send_cmd(conn, conn->info_ident,
2594 L2CAP_INFO_REQ, sizeof(req), &req);
2595 } else {
2596 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2597 conn->info_ident = 0;
2598
2599 l2cap_conn_start(conn);
2600 }
2601 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002602 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002603 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002604
2605 l2cap_conn_start(conn);
2606 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002607
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 return 0;
2609}
2610
2611static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
2612{
2613 u8 *data = skb->data;
2614 int len = skb->len;
2615 struct l2cap_cmd_hdr cmd;
2616 int err = 0;
2617
2618 l2cap_raw_recv(conn, skb);
2619
2620 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002621 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2623 data += L2CAP_CMD_HDR_SIZE;
2624 len -= L2CAP_CMD_HDR_SIZE;
2625
Al Viro88219a02007-07-29 00:17:25 -07002626 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
Al Viro88219a02007-07-29 00:17:25 -07002628 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 -07002629
Al Viro88219a02007-07-29 00:17:25 -07002630 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 BT_DBG("corrupted command");
2632 break;
2633 }
2634
2635 switch (cmd.code) {
2636 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002637 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 break;
2639
2640 case L2CAP_CONN_REQ:
2641 err = l2cap_connect_req(conn, &cmd, data);
2642 break;
2643
2644 case L2CAP_CONN_RSP:
2645 err = l2cap_connect_rsp(conn, &cmd, data);
2646 break;
2647
2648 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002649 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 break;
2651
2652 case L2CAP_CONF_RSP:
2653 err = l2cap_config_rsp(conn, &cmd, data);
2654 break;
2655
2656 case L2CAP_DISCONN_REQ:
2657 err = l2cap_disconnect_req(conn, &cmd, data);
2658 break;
2659
2660 case L2CAP_DISCONN_RSP:
2661 err = l2cap_disconnect_rsp(conn, &cmd, data);
2662 break;
2663
2664 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002665 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 break;
2667
2668 case L2CAP_ECHO_RSP:
2669 break;
2670
2671 case L2CAP_INFO_REQ:
2672 err = l2cap_information_req(conn, &cmd, data);
2673 break;
2674
2675 case L2CAP_INFO_RSP:
2676 err = l2cap_information_rsp(conn, &cmd, data);
2677 break;
2678
2679 default:
2680 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
2681 err = -EINVAL;
2682 break;
2683 }
2684
2685 if (err) {
2686 struct l2cap_cmd_rej rej;
2687 BT_DBG("error %d", err);
2688
2689 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002690 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2692 }
2693
Al Viro88219a02007-07-29 00:17:25 -07002694 data += cmd_len;
2695 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 }
2697
2698 kfree_skb(skb);
2699}
2700
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002701static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2702{
2703 u16 our_fcs, rcv_fcs;
2704 int hdr_size = L2CAP_HDR_SIZE + 2;
2705
2706 if (pi->fcs == L2CAP_FCS_CRC16) {
2707 skb_trim(skb, skb->len - 2);
2708 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2709 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2710
2711 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002712 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002713 }
2714 return 0;
2715}
2716
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002717static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2718{
2719 struct l2cap_pinfo *pi = l2cap_pi(sk);
2720 u16 control = 0;
2721
2722 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002723
2724 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2725
2726 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002727 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002728 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002729 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002730 }
2731
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002732 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2733 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002734
2735 l2cap_ertm_send(sk);
2736
2737 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2738 pi->frames_sent == 0) {
2739 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002740 l2cap_send_sframe(pi, control);
2741 }
2742}
2743
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002744static 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 -03002745{
2746 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002747 struct l2cap_pinfo *pi = l2cap_pi(sk);
2748 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002749
2750 bt_cb(skb)->tx_seq = tx_seq;
2751 bt_cb(skb)->sar = sar;
2752
2753 next_skb = skb_peek(SREJ_QUEUE(sk));
2754 if (!next_skb) {
2755 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002756 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002757 }
2758
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002759 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2760 if (tx_seq_offset < 0)
2761 tx_seq_offset += 64;
2762
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002763 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002764 if (bt_cb(next_skb)->tx_seq == tx_seq)
2765 return -EINVAL;
2766
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002767 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2768 pi->buffer_seq) % 64;
2769 if (next_tx_seq_offset < 0)
2770 next_tx_seq_offset += 64;
2771
2772 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002773 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002774 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002775 }
2776
2777 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2778 break;
2779
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002780 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002781
2782 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002783
2784 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002785}
2786
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002787static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2788{
2789 struct l2cap_pinfo *pi = l2cap_pi(sk);
2790 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002791 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002792
2793 switch (control & L2CAP_CTRL_SAR) {
2794 case L2CAP_SDU_UNSEGMENTED:
2795 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2796 goto drop;
2797
2798 err = sock_queue_rcv_skb(sk, skb);
2799 if (!err)
2800 return err;
2801
2802 break;
2803
2804 case L2CAP_SDU_START:
2805 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2806 goto drop;
2807
2808 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002809
2810 if (pi->sdu_len > pi->imtu)
2811 goto disconnect;
2812
2813 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002814 if (!pi->sdu)
2815 return -ENOMEM;
2816
2817 /* pull sdu_len bytes only after alloc, because of Local Busy
2818 * condition we have to be sure that this will be executed
2819 * only once, i.e., when alloc does not fail */
2820 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002821
2822 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2823
2824 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2825 pi->partial_sdu_len = skb->len;
2826 break;
2827
2828 case L2CAP_SDU_CONTINUE:
2829 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2830 goto disconnect;
2831
2832 if (!pi->sdu)
2833 goto disconnect;
2834
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002835 pi->partial_sdu_len += skb->len;
2836 if (pi->partial_sdu_len > pi->sdu_len)
2837 goto drop;
2838
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002839 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2840
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002841 break;
2842
2843 case L2CAP_SDU_END:
2844 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2845 goto disconnect;
2846
2847 if (!pi->sdu)
2848 goto disconnect;
2849
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002850 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002851 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002852
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002853 if (pi->partial_sdu_len > pi->imtu)
2854 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002855
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002856 if (pi->partial_sdu_len != pi->sdu_len)
2857 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002858
2859 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002860 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861
2862 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002863 if (!_skb) {
2864 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2865 return -ENOMEM;
2866 }
2867
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002868 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002869 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002870 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002871 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2872 return err;
2873 }
2874
2875 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2876 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877
2878 kfree_skb(pi->sdu);
2879 break;
2880 }
2881
2882 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002883 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002884
2885drop:
2886 kfree_skb(pi->sdu);
2887 pi->sdu = NULL;
2888
2889disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002890 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002891 kfree_skb(skb);
2892 return 0;
2893}
2894
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002895static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002896{
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002897 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002898 struct sk_buff *skb;
2899 u16 control;
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002900 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002901
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002902 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2903 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2904 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2905 if (err < 0) {
2906 skb_queue_head(BUSY_QUEUE(sk), skb);
2907 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002908 }
2909
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002910 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002911 }
2912
2913 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2914 goto done;
2915
2916 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2917 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2918 l2cap_send_sframe(pi, control);
2919 l2cap_pi(sk)->retry_count = 1;
2920
2921 del_timer(&pi->retrans_timer);
2922 __mod_monitor_timer();
2923
2924 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2925
2926done:
2927 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2928 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2929
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002930 BT_DBG("sk %p, Exit local busy", sk);
2931
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002932 return 0;
2933}
2934
2935static void l2cap_busy_work(struct work_struct *work)
2936{
2937 DECLARE_WAITQUEUE(wait, current);
2938 struct l2cap_pinfo *pi =
2939 container_of(work, struct l2cap_pinfo, busy_work);
2940 struct sock *sk = (struct sock *)pi;
2941 int n_tries = 0, timeo = HZ/5, err;
2942 struct sk_buff *skb;
2943
2944 lock_sock(sk);
2945
2946 add_wait_queue(sk_sleep(sk), &wait);
2947 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2948 set_current_state(TASK_INTERRUPTIBLE);
2949
2950 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2951 err = -EBUSY;
2952 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2953 break;
2954 }
2955
2956 if (!timeo)
2957 timeo = HZ/5;
2958
2959 if (signal_pending(current)) {
2960 err = sock_intr_errno(timeo);
2961 break;
2962 }
2963
2964 release_sock(sk);
2965 timeo = schedule_timeout(timeo);
2966 lock_sock(sk);
2967
2968 err = sock_error(sk);
2969 if (err)
2970 break;
2971
2972 if (l2cap_try_push_rx_skb(sk) == 0)
2973 break;
2974 }
2975
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002976 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002977 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002978
2979 release_sock(sk);
2980}
2981
2982static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2983{
2984 struct l2cap_pinfo *pi = l2cap_pi(sk);
2985 int sctrl, err;
2986
2987 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2988 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2989 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03002990 return l2cap_try_push_rx_skb(sk);
2991
2992
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 }
2994
2995 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2996 if (err >= 0) {
2997 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2998 return err;
2999 }
3000
3001 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003002 BT_DBG("sk %p, Enter local busy", sk);
3003
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003004 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3005 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3006 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3007
3008 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3009 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3010 l2cap_send_sframe(pi, sctrl);
3011
3012 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3013
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003014 del_timer(&pi->ack_timer);
3015
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003016 queue_work(_busy_wq, &pi->busy_work);
3017
3018 return err;
3019}
3020
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003021static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003022{
3023 struct l2cap_pinfo *pi = l2cap_pi(sk);
3024 struct sk_buff *_skb;
3025 int err = -EINVAL;
3026
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003027 /*
3028 * TODO: We have to notify the userland if some data is lost with the
3029 * Streaming Mode.
3030 */
3031
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003032 switch (control & L2CAP_CTRL_SAR) {
3033 case L2CAP_SDU_UNSEGMENTED:
3034 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3035 kfree_skb(pi->sdu);
3036 break;
3037 }
3038
3039 err = sock_queue_rcv_skb(sk, skb);
3040 if (!err)
3041 return 0;
3042
3043 break;
3044
3045 case L2CAP_SDU_START:
3046 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3047 kfree_skb(pi->sdu);
3048 break;
3049 }
3050
3051 pi->sdu_len = get_unaligned_le16(skb->data);
3052 skb_pull(skb, 2);
3053
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003054 if (pi->sdu_len > pi->imtu) {
3055 err = -EMSGSIZE;
3056 break;
3057 }
3058
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003059 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3060 if (!pi->sdu) {
3061 err = -ENOMEM;
3062 break;
3063 }
3064
3065 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3066
3067 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3068 pi->partial_sdu_len = skb->len;
3069 err = 0;
3070 break;
3071
3072 case L2CAP_SDU_CONTINUE:
3073 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3074 break;
3075
3076 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3077
3078 pi->partial_sdu_len += skb->len;
3079 if (pi->partial_sdu_len > pi->sdu_len)
3080 kfree_skb(pi->sdu);
3081 else
3082 err = 0;
3083
3084 break;
3085
3086 case L2CAP_SDU_END:
3087 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3088 break;
3089
3090 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3091
3092 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3093 pi->partial_sdu_len += skb->len;
3094
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003095 if (pi->partial_sdu_len > pi->imtu)
3096 goto drop;
3097
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003098 if (pi->partial_sdu_len == pi->sdu_len) {
3099 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3100 err = sock_queue_rcv_skb(sk, _skb);
3101 if (err < 0)
3102 kfree_skb(_skb);
3103 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003104 err = 0;
3105
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003106drop:
3107 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003108 break;
3109 }
3110
3111 kfree_skb(skb);
3112 return err;
3113}
3114
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003115static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3116{
3117 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003118 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003119
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003120 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003121 if (bt_cb(skb)->tx_seq != tx_seq)
3122 break;
3123
3124 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003125 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003126 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003127 l2cap_pi(sk)->buffer_seq_srej =
3128 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003129 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003130 }
3131}
3132
3133static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3134{
3135 struct l2cap_pinfo *pi = l2cap_pi(sk);
3136 struct srej_list *l, *tmp;
3137 u16 control;
3138
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003139 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003140 if (l->tx_seq == tx_seq) {
3141 list_del(&l->list);
3142 kfree(l);
3143 return;
3144 }
3145 control = L2CAP_SUPER_SELECT_REJECT;
3146 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3147 l2cap_send_sframe(pi, control);
3148 list_del(&l->list);
3149 list_add_tail(&l->list, SREJ_LIST(sk));
3150 }
3151}
3152
3153static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3154{
3155 struct l2cap_pinfo *pi = l2cap_pi(sk);
3156 struct srej_list *new;
3157 u16 control;
3158
3159 while (tx_seq != pi->expected_tx_seq) {
3160 control = L2CAP_SUPER_SELECT_REJECT;
3161 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3162 l2cap_send_sframe(pi, control);
3163
3164 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003165 new->tx_seq = pi->expected_tx_seq;
3166 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003167 list_add_tail(&new->list, SREJ_LIST(sk));
3168 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003169 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003170}
3171
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003172static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3173{
3174 struct l2cap_pinfo *pi = l2cap_pi(sk);
3175 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003176 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003177 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003178 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003179 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003180 int err = 0;
3181
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003182 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3183 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003184
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003185 if (L2CAP_CTRL_FINAL & rx_control &&
3186 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003187 del_timer(&pi->monitor_timer);
3188 if (pi->unacked_frames > 0)
3189 __mod_retrans_timer();
3190 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3191 }
3192
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003193 pi->expected_ack_seq = req_seq;
3194 l2cap_drop_acked_frames(sk);
3195
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003196 if (tx_seq == pi->expected_tx_seq)
3197 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003198
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003199 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3200 if (tx_seq_offset < 0)
3201 tx_seq_offset += 64;
3202
3203 /* invalid tx_seq */
3204 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003205 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003206 goto drop;
3207 }
3208
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003209 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3210 goto drop;
3211
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3213 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003214
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003215 first = list_first_entry(SREJ_LIST(sk),
3216 struct srej_list, list);
3217 if (tx_seq == first->tx_seq) {
3218 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3219 l2cap_check_srej_gap(sk, tx_seq);
3220
3221 list_del(&first->list);
3222 kfree(first);
3223
3224 if (list_empty(SREJ_LIST(sk))) {
3225 pi->buffer_seq = pi->buffer_seq_srej;
3226 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003227 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003228 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229 }
3230 } else {
3231 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003232
3233 /* duplicated tx_seq */
3234 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3235 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003236
3237 list_for_each_entry(l, SREJ_LIST(sk), list) {
3238 if (l->tx_seq == tx_seq) {
3239 l2cap_resend_srejframe(sk, tx_seq);
3240 return 0;
3241 }
3242 }
3243 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003244 }
3245 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003246 expected_tx_seq_offset =
3247 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3248 if (expected_tx_seq_offset < 0)
3249 expected_tx_seq_offset += 64;
3250
3251 /* duplicated tx_seq */
3252 if (tx_seq_offset < expected_tx_seq_offset)
3253 goto drop;
3254
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003255 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003256
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003257 BT_DBG("sk %p, Enter SREJ", sk);
3258
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003259 INIT_LIST_HEAD(SREJ_LIST(sk));
3260 pi->buffer_seq_srej = pi->buffer_seq;
3261
3262 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003263 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003264 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3265
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003266 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3267
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003268 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003269
3270 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003271 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003272 return 0;
3273
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003274expected:
3275 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3276
3277 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003278 bt_cb(skb)->tx_seq = tx_seq;
3279 bt_cb(skb)->sar = sar;
3280 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003281 return 0;
3282 }
3283
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003284 err = l2cap_push_rx_skb(sk, skb, rx_control);
3285 if (err < 0)
3286 return 0;
3287
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003288 if (rx_control & L2CAP_CTRL_FINAL) {
3289 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3290 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003291 else
3292 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003293 }
3294
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003295 __mod_ack_timer();
3296
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003297 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3298 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003299 l2cap_send_ack(pi);
3300
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003302
3303drop:
3304 kfree_skb(skb);
3305 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003306}
3307
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003308static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003309{
3310 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003311
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003312 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3313 rx_control);
3314
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003315 pi->expected_ack_seq = __get_reqseq(rx_control);
3316 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003317
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003318 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003319 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003320 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3321 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3322 (pi->unacked_frames > 0))
3323 __mod_retrans_timer();
3324
3325 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3326 l2cap_send_srejtail(sk);
3327 } else {
3328 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003329 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003330
3331 } else if (rx_control & L2CAP_CTRL_FINAL) {
3332 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003333
3334 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3335 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003336 else
3337 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003338
3339 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003340 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3341 (pi->unacked_frames > 0))
3342 __mod_retrans_timer();
3343
3344 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003345 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003346 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003347 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003348 l2cap_ertm_send(sk);
3349 }
3350}
3351
3352static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3353{
3354 struct l2cap_pinfo *pi = l2cap_pi(sk);
3355 u8 tx_seq = __get_reqseq(rx_control);
3356
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003357 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3358
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003359 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3360
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003361 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003362 l2cap_drop_acked_frames(sk);
3363
3364 if (rx_control & L2CAP_CTRL_FINAL) {
3365 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3366 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003367 else
3368 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003369 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003370 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003371
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003372 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003373 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003374 }
3375}
3376static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3377{
3378 struct l2cap_pinfo *pi = l2cap_pi(sk);
3379 u8 tx_seq = __get_reqseq(rx_control);
3380
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003381 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3382
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003383 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3384
3385 if (rx_control & L2CAP_CTRL_POLL) {
3386 pi->expected_ack_seq = tx_seq;
3387 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003388
3389 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003390 l2cap_retransmit_one_frame(sk, tx_seq);
3391
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003393
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3395 pi->srej_save_reqseq = tx_seq;
3396 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3397 }
3398 } else if (rx_control & L2CAP_CTRL_FINAL) {
3399 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3400 pi->srej_save_reqseq == tx_seq)
3401 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3402 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003403 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003404 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003405 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3407 pi->srej_save_reqseq = tx_seq;
3408 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3409 }
3410 }
3411}
3412
3413static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3414{
3415 struct l2cap_pinfo *pi = l2cap_pi(sk);
3416 u8 tx_seq = __get_reqseq(rx_control);
3417
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003418 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3419
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3421 pi->expected_ack_seq = tx_seq;
3422 l2cap_drop_acked_frames(sk);
3423
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003424 if (rx_control & L2CAP_CTRL_POLL)
3425 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3426
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003427 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3428 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003429 if (rx_control & L2CAP_CTRL_POLL)
3430 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003431 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003432 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003433
3434 if (rx_control & L2CAP_CTRL_POLL)
3435 l2cap_send_srejtail(sk);
3436 else
3437 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438}
3439
3440static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3441{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003442 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3443
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003444 if (L2CAP_CTRL_FINAL & rx_control &&
3445 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446 del_timer(&l2cap_pi(sk)->monitor_timer);
3447 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003448 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003450 }
3451
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003452 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3453 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003454 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003455 break;
3456
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003457 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003459 break;
3460
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003461 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003462 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003463 break;
3464
3465 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003467 break;
3468 }
3469
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003470 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003471 return 0;
3472}
3473
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003474static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3475{
3476 struct l2cap_pinfo *pi = l2cap_pi(sk);
3477 u16 control;
3478 u8 req_seq;
3479 int len, next_tx_seq_offset, req_seq_offset;
3480
3481 control = get_unaligned_le16(skb->data);
3482 skb_pull(skb, 2);
3483 len = skb->len;
3484
3485 /*
3486 * We can just drop the corrupted I-frame here.
3487 * Receiver will miss it and start proper recovery
3488 * procedures and ask retransmission.
3489 */
3490 if (l2cap_check_fcs(pi, skb))
3491 goto drop;
3492
3493 if (__is_sar_start(control) && __is_iframe(control))
3494 len -= 2;
3495
3496 if (pi->fcs == L2CAP_FCS_CRC16)
3497 len -= 2;
3498
3499 if (len > pi->mps) {
3500 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3501 goto drop;
3502 }
3503
3504 req_seq = __get_reqseq(control);
3505 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3506 if (req_seq_offset < 0)
3507 req_seq_offset += 64;
3508
3509 next_tx_seq_offset =
3510 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3511 if (next_tx_seq_offset < 0)
3512 next_tx_seq_offset += 64;
3513
3514 /* check for invalid req-seq */
3515 if (req_seq_offset > next_tx_seq_offset) {
3516 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3517 goto drop;
3518 }
3519
3520 if (__is_iframe(control)) {
3521 if (len < 0) {
3522 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3523 goto drop;
3524 }
3525
3526 l2cap_data_channel_iframe(sk, control, skb);
3527 } else {
3528 if (len != 0) {
3529 BT_ERR("%d", len);
3530 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3531 goto drop;
3532 }
3533
3534 l2cap_data_channel_sframe(sk, control, skb);
3535 }
3536
3537 return 0;
3538
3539drop:
3540 kfree_skb(skb);
3541 return 0;
3542}
3543
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3545{
3546 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003547 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003548 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003549 u8 tx_seq;
3550 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551
3552 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3553 if (!sk) {
3554 BT_DBG("unknown cid 0x%4.4x", cid);
3555 goto drop;
3556 }
3557
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003558 pi = l2cap_pi(sk);
3559
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 BT_DBG("sk %p, len %d", sk, skb->len);
3561
3562 if (sk->sk_state != BT_CONNECTED)
3563 goto drop;
3564
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003565 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003566 case L2CAP_MODE_BASIC:
3567 /* If socket recv buffers overflows we drop data here
3568 * which is *bad* because L2CAP has to be reliable.
3569 * But we don't have any other choice. L2CAP doesn't
3570 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003572 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003573 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003575 if (!sock_queue_rcv_skb(sk, skb))
3576 goto done;
3577 break;
3578
3579 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 if (!sock_owned_by_user(sk)) {
3581 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003582 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003583 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003584 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003585 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003586
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003587 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003588
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003589 case L2CAP_MODE_STREAMING:
3590 control = get_unaligned_le16(skb->data);
3591 skb_pull(skb, 2);
3592 len = skb->len;
3593
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003594 if (l2cap_check_fcs(pi, skb))
3595 goto drop;
3596
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003597 if (__is_sar_start(control))
3598 len -= 2;
3599
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003600 if (pi->fcs == L2CAP_FCS_CRC16)
3601 len -= 2;
3602
Nathan Holstein51893f82010-06-09 15:46:25 -04003603 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003604 goto drop;
3605
3606 tx_seq = __get_txseq(control);
3607
3608 if (pi->expected_tx_seq == tx_seq)
3609 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3610 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003611 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003612
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003613 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003614
3615 goto done;
3616
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003617 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003618 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003619 break;
3620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621
3622drop:
3623 kfree_skb(skb);
3624
3625done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003626 if (sk)
3627 bh_unlock_sock(sk);
3628
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 return 0;
3630}
3631
Al Viro8e036fc2007-07-29 00:16:36 -07003632static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633{
3634 struct sock *sk;
3635
3636 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3637 if (!sk)
3638 goto drop;
3639
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003640 bh_lock_sock(sk);
3641
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 BT_DBG("sk %p, len %d", sk, skb->len);
3643
3644 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3645 goto drop;
3646
3647 if (l2cap_pi(sk)->imtu < skb->len)
3648 goto drop;
3649
3650 if (!sock_queue_rcv_skb(sk, skb))
3651 goto done;
3652
3653drop:
3654 kfree_skb(skb);
3655
3656done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003657 if (sk)
3658 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 return 0;
3660}
3661
3662static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3663{
3664 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003665 u16 cid, len;
3666 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667
3668 skb_pull(skb, L2CAP_HDR_SIZE);
3669 cid = __le16_to_cpu(lh->cid);
3670 len = __le16_to_cpu(lh->len);
3671
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003672 if (len != skb->len) {
3673 kfree_skb(skb);
3674 return;
3675 }
3676
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3678
3679 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003680 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 l2cap_sig_channel(conn, skb);
3682 break;
3683
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003684 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003685 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 skb_pull(skb, 2);
3687 l2cap_conless_channel(conn, psm, skb);
3688 break;
3689
3690 default:
3691 l2cap_data_channel(conn, cid, skb);
3692 break;
3693 }
3694}
3695
3696/* ---- L2CAP interface with lower layer (HCI) ---- */
3697
3698static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3699{
3700 int exact = 0, lm1 = 0, lm2 = 0;
3701 register struct sock *sk;
3702 struct hlist_node *node;
3703
3704 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003705 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706
3707 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3708
3709 /* Find listening sockets and check their link_mode */
3710 read_lock(&l2cap_sk_list.lock);
3711 sk_for_each(sk, node, &l2cap_sk_list.head) {
3712 if (sk->sk_state != BT_LISTEN)
3713 continue;
3714
3715 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003716 lm1 |= HCI_LM_ACCEPT;
3717 if (l2cap_pi(sk)->role_switch)
3718 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003720 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3721 lm2 |= HCI_LM_ACCEPT;
3722 if (l2cap_pi(sk)->role_switch)
3723 lm2 |= HCI_LM_MASTER;
3724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 }
3726 read_unlock(&l2cap_sk_list.lock);
3727
3728 return exact ? lm1 : lm2;
3729}
3730
3731static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3732{
Marcel Holtmann01394182006-07-03 10:02:46 +02003733 struct l2cap_conn *conn;
3734
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3736
3737 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003738 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
3740 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741 conn = l2cap_conn_add(hcon, status);
3742 if (conn)
3743 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003744 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 l2cap_conn_del(hcon, bt_err(status));
3746
3747 return 0;
3748}
3749
Marcel Holtmann2950f212009-02-12 14:02:50 +01003750static int l2cap_disconn_ind(struct hci_conn *hcon)
3751{
3752 struct l2cap_conn *conn = hcon->l2cap_data;
3753
3754 BT_DBG("hcon %p", hcon);
3755
3756 if (hcon->type != ACL_LINK || !conn)
3757 return 0x13;
3758
3759 return conn->disc_reason;
3760}
3761
3762static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763{
3764 BT_DBG("hcon %p reason %d", hcon, reason);
3765
3766 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003767 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
3769 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003770
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 return 0;
3772}
3773
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003774static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3775{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003776 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003777 return;
3778
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003779 if (encrypt == 0x00) {
3780 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3781 l2cap_sock_clear_timer(sk);
3782 l2cap_sock_set_timer(sk, HZ * 5);
3783 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3784 __l2cap_sock_close(sk, ECONNREFUSED);
3785 } else {
3786 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3787 l2cap_sock_clear_timer(sk);
3788 }
3789}
3790
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003791static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792{
3793 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003794 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Marcel Holtmann01394182006-07-03 10:02:46 +02003797 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003799
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 l = &conn->chan_list;
3801
3802 BT_DBG("conn %p", conn);
3803
3804 read_lock(&l->lock);
3805
3806 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3807 bh_lock_sock(sk);
3808
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003809 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3810 bh_unlock_sock(sk);
3811 continue;
3812 }
3813
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003814 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003815 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003816 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003817 bh_unlock_sock(sk);
3818 continue;
3819 }
3820
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003821 if (sk->sk_state == BT_CONNECT) {
3822 if (!status) {
3823 struct l2cap_conn_req req;
3824 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3825 req.psm = l2cap_pi(sk)->psm;
3826
3827 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003828 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003829
3830 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3831 L2CAP_CONN_REQ, sizeof(req), &req);
3832 } else {
3833 l2cap_sock_clear_timer(sk);
3834 l2cap_sock_set_timer(sk, HZ / 10);
3835 }
3836 } else if (sk->sk_state == BT_CONNECT2) {
3837 struct l2cap_conn_rsp rsp;
3838 __u16 result;
3839
3840 if (!status) {
3841 sk->sk_state = BT_CONFIG;
3842 result = L2CAP_CR_SUCCESS;
3843 } else {
3844 sk->sk_state = BT_DISCONN;
3845 l2cap_sock_set_timer(sk, HZ / 10);
3846 result = L2CAP_CR_SEC_BLOCK;
3847 }
3848
3849 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3850 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3851 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003852 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003853 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3854 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 }
3856
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 bh_unlock_sock(sk);
3858 }
3859
3860 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003861
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 return 0;
3863}
3864
3865static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3866{
3867 struct l2cap_conn *conn = hcon->l2cap_data;
3868
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003869 if (!conn)
3870 conn = l2cap_conn_add(hcon, 0);
3871
3872 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 goto drop;
3874
3875 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3876
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003877 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003879 struct sock *sk;
3880 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 int len;
3882
3883 if (conn->rx_len) {
3884 BT_ERR("Unexpected start frame (len %d)", skb->len);
3885 kfree_skb(conn->rx_skb);
3886 conn->rx_skb = NULL;
3887 conn->rx_len = 0;
3888 l2cap_conn_unreliable(conn, ECOMM);
3889 }
3890
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003891 /* Start fragment always begin with Basic L2CAP header */
3892 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 BT_ERR("Frame is too short (len %d)", skb->len);
3894 l2cap_conn_unreliable(conn, ECOMM);
3895 goto drop;
3896 }
3897
3898 hdr = (struct l2cap_hdr *) skb->data;
3899 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003900 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901
3902 if (len == skb->len) {
3903 /* Complete frame received */
3904 l2cap_recv_frame(conn, skb);
3905 return 0;
3906 }
3907
3908 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3909
3910 if (skb->len > len) {
3911 BT_ERR("Frame is too long (len %d, expected len %d)",
3912 skb->len, len);
3913 l2cap_conn_unreliable(conn, ECOMM);
3914 goto drop;
3915 }
3916
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003917 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3918
3919 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3920 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3921 len, l2cap_pi(sk)->imtu);
3922 bh_unlock_sock(sk);
3923 l2cap_conn_unreliable(conn, ECOMM);
3924 goto drop;
3925 }
3926
3927 if (sk)
3928 bh_unlock_sock(sk);
3929
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003931 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3932 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 goto drop;
3934
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003935 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003936 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 conn->rx_len = len - skb->len;
3938 } else {
3939 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3940
3941 if (!conn->rx_len) {
3942 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3943 l2cap_conn_unreliable(conn, ECOMM);
3944 goto drop;
3945 }
3946
3947 if (skb->len > conn->rx_len) {
3948 BT_ERR("Fragment is too long (len %d, expected %d)",
3949 skb->len, conn->rx_len);
3950 kfree_skb(conn->rx_skb);
3951 conn->rx_skb = NULL;
3952 conn->rx_len = 0;
3953 l2cap_conn_unreliable(conn, ECOMM);
3954 goto drop;
3955 }
3956
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003957 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003958 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 conn->rx_len -= skb->len;
3960
3961 if (!conn->rx_len) {
3962 /* Complete frame received */
3963 l2cap_recv_frame(conn, conn->rx_skb);
3964 conn->rx_skb = NULL;
3965 }
3966 }
3967
3968drop:
3969 kfree_skb(skb);
3970 return 0;
3971}
3972
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003973static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974{
3975 struct sock *sk;
3976 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
3978 read_lock_bh(&l2cap_sk_list.lock);
3979
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003980 sk_for_each(sk, node, &l2cap_sk_list.head) {
3981 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003983 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
3984 batostr(&bt_sk(sk)->src),
3985 batostr(&bt_sk(sk)->dst),
3986 sk->sk_state, __le16_to_cpu(pi->psm),
3987 pi->scid, pi->dcid,
3988 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003992
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003993 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994}
3995
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003996static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3997{
3998 return single_open(file, l2cap_debugfs_show, inode->i_private);
3999}
4000
4001static const struct file_operations l2cap_debugfs_fops = {
4002 .open = l2cap_debugfs_open,
4003 .read = seq_read,
4004 .llseek = seq_lseek,
4005 .release = single_release,
4006};
4007
4008static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010static struct hci_proto l2cap_hci_proto = {
4011 .name = "L2CAP",
4012 .id = HCI_PROTO_L2CAP,
4013 .connect_ind = l2cap_connect_ind,
4014 .connect_cfm = l2cap_connect_cfm,
4015 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004016 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004017 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 .recv_acldata = l2cap_recv_acldata
4019};
4020
4021static int __init l2cap_init(void)
4022{
4023 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004024
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004025 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 if (err < 0)
4027 return err;
4028
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004029 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004030 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004031 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 goto error;
4033 }
4034
4035 err = hci_register_proto(&l2cap_hci_proto);
4036 if (err < 0) {
4037 BT_ERR("L2CAP protocol registration failed");
4038 bt_sock_unregister(BTPROTO_L2CAP);
4039 goto error;
4040 }
4041
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004042 if (bt_debugfs) {
4043 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4044 bt_debugfs, NULL, &l2cap_debugfs_fops);
4045 if (!l2cap_debugfs)
4046 BT_ERR("Failed to create L2CAP debug file");
4047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048
4049 BT_INFO("L2CAP ver %s", VERSION);
4050 BT_INFO("L2CAP socket layer initialized");
4051
4052 return 0;
4053
4054error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004055 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004056 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 return err;
4058}
4059
4060static void __exit l2cap_exit(void)
4061{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004062 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004064 flush_workqueue(_busy_wq);
4065 destroy_workqueue(_busy_wq);
4066
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4068 BT_ERR("L2CAP protocol unregistration failed");
4069
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004070 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071}
4072
4073void l2cap_load(void)
4074{
4075 /* Dummy function to trigger automatic L2CAP module loading by
4076 * other modules that use L2CAP sockets but don't use any other
4077 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078}
4079EXPORT_SYMBOL(l2cap_load);
4080
4081module_init(l2cap_init);
4082module_exit(l2cap_exit);
4083
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004084module_param(disable_ertm, bool, 0644);
4085MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004086
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004087MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4089MODULE_VERSION(VERSION);
4090MODULE_LICENSE("GPL");
4091MODULE_ALIAS("bt-proto-0");