blob: da9b3a44b0f09362a16d629e8b8d00dcd1c56188 [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. Padovanfd83ccd2011-02-04 03:20:52 -0200996void 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
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001012void 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. Padovanfd83ccd2011-02-04 03:20:52 -02001081int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001082{
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. Padovanfd83ccd2011-02-04 03:20:52 -02001221struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001222{
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
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001250struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251{
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. Padovanfd83ccd2011-02-04 03:20:52 -02001278struct 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. Padovanfd83ccd2011-02-04 03:20:52 -02001323int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001324{
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
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369static void l2cap_chan_ready(struct sock *sk)
1370{
1371 struct sock *parent = bt_sk(sk)->parent;
1372
1373 BT_DBG("sk %p, parent %p", sk, parent);
1374
1375 l2cap_pi(sk)->conf_state = 0;
1376 l2cap_sock_clear_timer(sk);
1377
1378 if (!parent) {
1379 /* Outgoing channel.
1380 * Wake up socket sleeping on connect.
1381 */
1382 sk->sk_state = BT_CONNECTED;
1383 sk->sk_state_change(sk);
1384 } else {
1385 /* Incoming channel.
1386 * Wake up socket sleeping on accept.
1387 */
1388 parent->sk_data_ready(parent, 0);
1389 }
1390}
1391
1392/* Copy frame to all raw sockets on that connection */
1393static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1394{
1395 struct l2cap_chan_list *l = &conn->chan_list;
1396 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001397 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399 BT_DBG("conn %p", conn);
1400
1401 read_lock(&l->lock);
1402 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1403 if (sk->sk_type != SOCK_RAW)
1404 continue;
1405
1406 /* Don't send frame to the socket it came from */
1407 if (skb->sk == sk)
1408 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001409 nskb = skb_clone(skb, GFP_ATOMIC);
1410 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 continue;
1412
1413 if (sock_queue_rcv_skb(sk, nskb))
1414 kfree_skb(nskb);
1415 }
1416 read_unlock(&l->lock);
1417}
1418
1419/* ---- L2CAP signalling commands ---- */
1420static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1421 u8 code, u8 ident, u16 dlen, void *data)
1422{
1423 struct sk_buff *skb, **frag;
1424 struct l2cap_cmd_hdr *cmd;
1425 struct l2cap_hdr *lh;
1426 int len, count;
1427
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001428 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1429 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
1431 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1432 count = min_t(unsigned int, conn->mtu, len);
1433
1434 skb = bt_skb_alloc(count, GFP_ATOMIC);
1435 if (!skb)
1436 return NULL;
1437
1438 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001439 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03001440 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
1442 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1443 cmd->code = code;
1444 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001445 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447 if (dlen) {
1448 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1449 memcpy(skb_put(skb, count), data, count);
1450 data += count;
1451 }
1452
1453 len -= skb->len;
1454
1455 /* Continuation fragments (no L2CAP header) */
1456 frag = &skb_shinfo(skb)->frag_list;
1457 while (len) {
1458 count = min_t(unsigned int, conn->mtu, len);
1459
1460 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1461 if (!*frag)
1462 goto fail;
1463
1464 memcpy(skb_put(*frag, count), data, count);
1465
1466 len -= count;
1467 data += count;
1468
1469 frag = &(*frag)->next;
1470 }
1471
1472 return skb;
1473
1474fail:
1475 kfree_skb(skb);
1476 return NULL;
1477}
1478
1479static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1480{
1481 struct l2cap_conf_opt *opt = *ptr;
1482 int len;
1483
1484 len = L2CAP_CONF_OPT_SIZE + opt->len;
1485 *ptr += len;
1486
1487 *type = opt->type;
1488 *olen = opt->len;
1489
1490 switch (opt->len) {
1491 case 1:
1492 *val = *((u8 *) opt->val);
1493 break;
1494
1495 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001496 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 break;
1498
1499 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001500 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 break;
1502
1503 default:
1504 *val = (unsigned long) opt->val;
1505 break;
1506 }
1507
1508 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1509 return len;
1510}
1511
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1513{
1514 struct l2cap_conf_opt *opt = *ptr;
1515
1516 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1517
1518 opt->type = type;
1519 opt->len = len;
1520
1521 switch (len) {
1522 case 1:
1523 *((u8 *) opt->val) = val;
1524 break;
1525
1526 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001527 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 break;
1529
1530 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001531 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 break;
1533
1534 default:
1535 memcpy(opt->val, (void *) val, len);
1536 break;
1537 }
1538
1539 *ptr += L2CAP_CONF_OPT_SIZE + len;
1540}
1541
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001542static void l2cap_ack_timeout(unsigned long arg)
1543{
1544 struct sock *sk = (void *) arg;
1545
1546 bh_lock_sock(sk);
1547 l2cap_send_ack(l2cap_pi(sk));
1548 bh_unlock_sock(sk);
1549}
1550
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001551static inline void l2cap_ertm_init(struct sock *sk)
1552{
1553 l2cap_pi(sk)->expected_ack_seq = 0;
1554 l2cap_pi(sk)->unacked_frames = 0;
1555 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001556 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001557 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001558
1559 setup_timer(&l2cap_pi(sk)->retrans_timer,
1560 l2cap_retrans_timeout, (unsigned long) sk);
1561 setup_timer(&l2cap_pi(sk)->monitor_timer,
1562 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001563 setup_timer(&l2cap_pi(sk)->ack_timer,
1564 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001565
1566 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001567 __skb_queue_head_init(BUSY_QUEUE(sk));
1568
1569 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001570
1571 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001572}
1573
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001574static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1575{
1576 switch (mode) {
1577 case L2CAP_MODE_STREAMING:
1578 case L2CAP_MODE_ERTM:
1579 if (l2cap_mode_supported(mode, remote_feat_mask))
1580 return mode;
1581 /* fall through */
1582 default:
1583 return L2CAP_MODE_BASIC;
1584 }
1585}
1586
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001587int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
1589 struct l2cap_pinfo *pi = l2cap_pi(sk);
1590 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001591 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 void *ptr = req->data;
1593
1594 BT_DBG("sk %p", sk);
1595
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001596 if (pi->num_conf_req || pi->num_conf_rsp)
1597 goto done;
1598
1599 switch (pi->mode) {
1600 case L2CAP_MODE_STREAMING:
1601 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001602 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001603 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001604
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001605 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001606 default:
1607 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1608 break;
1609 }
1610
1611done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001612 if (pi->imtu != L2CAP_DEFAULT_MTU)
1613 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1614
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001615 switch (pi->mode) {
1616 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001617 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1618 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1619 break;
1620
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001621 rfc.mode = L2CAP_MODE_BASIC;
1622 rfc.txwin_size = 0;
1623 rfc.max_transmit = 0;
1624 rfc.retrans_timeout = 0;
1625 rfc.monitor_timeout = 0;
1626 rfc.max_pdu_size = 0;
1627
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001628 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1629 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001630 break;
1631
1632 case L2CAP_MODE_ERTM:
1633 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001634 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001635 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001636 rfc.retrans_timeout = 0;
1637 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001638 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001639 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001640 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001641
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001642 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1643 (unsigned long) &rfc);
1644
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001645 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1646 break;
1647
1648 if (pi->fcs == L2CAP_FCS_NONE ||
1649 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1650 pi->fcs = L2CAP_FCS_NONE;
1651 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1652 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001653 break;
1654
1655 case L2CAP_MODE_STREAMING:
1656 rfc.mode = L2CAP_MODE_STREAMING;
1657 rfc.txwin_size = 0;
1658 rfc.max_transmit = 0;
1659 rfc.retrans_timeout = 0;
1660 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001661 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001662 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001663 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001664
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001665 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1666 (unsigned long) &rfc);
1667
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001668 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1669 break;
1670
1671 if (pi->fcs == L2CAP_FCS_NONE ||
1672 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1673 pi->fcs = L2CAP_FCS_NONE;
1674 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1675 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001676 break;
1677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
1679 /* FIXME: Need actual value of the flush timeout */
1680 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
1681 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
1682
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001683 req->dcid = cpu_to_le16(pi->dcid);
1684 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
1686 return ptr - data;
1687}
1688
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001689static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690{
1691 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001692 struct l2cap_conf_rsp *rsp = data;
1693 void *ptr = rsp->data;
1694 void *req = pi->conf_req;
1695 int len = pi->conf_len;
1696 int type, hint, olen;
1697 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001698 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001699 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001700 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001702 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001703
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001704 while (len >= L2CAP_CONF_OPT_SIZE) {
1705 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001707 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001708 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001709
1710 switch (type) {
1711 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001712 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001713 break;
1714
1715 case L2CAP_CONF_FLUSH_TO:
1716 pi->flush_to = val;
1717 break;
1718
1719 case L2CAP_CONF_QOS:
1720 break;
1721
Marcel Holtmann6464f352007-10-20 13:39:51 +02001722 case L2CAP_CONF_RFC:
1723 if (olen == sizeof(rfc))
1724 memcpy(&rfc, (void *) val, olen);
1725 break;
1726
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001727 case L2CAP_CONF_FCS:
1728 if (val == L2CAP_FCS_NONE)
1729 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1730
1731 break;
1732
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001733 default:
1734 if (hint)
1735 break;
1736
1737 result = L2CAP_CONF_UNKNOWN;
1738 *((u8 *) ptr++) = type;
1739 break;
1740 }
1741 }
1742
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001743 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001744 goto done;
1745
1746 switch (pi->mode) {
1747 case L2CAP_MODE_STREAMING:
1748 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001749 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1750 pi->mode = l2cap_select_mode(rfc.mode,
1751 pi->conn->feat_mask);
1752 break;
1753 }
1754
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001755 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001756 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001757
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001758 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001759 }
1760
1761done:
1762 if (pi->mode != rfc.mode) {
1763 result = L2CAP_CONF_UNACCEPT;
1764 rfc.mode = pi->mode;
1765
1766 if (pi->num_conf_rsp == 1)
1767 return -ECONNREFUSED;
1768
1769 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1770 sizeof(rfc), (unsigned long) &rfc);
1771 }
1772
1773
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001774 if (result == L2CAP_CONF_SUCCESS) {
1775 /* Configure output options and let the other side know
1776 * which ones we don't like. */
1777
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1779 result = L2CAP_CONF_UNACCEPT;
1780 else {
1781 pi->omtu = mtu;
1782 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1783 }
1784 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001785
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001786 switch (rfc.mode) {
1787 case L2CAP_MODE_BASIC:
1788 pi->fcs = L2CAP_FCS_NONE;
1789 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1790 break;
1791
1792 case L2CAP_MODE_ERTM:
1793 pi->remote_tx_win = rfc.txwin_size;
1794 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001795
1796 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1797 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001798
1799 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001801 rfc.retrans_timeout =
1802 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1803 rfc.monitor_timeout =
1804 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001805
1806 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001807
1808 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1809 sizeof(rfc), (unsigned long) &rfc);
1810
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001811 break;
1812
1813 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001814 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1815 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001816
1817 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001818
1819 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001820
1821 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1822 sizeof(rfc), (unsigned long) &rfc);
1823
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001824 break;
1825
1826 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001827 result = L2CAP_CONF_UNACCEPT;
1828
1829 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001830 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001831 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001832
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833 if (result == L2CAP_CONF_SUCCESS)
1834 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1835 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001836 rsp->scid = cpu_to_le16(pi->dcid);
1837 rsp->result = cpu_to_le16(result);
1838 rsp->flags = cpu_to_le16(0x0000);
1839
1840 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841}
1842
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001843static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1844{
1845 struct l2cap_pinfo *pi = l2cap_pi(sk);
1846 struct l2cap_conf_req *req = data;
1847 void *ptr = req->data;
1848 int type, olen;
1849 unsigned long val;
1850 struct l2cap_conf_rfc rfc;
1851
1852 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1853
1854 while (len >= L2CAP_CONF_OPT_SIZE) {
1855 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1856
1857 switch (type) {
1858 case L2CAP_CONF_MTU:
1859 if (val < L2CAP_DEFAULT_MIN_MTU) {
1860 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001861 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001862 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001863 pi->imtu = val;
1864 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865 break;
1866
1867 case L2CAP_CONF_FLUSH_TO:
1868 pi->flush_to = val;
1869 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1870 2, pi->flush_to);
1871 break;
1872
1873 case L2CAP_CONF_RFC:
1874 if (olen == sizeof(rfc))
1875 memcpy(&rfc, (void *)val, olen);
1876
1877 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1878 rfc.mode != pi->mode)
1879 return -ECONNREFUSED;
1880
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001881 pi->fcs = 0;
1882
1883 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1884 sizeof(rfc), (unsigned long) &rfc);
1885 break;
1886 }
1887 }
1888
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001889 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1890 return -ECONNREFUSED;
1891
1892 pi->mode = rfc.mode;
1893
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001894 if (*result == L2CAP_CONF_SUCCESS) {
1895 switch (rfc.mode) {
1896 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001897 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1898 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001899 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001900 break;
1901 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001902 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001903 }
1904 }
1905
1906 req->dcid = cpu_to_le16(pi->dcid);
1907 req->flags = cpu_to_le16(0x0000);
1908
1909 return ptr - data;
1910}
1911
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001912static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913{
1914 struct l2cap_conf_rsp *rsp = data;
1915 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001917 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001919 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001920 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001921 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
1923 return ptr - data;
1924}
1925
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001926static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1927{
1928 struct l2cap_pinfo *pi = l2cap_pi(sk);
1929 int type, olen;
1930 unsigned long val;
1931 struct l2cap_conf_rfc rfc;
1932
1933 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1934
1935 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1936 return;
1937
1938 while (len >= L2CAP_CONF_OPT_SIZE) {
1939 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1940
1941 switch (type) {
1942 case L2CAP_CONF_RFC:
1943 if (olen == sizeof(rfc))
1944 memcpy(&rfc, (void *)val, olen);
1945 goto done;
1946 }
1947 }
1948
1949done:
1950 switch (rfc.mode) {
1951 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001952 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1953 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001954 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1955 break;
1956 case L2CAP_MODE_STREAMING:
1957 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1958 }
1959}
1960
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001961static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1962{
1963 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1964
1965 if (rej->reason != 0x0000)
1966 return 0;
1967
1968 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1969 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001970 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001971
1972 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001973 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001974
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001975 l2cap_conn_start(conn);
1976 }
1977
1978 return 0;
1979}
1980
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1982{
1983 struct l2cap_chan_list *list = &conn->chan_list;
1984 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1985 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001986 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001987 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
1989 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001990 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
1992 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
1993
1994 /* Check if we have socket listening on psm */
1995 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
1996 if (!parent) {
1997 result = L2CAP_CR_BAD_PSM;
1998 goto sendresp;
1999 }
2000
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002001 bh_lock_sock(parent);
2002
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002003 /* Check if the ACL is secure enough (if not SDP) */
2004 if (psm != cpu_to_le16(0x0001) &&
2005 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002006 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002007 result = L2CAP_CR_SEC_BLOCK;
2008 goto response;
2009 }
2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 result = L2CAP_CR_NO_MEM;
2012
2013 /* Check for backlog size */
2014 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002015 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 goto response;
2017 }
2018
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002019 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 if (!sk)
2021 goto response;
2022
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002023 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
2025 /* Check if we already have channel with that dcid */
2026 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002027 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 sock_set_flag(sk, SOCK_ZAPPED);
2029 l2cap_sock_kill(sk);
2030 goto response;
2031 }
2032
2033 hci_conn_hold(conn->hcon);
2034
2035 l2cap_sock_init(sk, parent);
2036 bacpy(&bt_sk(sk)->src, conn->src);
2037 bacpy(&bt_sk(sk)->dst, conn->dst);
2038 l2cap_pi(sk)->psm = psm;
2039 l2cap_pi(sk)->dcid = scid;
2040
2041 __l2cap_chan_add(conn, sk, parent);
2042 dcid = l2cap_pi(sk)->scid;
2043
2044 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2045
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 l2cap_pi(sk)->ident = cmd->ident;
2047
Marcel Holtmann984947d2009-02-06 23:35:19 +01002048 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002049 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002050 if (bt_sk(sk)->defer_setup) {
2051 sk->sk_state = BT_CONNECT2;
2052 result = L2CAP_CR_PEND;
2053 status = L2CAP_CS_AUTHOR_PEND;
2054 parent->sk_data_ready(parent, 0);
2055 } else {
2056 sk->sk_state = BT_CONFIG;
2057 result = L2CAP_CR_SUCCESS;
2058 status = L2CAP_CS_NO_INFO;
2059 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002060 } else {
2061 sk->sk_state = BT_CONNECT2;
2062 result = L2CAP_CR_PEND;
2063 status = L2CAP_CS_AUTHEN_PEND;
2064 }
2065 } else {
2066 sk->sk_state = BT_CONNECT2;
2067 result = L2CAP_CR_PEND;
2068 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 }
2070
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002071 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
2073response:
2074 bh_unlock_sock(parent);
2075
2076sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002077 rsp.scid = cpu_to_le16(scid);
2078 rsp.dcid = cpu_to_le16(dcid);
2079 rsp.result = cpu_to_le16(result);
2080 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002082
2083 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2084 struct l2cap_info_req info;
2085 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2086
2087 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2088 conn->info_ident = l2cap_get_ident(conn);
2089
2090 mod_timer(&conn->info_timer, jiffies +
2091 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2092
2093 l2cap_send_cmd(conn, conn->info_ident,
2094 L2CAP_INFO_REQ, sizeof(info), &info);
2095 }
2096
Nathan Holsteind793fe82010-10-15 11:54:02 -04002097 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002098 result == L2CAP_CR_SUCCESS) {
2099 u8 buf[128];
2100 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2101 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2102 l2cap_build_conf_req(sk, buf), buf);
2103 l2cap_pi(sk)->num_conf_req++;
2104 }
2105
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 return 0;
2107}
2108
2109static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2110{
2111 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2112 u16 scid, dcid, result, status;
2113 struct sock *sk;
2114 u8 req[128];
2115
2116 scid = __le16_to_cpu(rsp->scid);
2117 dcid = __le16_to_cpu(rsp->dcid);
2118 result = __le16_to_cpu(rsp->result);
2119 status = __le16_to_cpu(rsp->status);
2120
2121 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2122
2123 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002124 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2125 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002126 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002128 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2129 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002130 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 }
2132
2133 switch (result) {
2134 case L2CAP_CR_SUCCESS:
2135 sk->sk_state = BT_CONFIG;
2136 l2cap_pi(sk)->ident = 0;
2137 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002138 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2139
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002140 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2141 break;
2142
2143 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2144
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2146 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002147 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 break;
2149
2150 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002151 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 break;
2153
2154 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002155 /* don't delete l2cap channel if sk is owned by user */
2156 if (sock_owned_by_user(sk)) {
2157 sk->sk_state = BT_DISCONN;
2158 l2cap_sock_clear_timer(sk);
2159 l2cap_sock_set_timer(sk, HZ / 5);
2160 break;
2161 }
2162
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 l2cap_chan_del(sk, ECONNREFUSED);
2164 break;
2165 }
2166
2167 bh_unlock_sock(sk);
2168 return 0;
2169}
2170
Mat Martineau8c462b62010-08-24 15:35:42 -07002171static inline void set_default_fcs(struct l2cap_pinfo *pi)
2172{
2173 /* FCS is enabled only in ERTM or streaming mode, if one or both
2174 * sides request it.
2175 */
2176 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2177 pi->fcs = L2CAP_FCS_NONE;
2178 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2179 pi->fcs = L2CAP_FCS_CRC16;
2180}
2181
Al Viro88219a02007-07-29 00:17:25 -07002182static 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 -07002183{
2184 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2185 u16 dcid, flags;
2186 u8 rsp[64];
2187 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002188 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
2190 dcid = __le16_to_cpu(req->dcid);
2191 flags = __le16_to_cpu(req->flags);
2192
2193 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2194
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002195 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2196 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 return -ENOENT;
2198
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002199 if (sk->sk_state != BT_CONFIG) {
2200 struct l2cap_cmd_rej rej;
2201
2202 rej.reason = cpu_to_le16(0x0002);
2203 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2204 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002205 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002206 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002207
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002208 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002209 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002210 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2211 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2212 l2cap_build_conf_rsp(sk, rsp,
2213 L2CAP_CONF_REJECT, flags), rsp);
2214 goto unlock;
2215 }
2216
2217 /* Store config. */
2218 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2219 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
2221 if (flags & 0x0001) {
2222 /* Incomplete config. Send empty response. */
2223 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002224 l2cap_build_conf_rsp(sk, rsp,
2225 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 goto unlock;
2227 }
2228
2229 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002230 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002231 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002232 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002236 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002237 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002238
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002239 /* Reset config buffer. */
2240 l2cap_pi(sk)->conf_len = 0;
2241
Marcel Holtmann876d9482007-10-20 13:35:42 +02002242 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2243 goto unlock;
2244
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002246 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002247
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002249
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002250 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002251 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002252 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002253 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2254 l2cap_ertm_init(sk);
2255
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002257 goto unlock;
2258 }
2259
2260 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002261 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002262 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002264 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002265 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 }
2267
2268unlock:
2269 bh_unlock_sock(sk);
2270 return 0;
2271}
2272
2273static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2274{
2275 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2276 u16 scid, flags, result;
2277 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002278 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
2280 scid = __le16_to_cpu(rsp->scid);
2281 flags = __le16_to_cpu(rsp->flags);
2282 result = __le16_to_cpu(rsp->result);
2283
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002284 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2285 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002287 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2288 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 return 0;
2290
2291 switch (result) {
2292 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002293 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 break;
2295
2296 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002297 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002298 char req[64];
2299
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002300 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002301 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002302 goto done;
2303 }
2304
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002305 /* throw out any old stored conf requests */
2306 result = L2CAP_CONF_SUCCESS;
2307 len = l2cap_parse_conf_rsp(sk, rsp->data,
2308 len, req, &result);
2309 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002310 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002311 goto done;
2312 }
2313
2314 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2315 L2CAP_CONF_REQ, len, req);
2316 l2cap_pi(sk)->num_conf_req++;
2317 if (result != L2CAP_CONF_SUCCESS)
2318 goto done;
2319 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 }
2321
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002322 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002323 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002325 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 goto done;
2327 }
2328
2329 if (flags & 0x01)
2330 goto done;
2331
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2333
2334 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002335 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002338 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002339 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002340 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002341 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2342 l2cap_ertm_init(sk);
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 l2cap_chan_ready(sk);
2345 }
2346
2347done:
2348 bh_unlock_sock(sk);
2349 return 0;
2350}
2351
2352static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2353{
2354 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2355 struct l2cap_disconn_rsp rsp;
2356 u16 dcid, scid;
2357 struct sock *sk;
2358
2359 scid = __le16_to_cpu(req->scid);
2360 dcid = __le16_to_cpu(req->dcid);
2361
2362 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2363
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002364 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2365 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 return 0;
2367
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002368 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2369 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2371
2372 sk->sk_shutdown = SHUTDOWN_MASK;
2373
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002374 /* don't delete l2cap channel if sk is owned by user */
2375 if (sock_owned_by_user(sk)) {
2376 sk->sk_state = BT_DISCONN;
2377 l2cap_sock_clear_timer(sk);
2378 l2cap_sock_set_timer(sk, HZ / 5);
2379 bh_unlock_sock(sk);
2380 return 0;
2381 }
2382
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 l2cap_chan_del(sk, ECONNRESET);
2384 bh_unlock_sock(sk);
2385
2386 l2cap_sock_kill(sk);
2387 return 0;
2388}
2389
2390static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2391{
2392 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2393 u16 dcid, scid;
2394 struct sock *sk;
2395
2396 scid = __le16_to_cpu(rsp->scid);
2397 dcid = __le16_to_cpu(rsp->dcid);
2398
2399 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2400
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002401 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2402 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 return 0;
2404
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002405 /* don't delete l2cap channel if sk is owned by user */
2406 if (sock_owned_by_user(sk)) {
2407 sk->sk_state = BT_DISCONN;
2408 l2cap_sock_clear_timer(sk);
2409 l2cap_sock_set_timer(sk, HZ / 5);
2410 bh_unlock_sock(sk);
2411 return 0;
2412 }
2413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 l2cap_chan_del(sk, 0);
2415 bh_unlock_sock(sk);
2416
2417 l2cap_sock_kill(sk);
2418 return 0;
2419}
2420
2421static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2422{
2423 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 u16 type;
2425
2426 type = __le16_to_cpu(req->type);
2427
2428 BT_DBG("type 0x%4.4x", type);
2429
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002430 if (type == L2CAP_IT_FEAT_MASK) {
2431 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002432 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002433 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2434 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2435 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002436 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002437 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2438 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002439 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002440 l2cap_send_cmd(conn, cmd->ident,
2441 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002442 } else if (type == L2CAP_IT_FIXED_CHAN) {
2443 u8 buf[12];
2444 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2445 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2446 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2447 memcpy(buf + 4, l2cap_fixed_chan, 8);
2448 l2cap_send_cmd(conn, cmd->ident,
2449 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002450 } else {
2451 struct l2cap_info_rsp rsp;
2452 rsp.type = cpu_to_le16(type);
2453 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2454 l2cap_send_cmd(conn, cmd->ident,
2455 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2456 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457
2458 return 0;
2459}
2460
2461static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2462{
2463 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2464 u16 type, result;
2465
2466 type = __le16_to_cpu(rsp->type);
2467 result = __le16_to_cpu(rsp->result);
2468
2469 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2470
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002471 del_timer(&conn->info_timer);
2472
Ville Tervoadb08ed2010-08-04 09:43:33 +03002473 if (result != L2CAP_IR_SUCCESS) {
2474 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2475 conn->info_ident = 0;
2476
2477 l2cap_conn_start(conn);
2478
2479 return 0;
2480 }
2481
Marcel Holtmann984947d2009-02-06 23:35:19 +01002482 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002483 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002484
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002485 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002486 struct l2cap_info_req req;
2487 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2488
2489 conn->info_ident = l2cap_get_ident(conn);
2490
2491 l2cap_send_cmd(conn, conn->info_ident,
2492 L2CAP_INFO_REQ, sizeof(req), &req);
2493 } else {
2494 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2495 conn->info_ident = 0;
2496
2497 l2cap_conn_start(conn);
2498 }
2499 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002500 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002501 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002502
2503 l2cap_conn_start(conn);
2504 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002505
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 return 0;
2507}
2508
2509static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
2510{
2511 u8 *data = skb->data;
2512 int len = skb->len;
2513 struct l2cap_cmd_hdr cmd;
2514 int err = 0;
2515
2516 l2cap_raw_recv(conn, skb);
2517
2518 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002519 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2521 data += L2CAP_CMD_HDR_SIZE;
2522 len -= L2CAP_CMD_HDR_SIZE;
2523
Al Viro88219a02007-07-29 00:17:25 -07002524 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
Al Viro88219a02007-07-29 00:17:25 -07002526 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 -07002527
Al Viro88219a02007-07-29 00:17:25 -07002528 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 BT_DBG("corrupted command");
2530 break;
2531 }
2532
2533 switch (cmd.code) {
2534 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002535 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 break;
2537
2538 case L2CAP_CONN_REQ:
2539 err = l2cap_connect_req(conn, &cmd, data);
2540 break;
2541
2542 case L2CAP_CONN_RSP:
2543 err = l2cap_connect_rsp(conn, &cmd, data);
2544 break;
2545
2546 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002547 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 break;
2549
2550 case L2CAP_CONF_RSP:
2551 err = l2cap_config_rsp(conn, &cmd, data);
2552 break;
2553
2554 case L2CAP_DISCONN_REQ:
2555 err = l2cap_disconnect_req(conn, &cmd, data);
2556 break;
2557
2558 case L2CAP_DISCONN_RSP:
2559 err = l2cap_disconnect_rsp(conn, &cmd, data);
2560 break;
2561
2562 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002563 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 break;
2565
2566 case L2CAP_ECHO_RSP:
2567 break;
2568
2569 case L2CAP_INFO_REQ:
2570 err = l2cap_information_req(conn, &cmd, data);
2571 break;
2572
2573 case L2CAP_INFO_RSP:
2574 err = l2cap_information_rsp(conn, &cmd, data);
2575 break;
2576
2577 default:
2578 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
2579 err = -EINVAL;
2580 break;
2581 }
2582
2583 if (err) {
2584 struct l2cap_cmd_rej rej;
2585 BT_DBG("error %d", err);
2586
2587 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002588 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2590 }
2591
Al Viro88219a02007-07-29 00:17:25 -07002592 data += cmd_len;
2593 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 }
2595
2596 kfree_skb(skb);
2597}
2598
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002599static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2600{
2601 u16 our_fcs, rcv_fcs;
2602 int hdr_size = L2CAP_HDR_SIZE + 2;
2603
2604 if (pi->fcs == L2CAP_FCS_CRC16) {
2605 skb_trim(skb, skb->len - 2);
2606 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2607 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2608
2609 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002610 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002611 }
2612 return 0;
2613}
2614
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002615static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2616{
2617 struct l2cap_pinfo *pi = l2cap_pi(sk);
2618 u16 control = 0;
2619
2620 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002621
2622 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2623
2624 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002625 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002626 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002627 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002628 }
2629
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002630 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2631 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002632
2633 l2cap_ertm_send(sk);
2634
2635 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2636 pi->frames_sent == 0) {
2637 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002638 l2cap_send_sframe(pi, control);
2639 }
2640}
2641
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002642static 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 -03002643{
2644 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002645 struct l2cap_pinfo *pi = l2cap_pi(sk);
2646 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002647
2648 bt_cb(skb)->tx_seq = tx_seq;
2649 bt_cb(skb)->sar = sar;
2650
2651 next_skb = skb_peek(SREJ_QUEUE(sk));
2652 if (!next_skb) {
2653 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002654 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002655 }
2656
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002657 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2658 if (tx_seq_offset < 0)
2659 tx_seq_offset += 64;
2660
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002661 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002662 if (bt_cb(next_skb)->tx_seq == tx_seq)
2663 return -EINVAL;
2664
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002665 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2666 pi->buffer_seq) % 64;
2667 if (next_tx_seq_offset < 0)
2668 next_tx_seq_offset += 64;
2669
2670 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002671 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002672 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002673 }
2674
2675 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2676 break;
2677
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002678 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002679
2680 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002681
2682 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002683}
2684
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002685static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2686{
2687 struct l2cap_pinfo *pi = l2cap_pi(sk);
2688 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002689 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002690
2691 switch (control & L2CAP_CTRL_SAR) {
2692 case L2CAP_SDU_UNSEGMENTED:
2693 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2694 goto drop;
2695
2696 err = sock_queue_rcv_skb(sk, skb);
2697 if (!err)
2698 return err;
2699
2700 break;
2701
2702 case L2CAP_SDU_START:
2703 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2704 goto drop;
2705
2706 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002707
2708 if (pi->sdu_len > pi->imtu)
2709 goto disconnect;
2710
2711 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002712 if (!pi->sdu)
2713 return -ENOMEM;
2714
2715 /* pull sdu_len bytes only after alloc, because of Local Busy
2716 * condition we have to be sure that this will be executed
2717 * only once, i.e., when alloc does not fail */
2718 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002719
2720 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2721
2722 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2723 pi->partial_sdu_len = skb->len;
2724 break;
2725
2726 case L2CAP_SDU_CONTINUE:
2727 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2728 goto disconnect;
2729
2730 if (!pi->sdu)
2731 goto disconnect;
2732
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002733 pi->partial_sdu_len += skb->len;
2734 if (pi->partial_sdu_len > pi->sdu_len)
2735 goto drop;
2736
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002737 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2738
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002739 break;
2740
2741 case L2CAP_SDU_END:
2742 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2743 goto disconnect;
2744
2745 if (!pi->sdu)
2746 goto disconnect;
2747
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002748 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002749 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002750
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002751 if (pi->partial_sdu_len > pi->imtu)
2752 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002753
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002754 if (pi->partial_sdu_len != pi->sdu_len)
2755 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002756
2757 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002758 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002759
2760 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002761 if (!_skb) {
2762 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2763 return -ENOMEM;
2764 }
2765
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002766 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002767 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002768 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002769 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2770 return err;
2771 }
2772
2773 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2774 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002775
2776 kfree_skb(pi->sdu);
2777 break;
2778 }
2779
2780 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002781 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002782
2783drop:
2784 kfree_skb(pi->sdu);
2785 pi->sdu = NULL;
2786
2787disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002788 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002789 kfree_skb(skb);
2790 return 0;
2791}
2792
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002793static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002794{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002795 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002796 struct sk_buff *skb;
2797 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002798 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002799
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002800 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2801 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2802 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2803 if (err < 0) {
2804 skb_queue_head(BUSY_QUEUE(sk), skb);
2805 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002806 }
2807
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002808 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002809 }
2810
2811 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2812 goto done;
2813
2814 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2815 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2816 l2cap_send_sframe(pi, control);
2817 l2cap_pi(sk)->retry_count = 1;
2818
2819 del_timer(&pi->retrans_timer);
2820 __mod_monitor_timer();
2821
2822 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2823
2824done:
2825 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2826 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2827
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002828 BT_DBG("sk %p, Exit local busy", sk);
2829
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002830 return 0;
2831}
2832
2833static void l2cap_busy_work(struct work_struct *work)
2834{
2835 DECLARE_WAITQUEUE(wait, current);
2836 struct l2cap_pinfo *pi =
2837 container_of(work, struct l2cap_pinfo, busy_work);
2838 struct sock *sk = (struct sock *)pi;
2839 int n_tries = 0, timeo = HZ/5, err;
2840 struct sk_buff *skb;
2841
2842 lock_sock(sk);
2843
2844 add_wait_queue(sk_sleep(sk), &wait);
2845 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2846 set_current_state(TASK_INTERRUPTIBLE);
2847
2848 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2849 err = -EBUSY;
2850 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2851 break;
2852 }
2853
2854 if (!timeo)
2855 timeo = HZ/5;
2856
2857 if (signal_pending(current)) {
2858 err = sock_intr_errno(timeo);
2859 break;
2860 }
2861
2862 release_sock(sk);
2863 timeo = schedule_timeout(timeo);
2864 lock_sock(sk);
2865
2866 err = sock_error(sk);
2867 if (err)
2868 break;
2869
2870 if (l2cap_try_push_rx_skb(sk) == 0)
2871 break;
2872 }
2873
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002874 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002875 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002876
2877 release_sock(sk);
2878}
2879
2880static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2881{
2882 struct l2cap_pinfo *pi = l2cap_pi(sk);
2883 int sctrl, err;
2884
2885 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2886 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2887 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002888 return l2cap_try_push_rx_skb(sk);
2889
2890
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002891 }
2892
2893 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2894 if (err >= 0) {
2895 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2896 return err;
2897 }
2898
2899 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002900 BT_DBG("sk %p, Enter local busy", sk);
2901
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002902 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
2903 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2904 __skb_queue_tail(BUSY_QUEUE(sk), skb);
2905
2906 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2907 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
2908 l2cap_send_sframe(pi, sctrl);
2909
2910 pi->conn_state |= L2CAP_CONN_RNR_SENT;
2911
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03002912 del_timer(&pi->ack_timer);
2913
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002914 queue_work(_busy_wq, &pi->busy_work);
2915
2916 return err;
2917}
2918
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002919static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002920{
2921 struct l2cap_pinfo *pi = l2cap_pi(sk);
2922 struct sk_buff *_skb;
2923 int err = -EINVAL;
2924
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925 /*
2926 * TODO: We have to notify the userland if some data is lost with the
2927 * Streaming Mode.
2928 */
2929
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002930 switch (control & L2CAP_CTRL_SAR) {
2931 case L2CAP_SDU_UNSEGMENTED:
2932 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2933 kfree_skb(pi->sdu);
2934 break;
2935 }
2936
2937 err = sock_queue_rcv_skb(sk, skb);
2938 if (!err)
2939 return 0;
2940
2941 break;
2942
2943 case L2CAP_SDU_START:
2944 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2945 kfree_skb(pi->sdu);
2946 break;
2947 }
2948
2949 pi->sdu_len = get_unaligned_le16(skb->data);
2950 skb_pull(skb, 2);
2951
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03002952 if (pi->sdu_len > pi->imtu) {
2953 err = -EMSGSIZE;
2954 break;
2955 }
2956
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002957 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
2958 if (!pi->sdu) {
2959 err = -ENOMEM;
2960 break;
2961 }
2962
2963 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2964
2965 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2966 pi->partial_sdu_len = skb->len;
2967 err = 0;
2968 break;
2969
2970 case L2CAP_SDU_CONTINUE:
2971 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2972 break;
2973
2974 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2975
2976 pi->partial_sdu_len += skb->len;
2977 if (pi->partial_sdu_len > pi->sdu_len)
2978 kfree_skb(pi->sdu);
2979 else
2980 err = 0;
2981
2982 break;
2983
2984 case L2CAP_SDU_END:
2985 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2986 break;
2987
2988 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2989
2990 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
2991 pi->partial_sdu_len += skb->len;
2992
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002993 if (pi->partial_sdu_len > pi->imtu)
2994 goto drop;
2995
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002996 if (pi->partial_sdu_len == pi->sdu_len) {
2997 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
2998 err = sock_queue_rcv_skb(sk, _skb);
2999 if (err < 0)
3000 kfree_skb(_skb);
3001 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003002 err = 0;
3003
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003004drop:
3005 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003006 break;
3007 }
3008
3009 kfree_skb(skb);
3010 return err;
3011}
3012
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003013static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3014{
3015 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003016 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003017
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003018 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003019 if (bt_cb(skb)->tx_seq != tx_seq)
3020 break;
3021
3022 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003023 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003024 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003025 l2cap_pi(sk)->buffer_seq_srej =
3026 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003027 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003028 }
3029}
3030
3031static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3032{
3033 struct l2cap_pinfo *pi = l2cap_pi(sk);
3034 struct srej_list *l, *tmp;
3035 u16 control;
3036
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003037 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003038 if (l->tx_seq == tx_seq) {
3039 list_del(&l->list);
3040 kfree(l);
3041 return;
3042 }
3043 control = L2CAP_SUPER_SELECT_REJECT;
3044 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3045 l2cap_send_sframe(pi, control);
3046 list_del(&l->list);
3047 list_add_tail(&l->list, SREJ_LIST(sk));
3048 }
3049}
3050
3051static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3052{
3053 struct l2cap_pinfo *pi = l2cap_pi(sk);
3054 struct srej_list *new;
3055 u16 control;
3056
3057 while (tx_seq != pi->expected_tx_seq) {
3058 control = L2CAP_SUPER_SELECT_REJECT;
3059 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3060 l2cap_send_sframe(pi, control);
3061
3062 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003063 new->tx_seq = pi->expected_tx_seq;
3064 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003065 list_add_tail(&new->list, SREJ_LIST(sk));
3066 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003067 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003068}
3069
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003070static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3071{
3072 struct l2cap_pinfo *pi = l2cap_pi(sk);
3073 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003074 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003075 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003076 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003077 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003078 int err = 0;
3079
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003080 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3081 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003082
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003083 if (L2CAP_CTRL_FINAL & rx_control &&
3084 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003085 del_timer(&pi->monitor_timer);
3086 if (pi->unacked_frames > 0)
3087 __mod_retrans_timer();
3088 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3089 }
3090
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003091 pi->expected_ack_seq = req_seq;
3092 l2cap_drop_acked_frames(sk);
3093
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003094 if (tx_seq == pi->expected_tx_seq)
3095 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003096
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003097 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3098 if (tx_seq_offset < 0)
3099 tx_seq_offset += 64;
3100
3101 /* invalid tx_seq */
3102 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003103 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003104 goto drop;
3105 }
3106
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003107 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3108 goto drop;
3109
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003110 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3111 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003112
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003113 first = list_first_entry(SREJ_LIST(sk),
3114 struct srej_list, list);
3115 if (tx_seq == first->tx_seq) {
3116 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3117 l2cap_check_srej_gap(sk, tx_seq);
3118
3119 list_del(&first->list);
3120 kfree(first);
3121
3122 if (list_empty(SREJ_LIST(sk))) {
3123 pi->buffer_seq = pi->buffer_seq_srej;
3124 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003125 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003126 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003127 }
3128 } else {
3129 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003130
3131 /* duplicated tx_seq */
3132 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3133 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003134
3135 list_for_each_entry(l, SREJ_LIST(sk), list) {
3136 if (l->tx_seq == tx_seq) {
3137 l2cap_resend_srejframe(sk, tx_seq);
3138 return 0;
3139 }
3140 }
3141 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003142 }
3143 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003144 expected_tx_seq_offset =
3145 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3146 if (expected_tx_seq_offset < 0)
3147 expected_tx_seq_offset += 64;
3148
3149 /* duplicated tx_seq */
3150 if (tx_seq_offset < expected_tx_seq_offset)
3151 goto drop;
3152
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003153 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003154
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003155 BT_DBG("sk %p, Enter SREJ", sk);
3156
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003157 INIT_LIST_HEAD(SREJ_LIST(sk));
3158 pi->buffer_seq_srej = pi->buffer_seq;
3159
3160 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003161 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003162 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3163
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003164 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3165
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003166 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003167
3168 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003169 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003170 return 0;
3171
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003172expected:
3173 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3174
3175 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003176 bt_cb(skb)->tx_seq = tx_seq;
3177 bt_cb(skb)->sar = sar;
3178 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003179 return 0;
3180 }
3181
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003182 err = l2cap_push_rx_skb(sk, skb, rx_control);
3183 if (err < 0)
3184 return 0;
3185
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003186 if (rx_control & L2CAP_CTRL_FINAL) {
3187 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3188 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003189 else
3190 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003191 }
3192
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003193 __mod_ack_timer();
3194
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003195 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3196 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003197 l2cap_send_ack(pi);
3198
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003199 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003200
3201drop:
3202 kfree_skb(skb);
3203 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003204}
3205
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003206static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003207{
3208 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003209
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003210 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3211 rx_control);
3212
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003213 pi->expected_ack_seq = __get_reqseq(rx_control);
3214 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003215
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003216 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003217 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003218 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3219 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3220 (pi->unacked_frames > 0))
3221 __mod_retrans_timer();
3222
3223 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3224 l2cap_send_srejtail(sk);
3225 } else {
3226 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003227 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003228
3229 } else if (rx_control & L2CAP_CTRL_FINAL) {
3230 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003231
3232 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3233 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003234 else
3235 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003236
3237 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003238 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3239 (pi->unacked_frames > 0))
3240 __mod_retrans_timer();
3241
3242 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003243 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003244 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003245 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003246 l2cap_ertm_send(sk);
3247 }
3248}
3249
3250static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3251{
3252 struct l2cap_pinfo *pi = l2cap_pi(sk);
3253 u8 tx_seq = __get_reqseq(rx_control);
3254
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003255 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3256
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003257 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3258
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003259 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003260 l2cap_drop_acked_frames(sk);
3261
3262 if (rx_control & L2CAP_CTRL_FINAL) {
3263 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3264 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003265 else
3266 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003267 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003268 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003269
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003270 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003271 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003272 }
3273}
3274static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3275{
3276 struct l2cap_pinfo *pi = l2cap_pi(sk);
3277 u8 tx_seq = __get_reqseq(rx_control);
3278
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003279 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3280
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003281 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3282
3283 if (rx_control & L2CAP_CTRL_POLL) {
3284 pi->expected_ack_seq = tx_seq;
3285 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003286
3287 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003288 l2cap_retransmit_one_frame(sk, tx_seq);
3289
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003290 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003291
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003292 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3293 pi->srej_save_reqseq = tx_seq;
3294 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3295 }
3296 } else if (rx_control & L2CAP_CTRL_FINAL) {
3297 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3298 pi->srej_save_reqseq == tx_seq)
3299 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3300 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003301 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003302 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003303 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003304 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3305 pi->srej_save_reqseq = tx_seq;
3306 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3307 }
3308 }
3309}
3310
3311static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3312{
3313 struct l2cap_pinfo *pi = l2cap_pi(sk);
3314 u8 tx_seq = __get_reqseq(rx_control);
3315
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003316 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3317
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003318 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3319 pi->expected_ack_seq = tx_seq;
3320 l2cap_drop_acked_frames(sk);
3321
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003322 if (rx_control & L2CAP_CTRL_POLL)
3323 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3324
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003325 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3326 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003327 if (rx_control & L2CAP_CTRL_POLL)
3328 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003329 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003330 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003331
3332 if (rx_control & L2CAP_CTRL_POLL)
3333 l2cap_send_srejtail(sk);
3334 else
3335 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003336}
3337
3338static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3339{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003340 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3341
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003342 if (L2CAP_CTRL_FINAL & rx_control &&
3343 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003344 del_timer(&l2cap_pi(sk)->monitor_timer);
3345 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003346 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003347 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003348 }
3349
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003350 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3351 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003352 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003353 break;
3354
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003355 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003356 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003357 break;
3358
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003359 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003360 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003361 break;
3362
3363 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003364 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003365 break;
3366 }
3367
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003368 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003369 return 0;
3370}
3371
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003372static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3373{
3374 struct l2cap_pinfo *pi = l2cap_pi(sk);
3375 u16 control;
3376 u8 req_seq;
3377 int len, next_tx_seq_offset, req_seq_offset;
3378
3379 control = get_unaligned_le16(skb->data);
3380 skb_pull(skb, 2);
3381 len = skb->len;
3382
3383 /*
3384 * We can just drop the corrupted I-frame here.
3385 * Receiver will miss it and start proper recovery
3386 * procedures and ask retransmission.
3387 */
3388 if (l2cap_check_fcs(pi, skb))
3389 goto drop;
3390
3391 if (__is_sar_start(control) && __is_iframe(control))
3392 len -= 2;
3393
3394 if (pi->fcs == L2CAP_FCS_CRC16)
3395 len -= 2;
3396
3397 if (len > pi->mps) {
3398 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3399 goto drop;
3400 }
3401
3402 req_seq = __get_reqseq(control);
3403 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3404 if (req_seq_offset < 0)
3405 req_seq_offset += 64;
3406
3407 next_tx_seq_offset =
3408 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3409 if (next_tx_seq_offset < 0)
3410 next_tx_seq_offset += 64;
3411
3412 /* check for invalid req-seq */
3413 if (req_seq_offset > next_tx_seq_offset) {
3414 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3415 goto drop;
3416 }
3417
3418 if (__is_iframe(control)) {
3419 if (len < 0) {
3420 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3421 goto drop;
3422 }
3423
3424 l2cap_data_channel_iframe(sk, control, skb);
3425 } else {
3426 if (len != 0) {
3427 BT_ERR("%d", len);
3428 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3429 goto drop;
3430 }
3431
3432 l2cap_data_channel_sframe(sk, control, skb);
3433 }
3434
3435 return 0;
3436
3437drop:
3438 kfree_skb(skb);
3439 return 0;
3440}
3441
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3443{
3444 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003445 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003446 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003447 u8 tx_seq;
3448 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449
3450 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3451 if (!sk) {
3452 BT_DBG("unknown cid 0x%4.4x", cid);
3453 goto drop;
3454 }
3455
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003456 pi = l2cap_pi(sk);
3457
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 BT_DBG("sk %p, len %d", sk, skb->len);
3459
3460 if (sk->sk_state != BT_CONNECTED)
3461 goto drop;
3462
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003463 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003464 case L2CAP_MODE_BASIC:
3465 /* If socket recv buffers overflows we drop data here
3466 * which is *bad* because L2CAP has to be reliable.
3467 * But we don't have any other choice. L2CAP doesn't
3468 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003470 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003471 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003473 if (!sock_queue_rcv_skb(sk, skb))
3474 goto done;
3475 break;
3476
3477 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003478 if (!sock_owned_by_user(sk)) {
3479 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003480 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003481 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003482 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003483 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003484
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003485 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003486
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003487 case L2CAP_MODE_STREAMING:
3488 control = get_unaligned_le16(skb->data);
3489 skb_pull(skb, 2);
3490 len = skb->len;
3491
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003492 if (l2cap_check_fcs(pi, skb))
3493 goto drop;
3494
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003495 if (__is_sar_start(control))
3496 len -= 2;
3497
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003498 if (pi->fcs == L2CAP_FCS_CRC16)
3499 len -= 2;
3500
Nathan Holstein51893f82010-06-09 15:46:25 -04003501 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003502 goto drop;
3503
3504 tx_seq = __get_txseq(control);
3505
3506 if (pi->expected_tx_seq == tx_seq)
3507 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3508 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003509 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003510
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003511 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003512
3513 goto done;
3514
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003515 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003516 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 break;
3518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519
3520drop:
3521 kfree_skb(skb);
3522
3523done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003524 if (sk)
3525 bh_unlock_sock(sk);
3526
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 return 0;
3528}
3529
Al Viro8e036fc2007-07-29 00:16:36 -07003530static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531{
3532 struct sock *sk;
3533
3534 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3535 if (!sk)
3536 goto drop;
3537
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003538 bh_lock_sock(sk);
3539
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 BT_DBG("sk %p, len %d", sk, skb->len);
3541
3542 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3543 goto drop;
3544
3545 if (l2cap_pi(sk)->imtu < skb->len)
3546 goto drop;
3547
3548 if (!sock_queue_rcv_skb(sk, skb))
3549 goto done;
3550
3551drop:
3552 kfree_skb(skb);
3553
3554done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003555 if (sk)
3556 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 return 0;
3558}
3559
3560static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3561{
3562 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003563 u16 cid, len;
3564 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565
3566 skb_pull(skb, L2CAP_HDR_SIZE);
3567 cid = __le16_to_cpu(lh->cid);
3568 len = __le16_to_cpu(lh->len);
3569
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003570 if (len != skb->len) {
3571 kfree_skb(skb);
3572 return;
3573 }
3574
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3576
3577 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003578 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 l2cap_sig_channel(conn, skb);
3580 break;
3581
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003582 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003583 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 skb_pull(skb, 2);
3585 l2cap_conless_channel(conn, psm, skb);
3586 break;
3587
3588 default:
3589 l2cap_data_channel(conn, cid, skb);
3590 break;
3591 }
3592}
3593
3594/* ---- L2CAP interface with lower layer (HCI) ---- */
3595
3596static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3597{
3598 int exact = 0, lm1 = 0, lm2 = 0;
3599 register struct sock *sk;
3600 struct hlist_node *node;
3601
3602 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003603 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604
3605 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3606
3607 /* Find listening sockets and check their link_mode */
3608 read_lock(&l2cap_sk_list.lock);
3609 sk_for_each(sk, node, &l2cap_sk_list.head) {
3610 if (sk->sk_state != BT_LISTEN)
3611 continue;
3612
3613 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003614 lm1 |= HCI_LM_ACCEPT;
3615 if (l2cap_pi(sk)->role_switch)
3616 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003618 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3619 lm2 |= HCI_LM_ACCEPT;
3620 if (l2cap_pi(sk)->role_switch)
3621 lm2 |= HCI_LM_MASTER;
3622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 }
3624 read_unlock(&l2cap_sk_list.lock);
3625
3626 return exact ? lm1 : lm2;
3627}
3628
3629static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3630{
Marcel Holtmann01394182006-07-03 10:02:46 +02003631 struct l2cap_conn *conn;
3632
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3634
3635 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003636 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
3638 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 conn = l2cap_conn_add(hcon, status);
3640 if (conn)
3641 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003642 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 l2cap_conn_del(hcon, bt_err(status));
3644
3645 return 0;
3646}
3647
Marcel Holtmann2950f212009-02-12 14:02:50 +01003648static int l2cap_disconn_ind(struct hci_conn *hcon)
3649{
3650 struct l2cap_conn *conn = hcon->l2cap_data;
3651
3652 BT_DBG("hcon %p", hcon);
3653
3654 if (hcon->type != ACL_LINK || !conn)
3655 return 0x13;
3656
3657 return conn->disc_reason;
3658}
3659
3660static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661{
3662 BT_DBG("hcon %p reason %d", hcon, reason);
3663
3664 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003665 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666
3667 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 return 0;
3670}
3671
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003672static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3673{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003674 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003675 return;
3676
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003677 if (encrypt == 0x00) {
3678 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3679 l2cap_sock_clear_timer(sk);
3680 l2cap_sock_set_timer(sk, HZ * 5);
3681 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3682 __l2cap_sock_close(sk, ECONNREFUSED);
3683 } else {
3684 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3685 l2cap_sock_clear_timer(sk);
3686 }
3687}
3688
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003689static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690{
3691 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003692 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694
Marcel Holtmann01394182006-07-03 10:02:46 +02003695 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003697
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 l = &conn->chan_list;
3699
3700 BT_DBG("conn %p", conn);
3701
3702 read_lock(&l->lock);
3703
3704 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3705 bh_lock_sock(sk);
3706
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003707 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3708 bh_unlock_sock(sk);
3709 continue;
3710 }
3711
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003712 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003713 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003714 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003715 bh_unlock_sock(sk);
3716 continue;
3717 }
3718
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003719 if (sk->sk_state == BT_CONNECT) {
3720 if (!status) {
3721 struct l2cap_conn_req req;
3722 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3723 req.psm = l2cap_pi(sk)->psm;
3724
3725 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003726 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003727
3728 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3729 L2CAP_CONN_REQ, sizeof(req), &req);
3730 } else {
3731 l2cap_sock_clear_timer(sk);
3732 l2cap_sock_set_timer(sk, HZ / 10);
3733 }
3734 } else if (sk->sk_state == BT_CONNECT2) {
3735 struct l2cap_conn_rsp rsp;
3736 __u16 result;
3737
3738 if (!status) {
3739 sk->sk_state = BT_CONFIG;
3740 result = L2CAP_CR_SUCCESS;
3741 } else {
3742 sk->sk_state = BT_DISCONN;
3743 l2cap_sock_set_timer(sk, HZ / 10);
3744 result = L2CAP_CR_SEC_BLOCK;
3745 }
3746
3747 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3748 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3749 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003750 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003751 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3752 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 }
3754
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 bh_unlock_sock(sk);
3756 }
3757
3758 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003759
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 return 0;
3761}
3762
3763static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3764{
3765 struct l2cap_conn *conn = hcon->l2cap_data;
3766
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003767 if (!conn)
3768 conn = l2cap_conn_add(hcon, 0);
3769
3770 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 goto drop;
3772
3773 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3774
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003775 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003777 struct sock *sk;
3778 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 int len;
3780
3781 if (conn->rx_len) {
3782 BT_ERR("Unexpected start frame (len %d)", skb->len);
3783 kfree_skb(conn->rx_skb);
3784 conn->rx_skb = NULL;
3785 conn->rx_len = 0;
3786 l2cap_conn_unreliable(conn, ECOMM);
3787 }
3788
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003789 /* Start fragment always begin with Basic L2CAP header */
3790 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 BT_ERR("Frame is too short (len %d)", skb->len);
3792 l2cap_conn_unreliable(conn, ECOMM);
3793 goto drop;
3794 }
3795
3796 hdr = (struct l2cap_hdr *) skb->data;
3797 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003798 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
3800 if (len == skb->len) {
3801 /* Complete frame received */
3802 l2cap_recv_frame(conn, skb);
3803 return 0;
3804 }
3805
3806 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3807
3808 if (skb->len > len) {
3809 BT_ERR("Frame is too long (len %d, expected len %d)",
3810 skb->len, len);
3811 l2cap_conn_unreliable(conn, ECOMM);
3812 goto drop;
3813 }
3814
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003815 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3816
3817 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3818 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3819 len, l2cap_pi(sk)->imtu);
3820 bh_unlock_sock(sk);
3821 l2cap_conn_unreliable(conn, ECOMM);
3822 goto drop;
3823 }
3824
3825 if (sk)
3826 bh_unlock_sock(sk);
3827
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003829 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3830 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 goto drop;
3832
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003833 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003834 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 conn->rx_len = len - skb->len;
3836 } else {
3837 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3838
3839 if (!conn->rx_len) {
3840 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3841 l2cap_conn_unreliable(conn, ECOMM);
3842 goto drop;
3843 }
3844
3845 if (skb->len > conn->rx_len) {
3846 BT_ERR("Fragment is too long (len %d, expected %d)",
3847 skb->len, conn->rx_len);
3848 kfree_skb(conn->rx_skb);
3849 conn->rx_skb = NULL;
3850 conn->rx_len = 0;
3851 l2cap_conn_unreliable(conn, ECOMM);
3852 goto drop;
3853 }
3854
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003855 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003856 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 conn->rx_len -= skb->len;
3858
3859 if (!conn->rx_len) {
3860 /* Complete frame received */
3861 l2cap_recv_frame(conn, conn->rx_skb);
3862 conn->rx_skb = NULL;
3863 }
3864 }
3865
3866drop:
3867 kfree_skb(skb);
3868 return 0;
3869}
3870
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003871static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872{
3873 struct sock *sk;
3874 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
3876 read_lock_bh(&l2cap_sk_list.lock);
3877
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003878 sk_for_each(sk, node, &l2cap_sk_list.head) {
3879 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003881 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
3882 batostr(&bt_sk(sk)->src),
3883 batostr(&bt_sk(sk)->dst),
3884 sk->sk_state, __le16_to_cpu(pi->psm),
3885 pi->scid, pi->dcid,
3886 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003890
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003891 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892}
3893
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003894static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3895{
3896 return single_open(file, l2cap_debugfs_show, inode->i_private);
3897}
3898
3899static const struct file_operations l2cap_debugfs_fops = {
3900 .open = l2cap_debugfs_open,
3901 .read = seq_read,
3902 .llseek = seq_lseek,
3903 .release = single_release,
3904};
3905
3906static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908static struct hci_proto l2cap_hci_proto = {
3909 .name = "L2CAP",
3910 .id = HCI_PROTO_L2CAP,
3911 .connect_ind = l2cap_connect_ind,
3912 .connect_cfm = l2cap_connect_cfm,
3913 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01003914 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003915 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 .recv_acldata = l2cap_recv_acldata
3917};
3918
3919static int __init l2cap_init(void)
3920{
3921 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003922
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003923 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924 if (err < 0)
3925 return err;
3926
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003927 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003928 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003929 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 goto error;
3931 }
3932
3933 err = hci_register_proto(&l2cap_hci_proto);
3934 if (err < 0) {
3935 BT_ERR("L2CAP protocol registration failed");
3936 bt_sock_unregister(BTPROTO_L2CAP);
3937 goto error;
3938 }
3939
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003940 if (bt_debugfs) {
3941 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
3942 bt_debugfs, NULL, &l2cap_debugfs_fops);
3943 if (!l2cap_debugfs)
3944 BT_ERR("Failed to create L2CAP debug file");
3945 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
3947 BT_INFO("L2CAP ver %s", VERSION);
3948 BT_INFO("L2CAP socket layer initialized");
3949
3950 return 0;
3951
3952error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003953 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003954 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 return err;
3956}
3957
3958static void __exit l2cap_exit(void)
3959{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003960 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003962 flush_workqueue(_busy_wq);
3963 destroy_workqueue(_busy_wq);
3964
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
3966 BT_ERR("L2CAP protocol unregistration failed");
3967
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003968 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969}
3970
3971void l2cap_load(void)
3972{
3973 /* Dummy function to trigger automatic L2CAP module loading by
3974 * other modules that use L2CAP sockets but don't use any other
3975 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976}
3977EXPORT_SYMBOL(l2cap_load);
3978
3979module_init(l2cap_init);
3980module_exit(l2cap_exit);
3981
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003982module_param(disable_ertm, bool, 0644);
3983MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003984
Marcel Holtmann63fbd242008-08-18 13:23:53 +02003985MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
3987MODULE_VERSION(VERSION);
3988MODULE_LICENSE("GPL");
3989MODULE_ALIAS("bt-proto-0");