blob: ff6a54ffed890762a577a08f2d6ead2fdbbef01f [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
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -030075static int l2cap_build_conf_req(struct sock *sk, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
77 u8 code, u8 ident, u16 dlen, void *data);
78
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030079static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081/* ---- L2CAP timers ---- */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020082void l2cap_sock_set_timer(struct sock *sk, long timeout)
Andrei Emeltchenko940a9ee2010-11-03 12:32:45 +020083{
84 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
85 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
86}
87
88static void l2cap_sock_clear_timer(struct sock *sk)
89{
90 BT_DBG("sock %p state %d", sk, sk->sk_state);
91 sk_stop_timer(sk, &sk->sk_timer);
92}
93
Marcel Holtmann01394182006-07-03 10:02:46 +020094/* ---- L2CAP channels ---- */
95static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
96{
97 struct sock *s;
98 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
99 if (l2cap_pi(s)->dcid == cid)
100 break;
101 }
102 return s;
103}
104
105static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
106{
107 struct sock *s;
108 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
109 if (l2cap_pi(s)->scid == cid)
110 break;
111 }
112 return s;
113}
114
115/* Find channel with given SCID.
116 * Returns locked socket */
117static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
118{
119 struct sock *s;
120 read_lock(&l->lock);
121 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300122 if (s)
123 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 read_unlock(&l->lock);
125 return s;
126}
127
128static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
129{
130 struct sock *s;
131 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
132 if (l2cap_pi(s)->ident == ident)
133 break;
134 }
135 return s;
136}
137
138static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
139{
140 struct sock *s;
141 read_lock(&l->lock);
142 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300143 if (s)
144 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200145 read_unlock(&l->lock);
146 return s;
147}
148
149static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
150{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300151 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200152
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300153 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300154 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200155 return cid;
156 }
157
158 return 0;
159}
160
161static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
162{
163 sock_hold(sk);
164
165 if (l->head)
166 l2cap_pi(l->head)->prev_c = sk;
167
168 l2cap_pi(sk)->next_c = l->head;
169 l2cap_pi(sk)->prev_c = NULL;
170 l->head = sk;
171}
172
173static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
174{
175 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
176
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200177 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200178 if (sk == l->head)
179 l->head = next;
180
181 if (next)
182 l2cap_pi(next)->prev_c = prev;
183 if (prev)
184 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200185 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200186
187 __sock_put(sk);
188}
189
190static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
191{
192 struct l2cap_chan_list *l = &conn->chan_list;
193
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300194 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
195 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200196
Marcel Holtmann2950f212009-02-12 14:02:50 +0100197 conn->disc_reason = 0x13;
198
Marcel Holtmann01394182006-07-03 10:02:46 +0200199 l2cap_pi(sk)->conn = conn;
200
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300201 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200202 /* Alloc CID for connection-oriented socket */
203 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
204 } else if (sk->sk_type == SOCK_DGRAM) {
205 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300206 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
207 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200208 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
209 } else {
210 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300211 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
212 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200213 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
214 }
215
216 __l2cap_chan_link(l, sk);
217
218 if (parent)
219 bt_accept_enqueue(parent, sk);
220}
221
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900222/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 * Must be called on the locked socket. */
224static void l2cap_chan_del(struct sock *sk, int err)
225{
226 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
227 struct sock *parent = bt_sk(sk)->parent;
228
229 l2cap_sock_clear_timer(sk);
230
231 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
232
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900233 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200234 /* Unlink from channel list */
235 l2cap_chan_unlink(&conn->chan_list, sk);
236 l2cap_pi(sk)->conn = NULL;
237 hci_conn_put(conn->hcon);
238 }
239
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200240 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200241 sock_set_flag(sk, SOCK_ZAPPED);
242
243 if (err)
244 sk->sk_err = err;
245
246 if (parent) {
247 bt_accept_unlink(sk);
248 parent->sk_data_ready(parent, 0);
249 } else
250 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
252 skb_queue_purge(TX_QUEUE(sk));
253
254 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
255 struct srej_list *l, *tmp;
256
257 del_timer(&l2cap_pi(sk)->retrans_timer);
258 del_timer(&l2cap_pi(sk)->monitor_timer);
259 del_timer(&l2cap_pi(sk)->ack_timer);
260
261 skb_queue_purge(SREJ_QUEUE(sk));
262 skb_queue_purge(BUSY_QUEUE(sk));
263
264 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
265 list_del(&l->list);
266 kfree(l);
267 }
268 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200269}
270
Johan Hedberg8556edd32011-01-19 12:06:50 +0530271static inline u8 l2cap_get_auth_type(struct sock *sk)
272{
273 if (sk->sk_type == SOCK_RAW) {
274 switch (l2cap_pi(sk)->sec_level) {
275 case BT_SECURITY_HIGH:
276 return HCI_AT_DEDICATED_BONDING_MITM;
277 case BT_SECURITY_MEDIUM:
278 return HCI_AT_DEDICATED_BONDING;
279 default:
280 return HCI_AT_NO_BONDING;
281 }
282 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
283 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
284 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
285
286 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
287 return HCI_AT_NO_BONDING_MITM;
288 else
289 return HCI_AT_NO_BONDING;
290 } else {
291 switch (l2cap_pi(sk)->sec_level) {
292 case BT_SECURITY_HIGH:
293 return HCI_AT_GENERAL_BONDING_MITM;
294 case BT_SECURITY_MEDIUM:
295 return HCI_AT_GENERAL_BONDING;
296 default:
297 return HCI_AT_NO_BONDING;
298 }
299 }
300}
301
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200302/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100303static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200304{
305 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100306 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200307
Johan Hedberg8556edd32011-01-19 12:06:50 +0530308 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100309
310 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
311 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200312}
313
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200314static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
315{
316 u8 id;
317
318 /* Get next available identificator.
319 * 1 - 128 are used by kernel.
320 * 129 - 199 are reserved.
321 * 200 - 254 are used by utilities like l2ping, etc.
322 */
323
324 spin_lock_bh(&conn->lock);
325
326 if (++conn->tx_ident > 128)
327 conn->tx_ident = 1;
328
329 id = conn->tx_ident;
330
331 spin_unlock_bh(&conn->lock);
332
333 return id;
334}
335
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300336static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200337{
338 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200339 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200340
341 BT_DBG("code 0x%2.2x", code);
342
343 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300344 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200345
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200346 if (lmp_no_flush_capable(conn->hcon->hdev))
347 flags = ACL_START_NO_FLUSH;
348 else
349 flags = ACL_START;
350
351 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200352}
353
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300354static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300355{
356 struct sk_buff *skb;
357 struct l2cap_hdr *lh;
358 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300359 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300360 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200361 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300362
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300363 if (sk->sk_state != BT_CONNECTED)
364 return;
365
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366 if (pi->fcs == L2CAP_FCS_CRC16)
367 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300368
369 BT_DBG("pi %p, control 0x%2.2x", pi, control);
370
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300371 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300372 control |= L2CAP_CTRL_FRAME_TYPE;
373
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300374 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
375 control |= L2CAP_CTRL_FINAL;
376 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
377 }
378
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300379 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
380 control |= L2CAP_CTRL_POLL;
381 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
382 }
383
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300384 skb = bt_skb_alloc(count, GFP_ATOMIC);
385 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300386 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300387
388 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300389 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300390 lh->cid = cpu_to_le16(pi->dcid);
391 put_unaligned_le16(control, skb_put(skb, 2));
392
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300393 if (pi->fcs == L2CAP_FCS_CRC16) {
394 u16 fcs = crc16(0, (u8 *)lh, count - 2);
395 put_unaligned_le16(fcs, skb_put(skb, 2));
396 }
397
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200398 if (lmp_no_flush_capable(conn->hcon->hdev))
399 flags = ACL_START_NO_FLUSH;
400 else
401 flags = ACL_START;
402
403 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300404}
405
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300406static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300408 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300409 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300410 pi->conn_state |= L2CAP_CONN_RNR_SENT;
411 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300412 control |= L2CAP_SUPER_RCV_READY;
413
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300414 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
415
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300416 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300417}
418
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300419static inline int __l2cap_no_conn_pending(struct sock *sk)
420{
421 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
422}
423
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200424static void l2cap_do_start(struct sock *sk)
425{
426 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
427
428 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100429 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
430 return;
431
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300432 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200433 struct l2cap_conn_req req;
434 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
435 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200436
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200437 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300438 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200440 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200441 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200442 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200443 } else {
444 struct l2cap_info_req req;
445 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
446
447 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
448 conn->info_ident = l2cap_get_ident(conn);
449
450 mod_timer(&conn->info_timer, jiffies +
451 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
452
453 l2cap_send_cmd(conn, conn->info_ident,
454 L2CAP_INFO_REQ, sizeof(req), &req);
455 }
456}
457
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
459{
460 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300461 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300462 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
463
464 switch (mode) {
465 case L2CAP_MODE_ERTM:
466 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
467 case L2CAP_MODE_STREAMING:
468 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
469 default:
470 return 0x00;
471 }
472}
473
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300474static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300475{
476 struct l2cap_disconn_req req;
477
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300478 if (!conn)
479 return;
480
481 skb_queue_purge(TX_QUEUE(sk));
482
483 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
484 del_timer(&l2cap_pi(sk)->retrans_timer);
485 del_timer(&l2cap_pi(sk)->monitor_timer);
486 del_timer(&l2cap_pi(sk)->ack_timer);
487 }
488
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300489 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
490 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
491 l2cap_send_cmd(conn, l2cap_get_ident(conn),
492 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300493
494 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300495 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300496}
497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499static void l2cap_conn_start(struct l2cap_conn *conn)
500{
501 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300502 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503 struct sock *sk;
504
505 BT_DBG("conn %p", conn);
506
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300507 INIT_LIST_HEAD(&del.list);
508
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 read_lock(&l->lock);
510
511 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
512 bh_lock_sock(sk);
513
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300514 if (sk->sk_type != SOCK_SEQPACKET &&
515 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200516 bh_unlock_sock(sk);
517 continue;
518 }
519
520 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300521 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300522
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300523 if (!l2cap_check_security(sk) ||
524 !__l2cap_no_conn_pending(sk)) {
525 bh_unlock_sock(sk);
526 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200527 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300528
529 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
530 conn->feat_mask)
531 && l2cap_pi(sk)->conf_state &
532 L2CAP_CONF_STATE2_DEVICE) {
533 tmp1 = kzalloc(sizeof(struct sock_del_list),
534 GFP_ATOMIC);
535 tmp1->sk = sk;
536 list_add_tail(&tmp1->list, &del.list);
537 bh_unlock_sock(sk);
538 continue;
539 }
540
541 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
542 req.psm = l2cap_pi(sk)->psm;
543
544 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
545 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
546
547 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
548 L2CAP_CONN_REQ, sizeof(req), &req);
549
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200550 } else if (sk->sk_state == BT_CONNECT2) {
551 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300552 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200553 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
554 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
555
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100556 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100557 if (bt_sk(sk)->defer_setup) {
558 struct sock *parent = bt_sk(sk)->parent;
559 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
560 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
561 parent->sk_data_ready(parent, 0);
562
563 } else {
564 sk->sk_state = BT_CONFIG;
565 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
566 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
567 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200568 } else {
569 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
570 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
571 }
572
573 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
574 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300575
576 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
577 rsp.result != L2CAP_CR_SUCCESS) {
578 bh_unlock_sock(sk);
579 continue;
580 }
581
582 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
583 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
584 l2cap_build_conf_req(sk, buf), buf);
585 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200586 }
587
588 bh_unlock_sock(sk);
589 }
590
591 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300592
593 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
594 bh_lock_sock(tmp1->sk);
595 __l2cap_sock_close(tmp1->sk, ECONNRESET);
596 bh_unlock_sock(tmp1->sk);
597 list_del(&tmp1->list);
598 kfree(tmp1);
599 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200600}
601
602static void l2cap_conn_ready(struct l2cap_conn *conn)
603{
604 struct l2cap_chan_list *l = &conn->chan_list;
605 struct sock *sk;
606
607 BT_DBG("conn %p", conn);
608
609 read_lock(&l->lock);
610
611 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
612 bh_lock_sock(sk);
613
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300614 if (sk->sk_type != SOCK_SEQPACKET &&
615 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200616 l2cap_sock_clear_timer(sk);
617 sk->sk_state = BT_CONNECTED;
618 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200619 } else if (sk->sk_state == BT_CONNECT)
620 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200621
622 bh_unlock_sock(sk);
623 }
624
625 read_unlock(&l->lock);
626}
627
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200628/* Notify sockets that we cannot guaranty reliability anymore */
629static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
630{
631 struct l2cap_chan_list *l = &conn->chan_list;
632 struct sock *sk;
633
634 BT_DBG("conn %p", conn);
635
636 read_lock(&l->lock);
637
638 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100639 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200640 sk->sk_err = err;
641 }
642
643 read_unlock(&l->lock);
644}
645
646static void l2cap_info_timeout(unsigned long arg)
647{
648 struct l2cap_conn *conn = (void *) arg;
649
Marcel Holtmann984947d2009-02-06 23:35:19 +0100650 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100651 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100652
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200653 l2cap_conn_start(conn);
654}
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
657{
Marcel Holtmann01394182006-07-03 10:02:46 +0200658 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Marcel Holtmann01394182006-07-03 10:02:46 +0200660 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 return conn;
662
Marcel Holtmann01394182006-07-03 10:02:46 +0200663 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
664 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667 hcon->l2cap_data = conn;
668 conn->hcon = hcon;
669
Marcel Holtmann01394182006-07-03 10:02:46 +0200670 BT_DBG("hcon %p conn %p", hcon, conn);
671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 conn->mtu = hcon->hdev->acl_mtu;
673 conn->src = &hcon->hdev->bdaddr;
674 conn->dst = &hcon->dst;
675
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200676 conn->feat_mask = 0;
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 spin_lock_init(&conn->lock);
679 rwlock_init(&conn->chan_list.lock);
680
Dave Young45054dc2009-10-18 20:28:30 +0000681 setup_timer(&conn->info_timer, l2cap_info_timeout,
682 (unsigned long) conn);
683
Marcel Holtmann2950f212009-02-12 14:02:50 +0100684 conn->disc_reason = 0x13;
685
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 return conn;
687}
688
Marcel Holtmann01394182006-07-03 10:02:46 +0200689static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690{
Marcel Holtmann01394182006-07-03 10:02:46 +0200691 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 struct sock *sk;
693
Marcel Holtmann01394182006-07-03 10:02:46 +0200694 if (!conn)
695 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
698
Wei Yongjun7585b972009-02-25 18:29:52 +0800699 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701 /* Kill channels */
702 while ((sk = conn->chan_list.head)) {
703 bh_lock_sock(sk);
704 l2cap_chan_del(sk, err);
705 bh_unlock_sock(sk);
706 l2cap_sock_kill(sk);
707 }
708
Dave Young8e8440f2008-03-03 12:18:55 -0800709 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
710 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 hcon->l2cap_data = NULL;
713 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
716static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
717{
718 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200719 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200721 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722}
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726/* Find socket with psm and source bdaddr.
727 * Returns closest match.
728 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000729static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
731 struct sock *sk = NULL, *sk1 = NULL;
732 struct hlist_node *node;
733
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000734 read_lock(&l2cap_sk_list.lock);
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 sk_for_each(sk, node, &l2cap_sk_list.head) {
737 if (state && sk->sk_state != state)
738 continue;
739
740 if (l2cap_pi(sk)->psm == psm) {
741 /* Exact match. */
742 if (!bacmp(&bt_sk(sk)->src, src))
743 break;
744
745 /* Closest match */
746 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
747 sk1 = sk;
748 }
749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000752
753 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754}
755
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756static void l2cap_sock_cleanup_listen(struct sock *parent)
757{
758 struct sock *sk;
759
760 BT_DBG("parent %p", parent);
761
762 /* Close not yet accepted channels */
763 while ((sk = bt_accept_dequeue(parent, NULL)))
764 l2cap_sock_close(sk);
765
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200766 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 sock_set_flag(parent, SOCK_ZAPPED);
768}
769
770/* Kill socket (only if zapped and orphan)
771 * Must be called on unlocked socket.
772 */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200773void l2cap_sock_kill(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774{
775 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
776 return;
777
778 BT_DBG("sk %p state %d", sk, sk->sk_state);
779
780 /* Kill poor orphan */
781 bt_sock_unlink(&l2cap_sk_list, sk);
782 sock_set_flag(sk, SOCK_DEAD);
783 sock_put(sk);
784}
785
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200786void __l2cap_sock_close(struct sock *sk, int reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
788 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
789
790 switch (sk->sk_state) {
791 case BT_LISTEN:
792 l2cap_sock_cleanup_listen(sk);
793 break;
794
795 case BT_CONNECTED:
796 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300797 if (sk->sk_type == SOCK_SEQPACKET ||
798 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300802 l2cap_send_disconn_req(conn, sk, reason);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200803 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 break;
806
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100807 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300808 if (sk->sk_type == SOCK_SEQPACKET ||
809 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100810 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
811 struct l2cap_conn_rsp rsp;
812 __u16 result;
813
814 if (bt_sk(sk)->defer_setup)
815 result = L2CAP_CR_SEC_BLOCK;
816 else
817 result = L2CAP_CR_BAD_PSM;
Bao Liange733fb62011-01-29 21:39:37 +0800818 sk->sk_state = BT_DISCONN;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100819
820 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
821 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
822 rsp.result = cpu_to_le16(result);
823 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
824 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
825 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
826 } else
827 l2cap_chan_del(sk, reason);
828 break;
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 case BT_CONNECT:
831 case BT_DISCONN:
832 l2cap_chan_del(sk, reason);
833 break;
834
835 default:
836 sock_set_flag(sk, SOCK_ZAPPED);
837 break;
838 }
839}
840
841/* Must be called on unlocked socket. */
842static void l2cap_sock_close(struct sock *sk)
843{
844 l2cap_sock_clear_timer(sk);
845 lock_sock(sk);
846 __l2cap_sock_close(sk, ECONNRESET);
847 release_sock(sk);
848 l2cap_sock_kill(sk);
849}
850
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851static int l2cap_do_connect(struct sock *sk)
852{
853 bdaddr_t *src = &bt_sk(sk)->src;
854 bdaddr_t *dst = &bt_sk(sk)->dst;
855 struct l2cap_conn *conn;
856 struct hci_conn *hcon;
857 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200858 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200859 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100861 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
862 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300864 hdev = hci_get_route(dst, src);
865 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return -EHOSTUNREACH;
867
868 hci_dev_lock_bh(hdev);
869
870 err = -ENOMEM;
871
Johan Hedberg8556edd32011-01-19 12:06:50 +0530872 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100874 hcon = hci_connect(hdev, ACL_LINK, dst,
875 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 if (!hcon)
877 goto done;
878
879 conn = l2cap_conn_add(hcon, 0);
880 if (!conn) {
881 hci_conn_put(hcon);
882 goto done;
883 }
884
885 err = 0;
886
887 /* Update source addr of the socket */
888 bacpy(src, conn->src);
889
890 l2cap_chan_add(conn, sk, NULL);
891
892 sk->sk_state = BT_CONNECT;
893 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
894
895 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300896 if (sk->sk_type != SOCK_SEQPACKET &&
897 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530899 if (l2cap_check_security(sk))
900 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200901 } else
902 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
904
905done:
906 hci_dev_unlock_bh(hdev);
907 hci_dev_put(hdev);
908 return err;
909}
910
Gustavo F. Padovan65390582011-02-04 02:33:56 -0200911int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100914 struct sockaddr_l2 la;
915 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 BT_DBG("sk %p", sk);
918
Changli Gao6503d962010-03-31 22:58:26 +0000919 if (!addr || alen < sizeof(addr->sa_family) ||
920 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100921 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100923 memset(&la, 0, sizeof(la));
924 len = min_t(unsigned int, sizeof(la), alen);
925 memcpy(&la, addr, len);
926
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100927 if (la.l2_cid)
928 return -EINVAL;
929
930 lock_sock(sk);
931
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300932 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
933 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 err = -EINVAL;
935 goto done;
936 }
937
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700938 switch (l2cap_pi(sk)->mode) {
939 case L2CAP_MODE_BASIC:
940 break;
941 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -0300942 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300943 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700944 break;
945 /* fall through */
946 default:
947 err = -ENOTSUPP;
948 goto done;
949 }
950
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300951 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 case BT_CONNECT:
953 case BT_CONNECT2:
954 case BT_CONFIG:
955 /* Already connecting */
956 goto wait;
957
958 case BT_CONNECTED:
959 /* Already connected */
João Paulo Rechi Vita8b0dc6d2010-06-22 13:56:22 -0300960 err = -EISCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 goto done;
962
963 case BT_OPEN:
964 case BT_BOUND:
965 /* Can connect */
966 break;
967
968 default:
969 err = -EBADFD;
970 goto done;
971 }
972
Mat Martineau0fba2552010-09-08 10:05:26 -0700973 /* PSM must be odd and lsb of upper byte must be 0 */
974 if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
975 sk->sk_type != SOCK_RAW) {
976 err = -EINVAL;
977 goto done;
978 }
979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100981 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
982 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300984 err = l2cap_do_connect(sk);
985 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 goto done;
987
988wait:
989 err = bt_sock_wait_state(sk, BT_CONNECTED,
990 sock_sndtimeo(sk, flags & O_NONBLOCK));
991done:
992 release_sock(sk);
993 return err;
994}
995
Gustavo F. Padovan65390582011-02-04 02:33:56 -0200996int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997{
998 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
999 struct sock *sk = sock->sk;
1000
1001 BT_DBG("sock %p, sk %p", sock, sk);
1002
1003 addr->sa_family = AF_BLUETOOTH;
1004 *len = sizeof(struct sockaddr_l2);
1005
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001006 if (peer) {
1007 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001009 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001010 } else {
1011 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001013 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return 0;
1017}
1018
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001019static int __l2cap_wait_ack(struct sock *sk)
1020{
1021 DECLARE_WAITQUEUE(wait, current);
1022 int err = 0;
1023 int timeo = HZ/5;
1024
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001025 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001026 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
1027 set_current_state(TASK_INTERRUPTIBLE);
1028
1029 if (!timeo)
1030 timeo = HZ/5;
1031
1032 if (signal_pending(current)) {
1033 err = sock_intr_errno(timeo);
1034 break;
1035 }
1036
1037 release_sock(sk);
1038 timeo = schedule_timeout(timeo);
1039 lock_sock(sk);
1040
1041 err = sock_error(sk);
1042 if (err)
1043 break;
1044 }
1045 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001046 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001047 return err;
1048}
1049
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001050static void l2cap_monitor_timeout(unsigned long arg)
1051{
1052 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001053
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001054 BT_DBG("sk %p", sk);
1055
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001056 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001057 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001058 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001059 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001060 return;
1061 }
1062
1063 l2cap_pi(sk)->retry_count++;
1064 __mod_monitor_timer();
1065
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001066 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001067 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001068}
1069
1070static void l2cap_retrans_timeout(unsigned long arg)
1071{
1072 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001073
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001074 BT_DBG("sk %p", sk);
1075
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001076 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001077 l2cap_pi(sk)->retry_count = 1;
1078 __mod_monitor_timer();
1079
1080 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1081
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001082 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001083 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001084}
1085
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001086static void l2cap_drop_acked_frames(struct sock *sk)
1087{
1088 struct sk_buff *skb;
1089
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001090 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1091 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001092 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1093 break;
1094
1095 skb = skb_dequeue(TX_QUEUE(sk));
1096 kfree_skb(skb);
1097
1098 l2cap_pi(sk)->unacked_frames--;
1099 }
1100
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001101 if (!l2cap_pi(sk)->unacked_frames)
1102 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103}
1104
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001105static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001106{
1107 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001108 struct hci_conn *hcon = pi->conn->hcon;
1109 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001110
1111 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1112
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001113 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1114 flags = ACL_START_NO_FLUSH;
1115 else
1116 flags = ACL_START;
1117
1118 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001119}
1120
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001121static void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001122{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001123 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001124 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001125 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001126
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001127 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1128 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001129 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001130 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001131
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001132 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001133 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1134 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001135 }
1136
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001137 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001138
1139 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001140 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001141}
1142
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001143static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001144{
1145 struct l2cap_pinfo *pi = l2cap_pi(sk);
1146 struct sk_buff *skb, *tx_skb;
1147 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001148
1149 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001150 if (!skb)
1151 return;
1152
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001153 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001154 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001155 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001156
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001157 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1158 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001159
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001160 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001161
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001162 if (pi->remote_max_tx &&
1163 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001164 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001165 return;
1166 }
1167
1168 tx_skb = skb_clone(skb, GFP_ATOMIC);
1169 bt_cb(skb)->retries++;
1170 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001171
1172 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1173 control |= L2CAP_CTRL_FINAL;
1174 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1175 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001176
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001177 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1178 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001179
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001180 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1181
1182 if (pi->fcs == L2CAP_FCS_CRC16) {
1183 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1184 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1185 }
1186
1187 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001188}
1189
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001190static int l2cap_ertm_send(struct sock *sk)
1191{
1192 struct sk_buff *skb, *tx_skb;
1193 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001194 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001195 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001196
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001197 if (sk->sk_state != BT_CONNECTED)
1198 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001199
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001200 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001201
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001202 if (pi->remote_max_tx &&
1203 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001204 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001205 break;
1206 }
1207
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001208 tx_skb = skb_clone(skb, GFP_ATOMIC);
1209
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210 bt_cb(skb)->retries++;
1211
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001213 control &= L2CAP_CTRL_SAR;
1214
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001215 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1216 control |= L2CAP_CTRL_FINAL;
1217 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1218 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001219 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001220 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1221 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1222
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001224 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001225 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1226 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1227 }
1228
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001229 l2cap_do_send(sk, tx_skb);
1230
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001231 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232
1233 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1234 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1235
1236 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001237 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001238
1239 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1240 sk->sk_send_head = NULL;
1241 else
1242 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001243
1244 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245 }
1246
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001247 return nsent;
1248}
1249
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001250static int l2cap_retransmit_frames(struct sock *sk)
1251{
1252 struct l2cap_pinfo *pi = l2cap_pi(sk);
1253 int ret;
1254
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001255 if (!skb_queue_empty(TX_QUEUE(sk)))
1256 sk->sk_send_head = TX_QUEUE(sk)->next;
1257
1258 pi->next_tx_seq = pi->expected_ack_seq;
1259 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001260 return ret;
1261}
1262
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001263static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001264{
1265 struct sock *sk = (struct sock *)pi;
1266 u16 control = 0;
1267
1268 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1269
1270 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1271 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001272 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001273 l2cap_send_sframe(pi, control);
1274 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001275 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001276
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001277 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001278 return;
1279
1280 control |= L2CAP_SUPER_RCV_READY;
1281 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001282}
1283
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001284static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001285{
1286 struct srej_list *tail;
1287 u16 control;
1288
1289 control = L2CAP_SUPER_SELECT_REJECT;
1290 control |= L2CAP_CTRL_FINAL;
1291
1292 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1293 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1294
1295 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001296}
1297
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298static 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 -07001299{
1300 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301 struct sk_buff **frag;
1302 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001304 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001305 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307 sent += count;
1308 len -= count;
1309
1310 /* Continuation fragments (no L2CAP header) */
1311 frag = &skb_shinfo(skb)->frag_list;
1312 while (len) {
1313 count = min_t(unsigned int, conn->mtu, len);
1314
1315 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1316 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001317 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001318 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1319 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 sent += count;
1322 len -= count;
1323
1324 frag = &(*frag)->next;
1325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
1327 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1331{
1332 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1333 struct sk_buff *skb;
1334 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1335 struct l2cap_hdr *lh;
1336
1337 BT_DBG("sk %p len %d", sk, (int)len);
1338
1339 count = min_t(unsigned int, (conn->mtu - hlen), len);
1340 skb = bt_skb_send_alloc(sk, count + hlen,
1341 msg->msg_flags & MSG_DONTWAIT, &err);
1342 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001343 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001344
1345 /* Create L2CAP header */
1346 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1347 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1348 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1349 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1350
1351 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1352 if (unlikely(err < 0)) {
1353 kfree_skb(skb);
1354 return ERR_PTR(err);
1355 }
1356 return skb;
1357}
1358
1359static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1360{
1361 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1362 struct sk_buff *skb;
1363 int err, count, hlen = L2CAP_HDR_SIZE;
1364 struct l2cap_hdr *lh;
1365
1366 BT_DBG("sk %p len %d", sk, (int)len);
1367
1368 count = min_t(unsigned int, (conn->mtu - hlen), len);
1369 skb = bt_skb_send_alloc(sk, count + hlen,
1370 msg->msg_flags & MSG_DONTWAIT, &err);
1371 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001372 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
1374 /* Create L2CAP header */
1375 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1376 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1377 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1378
1379 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1380 if (unlikely(err < 0)) {
1381 kfree_skb(skb);
1382 return ERR_PTR(err);
1383 }
1384 return skb;
1385}
1386
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001387static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001388{
1389 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1390 struct sk_buff *skb;
1391 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1392 struct l2cap_hdr *lh;
1393
1394 BT_DBG("sk %p len %d", sk, (int)len);
1395
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001396 if (!conn)
1397 return ERR_PTR(-ENOTCONN);
1398
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001399 if (sdulen)
1400 hlen += 2;
1401
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001402 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1403 hlen += 2;
1404
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405 count = min_t(unsigned int, (conn->mtu - hlen), len);
1406 skb = bt_skb_send_alloc(sk, count + hlen,
1407 msg->msg_flags & MSG_DONTWAIT, &err);
1408 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001409 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001410
1411 /* Create L2CAP header */
1412 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1413 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1414 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1415 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001416 if (sdulen)
1417 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001418
1419 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1420 if (unlikely(err < 0)) {
1421 kfree_skb(skb);
1422 return ERR_PTR(err);
1423 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001424
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001425 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1426 put_unaligned_le16(0, skb_put(skb, 2));
1427
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001428 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001429 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430}
1431
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001432static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1433{
1434 struct l2cap_pinfo *pi = l2cap_pi(sk);
1435 struct sk_buff *skb;
1436 struct sk_buff_head sar_queue;
1437 u16 control;
1438 size_t size = 0;
1439
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001440 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001441 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001442 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001443 if (IS_ERR(skb))
1444 return PTR_ERR(skb);
1445
1446 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001447 len -= pi->remote_mps;
1448 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001449
1450 while (len > 0) {
1451 size_t buflen;
1452
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001453 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001454 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001455 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001456 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001457 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001458 buflen = len;
1459 }
1460
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001461 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001462 if (IS_ERR(skb)) {
1463 skb_queue_purge(&sar_queue);
1464 return PTR_ERR(skb);
1465 }
1466
1467 __skb_queue_tail(&sar_queue, skb);
1468 len -= buflen;
1469 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001470 }
1471 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1472 if (sk->sk_send_head == NULL)
1473 sk->sk_send_head = sar_queue.next;
1474
1475 return size;
1476}
1477
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001478int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479{
1480 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001481 struct l2cap_pinfo *pi = l2cap_pi(sk);
1482 struct sk_buff *skb;
1483 u16 control;
1484 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
1486 BT_DBG("sock %p, sk %p", sock, sk);
1487
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001488 err = sock_error(sk);
1489 if (err)
1490 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
1492 if (msg->msg_flags & MSG_OOB)
1493 return -EOPNOTSUPP;
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 lock_sock(sk);
1496
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499 goto done;
1500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502 /* Connectionless channel */
1503 if (sk->sk_type == SOCK_DGRAM) {
1504 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001505 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001506 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001507 } else {
1508 l2cap_do_send(sk, skb);
1509 err = len;
1510 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001511 goto done;
1512 }
1513
1514 switch (pi->mode) {
1515 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001516 /* Check outgoing MTU */
1517 if (len > pi->omtu) {
João Paulo Rechi Vitaf9dd11b2010-06-22 13:56:24 -03001518 err = -EMSGSIZE;
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001519 goto done;
1520 }
1521
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 /* Create a basic PDU */
1523 skb = l2cap_create_basic_pdu(sk, msg, len);
1524 if (IS_ERR(skb)) {
1525 err = PTR_ERR(skb);
1526 goto done;
1527 }
1528
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001529 l2cap_do_send(sk, skb);
1530 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001531 break;
1532
1533 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001534 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001535 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001536 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001537 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001538 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001539 if (IS_ERR(skb)) {
1540 err = PTR_ERR(skb);
1541 goto done;
1542 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001543 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001544
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001545 if (sk->sk_send_head == NULL)
1546 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001547
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001549 /* Segment SDU into multiples PDUs */
1550 err = l2cap_sar_segment_sdu(sk, msg, len);
1551 if (err < 0)
1552 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001555 if (pi->mode == L2CAP_MODE_STREAMING) {
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001556 l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001557 } else {
David Sterba45719282011-01-14 14:59:44 +01001558 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1559 (pi->conn_state & L2CAP_CONN_WAIT_F)) {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001560 err = len;
1561 break;
1562 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001563 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001564 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001565
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001566 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001567 err = len;
1568 break;
1569
1570 default:
1571 BT_DBG("bad state %1.1x", pi->mode);
João Paulo Rechi Vitabc766db22010-06-22 13:56:25 -03001572 err = -EBADFD;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573 }
1574
1575done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 release_sock(sk);
1577 return err;
1578}
1579
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001580int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001581{
1582 struct sock *sk = sock->sk;
1583
1584 lock_sock(sk);
1585
1586 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1587 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001588 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1589 u8 buf[128];
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001590
1591 sk->sk_state = BT_CONFIG;
1592
1593 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1594 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1595 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1596 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1597 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1598 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1599
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001600 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
1601 release_sock(sk);
1602 return 0;
1603 }
1604
1605 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1606 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1607 l2cap_build_conf_req(sk, buf), buf);
1608 l2cap_pi(sk)->num_conf_req++;
1609
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001610 release_sock(sk);
1611 return 0;
1612 }
1613
1614 release_sock(sk);
1615
Mat Martineau6fdf4822010-09-08 10:05:29 -07001616 if (sock->type == SOCK_STREAM)
1617 return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
1618
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001619 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1620}
1621
David S. Millerb7058842009-09-30 16:12:20 -07001622static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 struct sock *sk = sock->sk;
1625 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001626 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 u32 opt;
1628
1629 BT_DBG("sk %p", sk);
1630
1631 lock_sock(sk);
1632
1633 switch (optname) {
1634 case L2CAP_OPTIONS:
Gustavo F. Padovaneaa71b32010-10-04 19:28:52 -03001635 if (sk->sk_state == BT_CONNECTED) {
1636 err = -EINVAL;
1637 break;
1638 }
1639
Marcel Holtmann0878b662007-05-05 00:35:59 +02001640 opts.imtu = l2cap_pi(sk)->imtu;
1641 opts.omtu = l2cap_pi(sk)->omtu;
1642 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001643 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001644 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001645 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001646 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001647
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 len = min_t(unsigned int, sizeof(opts), optlen);
1649 if (copy_from_user((char *) &opts, optval, len)) {
1650 err = -EFAULT;
1651 break;
1652 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001653
Gustavo F. Padovan45d65c42010-06-07 19:21:30 -03001654 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
1655 err = -EINVAL;
1656 break;
1657 }
1658
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001659 l2cap_pi(sk)->mode = opts.mode;
1660 switch (l2cap_pi(sk)->mode) {
1661 case L2CAP_MODE_BASIC:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001662 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001663 break;
1664 case L2CAP_MODE_ERTM:
1665 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001666 if (!disable_ertm)
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001667 break;
1668 /* fall through */
1669 default:
1670 err = -EINVAL;
1671 break;
1672 }
1673
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001674 l2cap_pi(sk)->imtu = opts.imtu;
1675 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001676 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001677 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001678 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 break;
1680
1681 case L2CAP_LM:
1682 if (get_user(opt, (u32 __user *) optval)) {
1683 err = -EFAULT;
1684 break;
1685 }
1686
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001687 if (opt & L2CAP_LM_AUTH)
1688 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
1689 if (opt & L2CAP_LM_ENCRYPT)
1690 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
1691 if (opt & L2CAP_LM_SECURE)
1692 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
1693
1694 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
1695 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 break;
1697
1698 default:
1699 err = -ENOPROTOOPT;
1700 break;
1701 }
1702
1703 release_sock(sk);
1704 return err;
1705}
1706
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001707int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001708{
1709 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001710 struct bt_security sec;
1711 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001712 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001713
1714 BT_DBG("sk %p", sk);
1715
1716 if (level == SOL_L2CAP)
1717 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
1718
Marcel Holtmann0588d942009-01-16 10:06:13 +01001719 if (level != SOL_BLUETOOTH)
1720 return -ENOPROTOOPT;
1721
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001722 lock_sock(sk);
1723
1724 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001725 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001726 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
1727 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01001728 err = -EINVAL;
1729 break;
1730 }
1731
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001732 sec.level = BT_SECURITY_LOW;
1733
1734 len = min_t(unsigned int, sizeof(sec), optlen);
1735 if (copy_from_user((char *) &sec, optval, len)) {
1736 err = -EFAULT;
1737 break;
1738 }
1739
1740 if (sec.level < BT_SECURITY_LOW ||
1741 sec.level > BT_SECURITY_HIGH) {
1742 err = -EINVAL;
1743 break;
1744 }
1745
1746 l2cap_pi(sk)->sec_level = sec.level;
1747 break;
1748
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001749 case BT_DEFER_SETUP:
1750 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1751 err = -EINVAL;
1752 break;
1753 }
1754
1755 if (get_user(opt, (u32 __user *) optval)) {
1756 err = -EFAULT;
1757 break;
1758 }
1759
1760 bt_sk(sk)->defer_setup = opt;
1761 break;
1762
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001763 case BT_FLUSHABLE:
1764 if (get_user(opt, (u32 __user *) optval)) {
1765 err = -EFAULT;
1766 break;
1767 }
1768
1769 if (opt > BT_FLUSHABLE_ON) {
1770 err = -EINVAL;
1771 break;
1772 }
1773
1774 if (opt == BT_FLUSHABLE_OFF) {
1775 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1776 /* proceed futher only when we have l2cap_conn and
1777 No Flush support in the LM */
1778 if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
1779 err = -EINVAL;
1780 break;
1781 }
1782 }
1783
1784 l2cap_pi(sk)->flushable = opt;
1785 break;
1786
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001787 default:
1788 err = -ENOPROTOOPT;
1789 break;
1790 }
1791
1792 release_sock(sk);
1793 return err;
1794}
1795
1796static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797{
1798 struct sock *sk = sock->sk;
1799 struct l2cap_options opts;
1800 struct l2cap_conninfo cinfo;
1801 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001802 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
1804 BT_DBG("sk %p", sk);
1805
1806 if (get_user(len, optlen))
1807 return -EFAULT;
1808
1809 lock_sock(sk);
1810
1811 switch (optname) {
1812 case L2CAP_OPTIONS:
1813 opts.imtu = l2cap_pi(sk)->imtu;
1814 opts.omtu = l2cap_pi(sk)->omtu;
1815 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001816 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001817 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001818 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001819 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821 len = min_t(unsigned int, len, sizeof(opts));
1822 if (copy_to_user(optval, (char *) &opts, len))
1823 err = -EFAULT;
1824
1825 break;
1826
1827 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001828 switch (l2cap_pi(sk)->sec_level) {
1829 case BT_SECURITY_LOW:
1830 opt = L2CAP_LM_AUTH;
1831 break;
1832 case BT_SECURITY_MEDIUM:
1833 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
1834 break;
1835 case BT_SECURITY_HIGH:
1836 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
1837 L2CAP_LM_SECURE;
1838 break;
1839 default:
1840 opt = 0;
1841 break;
1842 }
1843
1844 if (l2cap_pi(sk)->role_switch)
1845 opt |= L2CAP_LM_MASTER;
1846
1847 if (l2cap_pi(sk)->force_reliable)
1848 opt |= L2CAP_LM_RELIABLE;
1849
1850 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 err = -EFAULT;
1852 break;
1853
1854 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001855 if (sk->sk_state != BT_CONNECTED &&
1856 !(sk->sk_state == BT_CONNECT2 &&
1857 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 err = -ENOTCONN;
1859 break;
1860 }
1861
1862 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
1863 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
1864
1865 len = min_t(unsigned int, len, sizeof(cinfo));
1866 if (copy_to_user(optval, (char *) &cinfo, len))
1867 err = -EFAULT;
1868
1869 break;
1870
1871 default:
1872 err = -ENOPROTOOPT;
1873 break;
1874 }
1875
1876 release_sock(sk);
1877 return err;
1878}
1879
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001880int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001881{
1882 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001883 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001884 int len, err = 0;
1885
1886 BT_DBG("sk %p", sk);
1887
1888 if (level == SOL_L2CAP)
1889 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
1890
Marcel Holtmann0588d942009-01-16 10:06:13 +01001891 if (level != SOL_BLUETOOTH)
1892 return -ENOPROTOOPT;
1893
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001894 if (get_user(len, optlen))
1895 return -EFAULT;
1896
1897 lock_sock(sk);
1898
1899 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001900 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001901 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
1902 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01001903 err = -EINVAL;
1904 break;
1905 }
1906
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001907 sec.level = l2cap_pi(sk)->sec_level;
1908
1909 len = min_t(unsigned int, len, sizeof(sec));
1910 if (copy_to_user(optval, (char *) &sec, len))
1911 err = -EFAULT;
1912
1913 break;
1914
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001915 case BT_DEFER_SETUP:
1916 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1917 err = -EINVAL;
1918 break;
1919 }
1920
1921 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
1922 err = -EFAULT;
1923
1924 break;
1925
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001926 case BT_FLUSHABLE:
1927 if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
1928 err = -EFAULT;
1929
1930 break;
1931
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001932 default:
1933 err = -ENOPROTOOPT;
1934 break;
1935 }
1936
1937 release_sock(sk);
1938 return err;
1939}
1940
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001941int l2cap_sock_shutdown(struct socket *sock, int how)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
1943 struct sock *sk = sock->sk;
1944 int err = 0;
1945
1946 BT_DBG("sock %p, sk %p", sock, sk);
1947
1948 if (!sk)
1949 return 0;
1950
1951 lock_sock(sk);
1952 if (!sk->sk_shutdown) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001953 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
1954 err = __l2cap_wait_ack(sk);
1955
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 sk->sk_shutdown = SHUTDOWN_MASK;
1957 l2cap_sock_clear_timer(sk);
1958 __l2cap_sock_close(sk, 0);
1959
1960 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02001961 err = bt_sock_wait_state(sk, BT_CLOSED,
1962 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 }
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001964
1965 if (!err && sk->sk_err)
1966 err = -sk->sk_err;
1967
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 release_sock(sk);
1969 return err;
1970}
1971
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972static void l2cap_chan_ready(struct sock *sk)
1973{
1974 struct sock *parent = bt_sk(sk)->parent;
1975
1976 BT_DBG("sk %p, parent %p", sk, parent);
1977
1978 l2cap_pi(sk)->conf_state = 0;
1979 l2cap_sock_clear_timer(sk);
1980
1981 if (!parent) {
1982 /* Outgoing channel.
1983 * Wake up socket sleeping on connect.
1984 */
1985 sk->sk_state = BT_CONNECTED;
1986 sk->sk_state_change(sk);
1987 } else {
1988 /* Incoming channel.
1989 * Wake up socket sleeping on accept.
1990 */
1991 parent->sk_data_ready(parent, 0);
1992 }
1993}
1994
1995/* Copy frame to all raw sockets on that connection */
1996static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1997{
1998 struct l2cap_chan_list *l = &conn->chan_list;
1999 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002000 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
2002 BT_DBG("conn %p", conn);
2003
2004 read_lock(&l->lock);
2005 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2006 if (sk->sk_type != SOCK_RAW)
2007 continue;
2008
2009 /* Don't send frame to the socket it came from */
2010 if (skb->sk == sk)
2011 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002012 nskb = skb_clone(skb, GFP_ATOMIC);
2013 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 continue;
2015
2016 if (sock_queue_rcv_skb(sk, nskb))
2017 kfree_skb(nskb);
2018 }
2019 read_unlock(&l->lock);
2020}
2021
2022/* ---- L2CAP signalling commands ---- */
2023static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2024 u8 code, u8 ident, u16 dlen, void *data)
2025{
2026 struct sk_buff *skb, **frag;
2027 struct l2cap_cmd_hdr *cmd;
2028 struct l2cap_hdr *lh;
2029 int len, count;
2030
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002031 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2032 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2035 count = min_t(unsigned int, conn->mtu, len);
2036
2037 skb = bt_skb_alloc(count, GFP_ATOMIC);
2038 if (!skb)
2039 return NULL;
2040
2041 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002042 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002043 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
2045 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2046 cmd->code = code;
2047 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002048 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
2050 if (dlen) {
2051 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2052 memcpy(skb_put(skb, count), data, count);
2053 data += count;
2054 }
2055
2056 len -= skb->len;
2057
2058 /* Continuation fragments (no L2CAP header) */
2059 frag = &skb_shinfo(skb)->frag_list;
2060 while (len) {
2061 count = min_t(unsigned int, conn->mtu, len);
2062
2063 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2064 if (!*frag)
2065 goto fail;
2066
2067 memcpy(skb_put(*frag, count), data, count);
2068
2069 len -= count;
2070 data += count;
2071
2072 frag = &(*frag)->next;
2073 }
2074
2075 return skb;
2076
2077fail:
2078 kfree_skb(skb);
2079 return NULL;
2080}
2081
2082static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2083{
2084 struct l2cap_conf_opt *opt = *ptr;
2085 int len;
2086
2087 len = L2CAP_CONF_OPT_SIZE + opt->len;
2088 *ptr += len;
2089
2090 *type = opt->type;
2091 *olen = opt->len;
2092
2093 switch (opt->len) {
2094 case 1:
2095 *val = *((u8 *) opt->val);
2096 break;
2097
2098 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002099 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 break;
2101
2102 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002103 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 break;
2105
2106 default:
2107 *val = (unsigned long) opt->val;
2108 break;
2109 }
2110
2111 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2112 return len;
2113}
2114
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2116{
2117 struct l2cap_conf_opt *opt = *ptr;
2118
2119 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2120
2121 opt->type = type;
2122 opt->len = len;
2123
2124 switch (len) {
2125 case 1:
2126 *((u8 *) opt->val) = val;
2127 break;
2128
2129 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002130 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 break;
2132
2133 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002134 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 break;
2136
2137 default:
2138 memcpy(opt->val, (void *) val, len);
2139 break;
2140 }
2141
2142 *ptr += L2CAP_CONF_OPT_SIZE + len;
2143}
2144
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002145static void l2cap_ack_timeout(unsigned long arg)
2146{
2147 struct sock *sk = (void *) arg;
2148
2149 bh_lock_sock(sk);
2150 l2cap_send_ack(l2cap_pi(sk));
2151 bh_unlock_sock(sk);
2152}
2153
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002154static inline void l2cap_ertm_init(struct sock *sk)
2155{
2156 l2cap_pi(sk)->expected_ack_seq = 0;
2157 l2cap_pi(sk)->unacked_frames = 0;
2158 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002159 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002160 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002161
2162 setup_timer(&l2cap_pi(sk)->retrans_timer,
2163 l2cap_retrans_timeout, (unsigned long) sk);
2164 setup_timer(&l2cap_pi(sk)->monitor_timer,
2165 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002166 setup_timer(&l2cap_pi(sk)->ack_timer,
2167 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002168
2169 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002170 __skb_queue_head_init(BUSY_QUEUE(sk));
2171
2172 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03002173
2174 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002175}
2176
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002177static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2178{
2179 switch (mode) {
2180 case L2CAP_MODE_STREAMING:
2181 case L2CAP_MODE_ERTM:
2182 if (l2cap_mode_supported(mode, remote_feat_mask))
2183 return mode;
2184 /* fall through */
2185 default:
2186 return L2CAP_MODE_BASIC;
2187 }
2188}
2189
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190static int l2cap_build_conf_req(struct sock *sk, void *data)
2191{
2192 struct l2cap_pinfo *pi = l2cap_pi(sk);
2193 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002194 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 void *ptr = req->data;
2196
2197 BT_DBG("sk %p", sk);
2198
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002199 if (pi->num_conf_req || pi->num_conf_rsp)
2200 goto done;
2201
2202 switch (pi->mode) {
2203 case L2CAP_MODE_STREAMING:
2204 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002205 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002206 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002207
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002208 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002209 default:
2210 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2211 break;
2212 }
2213
2214done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002215 if (pi->imtu != L2CAP_DEFAULT_MTU)
2216 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
2217
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002218 switch (pi->mode) {
2219 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002220 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2221 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
2222 break;
2223
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002224 rfc.mode = L2CAP_MODE_BASIC;
2225 rfc.txwin_size = 0;
2226 rfc.max_transmit = 0;
2227 rfc.retrans_timeout = 0;
2228 rfc.monitor_timeout = 0;
2229 rfc.max_pdu_size = 0;
2230
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002231 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2232 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002233 break;
2234
2235 case L2CAP_MODE_ERTM:
2236 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002237 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002238 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002239 rfc.retrans_timeout = 0;
2240 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002241 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002242 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002243 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002244
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002245 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2246 (unsigned long) &rfc);
2247
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002248 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2249 break;
2250
2251 if (pi->fcs == L2CAP_FCS_NONE ||
2252 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2253 pi->fcs = L2CAP_FCS_NONE;
2254 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2255 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002256 break;
2257
2258 case L2CAP_MODE_STREAMING:
2259 rfc.mode = L2CAP_MODE_STREAMING;
2260 rfc.txwin_size = 0;
2261 rfc.max_transmit = 0;
2262 rfc.retrans_timeout = 0;
2263 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002264 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002265 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002266 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002267
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002268 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2269 (unsigned long) &rfc);
2270
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002271 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2272 break;
2273
2274 if (pi->fcs == L2CAP_FCS_NONE ||
2275 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2276 pi->fcs = L2CAP_FCS_NONE;
2277 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2278 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002279 break;
2280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
2282 /* FIXME: Need actual value of the flush timeout */
2283 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2284 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2285
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002286 req->dcid = cpu_to_le16(pi->dcid);
2287 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
2289 return ptr - data;
2290}
2291
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293{
2294 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002295 struct l2cap_conf_rsp *rsp = data;
2296 void *ptr = rsp->data;
2297 void *req = pi->conf_req;
2298 int len = pi->conf_len;
2299 int type, hint, olen;
2300 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002301 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002302 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002303 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002305 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002306
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002307 while (len >= L2CAP_CONF_OPT_SIZE) {
2308 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002310 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002311 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002312
2313 switch (type) {
2314 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002315 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002316 break;
2317
2318 case L2CAP_CONF_FLUSH_TO:
2319 pi->flush_to = val;
2320 break;
2321
2322 case L2CAP_CONF_QOS:
2323 break;
2324
Marcel Holtmann6464f352007-10-20 13:39:51 +02002325 case L2CAP_CONF_RFC:
2326 if (olen == sizeof(rfc))
2327 memcpy(&rfc, (void *) val, olen);
2328 break;
2329
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002330 case L2CAP_CONF_FCS:
2331 if (val == L2CAP_FCS_NONE)
2332 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2333
2334 break;
2335
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002336 default:
2337 if (hint)
2338 break;
2339
2340 result = L2CAP_CONF_UNKNOWN;
2341 *((u8 *) ptr++) = type;
2342 break;
2343 }
2344 }
2345
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002346 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002347 goto done;
2348
2349 switch (pi->mode) {
2350 case L2CAP_MODE_STREAMING:
2351 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002352 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
2353 pi->mode = l2cap_select_mode(rfc.mode,
2354 pi->conn->feat_mask);
2355 break;
2356 }
2357
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002358 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002359 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002360
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002361 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002362 }
2363
2364done:
2365 if (pi->mode != rfc.mode) {
2366 result = L2CAP_CONF_UNACCEPT;
2367 rfc.mode = pi->mode;
2368
2369 if (pi->num_conf_rsp == 1)
2370 return -ECONNREFUSED;
2371
2372 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2373 sizeof(rfc), (unsigned long) &rfc);
2374 }
2375
2376
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002377 if (result == L2CAP_CONF_SUCCESS) {
2378 /* Configure output options and let the other side know
2379 * which ones we don't like. */
2380
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002381 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2382 result = L2CAP_CONF_UNACCEPT;
2383 else {
2384 pi->omtu = mtu;
2385 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2386 }
2387 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002388
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389 switch (rfc.mode) {
2390 case L2CAP_MODE_BASIC:
2391 pi->fcs = L2CAP_FCS_NONE;
2392 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2393 break;
2394
2395 case L2CAP_MODE_ERTM:
2396 pi->remote_tx_win = rfc.txwin_size;
2397 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002398
2399 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2400 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002401
2402 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002403
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002404 rfc.retrans_timeout =
2405 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2406 rfc.monitor_timeout =
2407 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002408
2409 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002410
2411 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2412 sizeof(rfc), (unsigned long) &rfc);
2413
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002414 break;
2415
2416 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07002417 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2418 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002419
2420 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002421
2422 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002423
2424 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2425 sizeof(rfc), (unsigned long) &rfc);
2426
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002427 break;
2428
2429 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002430 result = L2CAP_CONF_UNACCEPT;
2431
2432 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002433 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002434 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002435
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002436 if (result == L2CAP_CONF_SUCCESS)
2437 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2438 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002439 rsp->scid = cpu_to_le16(pi->dcid);
2440 rsp->result = cpu_to_le16(result);
2441 rsp->flags = cpu_to_le16(0x0000);
2442
2443 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444}
2445
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002446static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2447{
2448 struct l2cap_pinfo *pi = l2cap_pi(sk);
2449 struct l2cap_conf_req *req = data;
2450 void *ptr = req->data;
2451 int type, olen;
2452 unsigned long val;
2453 struct l2cap_conf_rfc rfc;
2454
2455 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2456
2457 while (len >= L2CAP_CONF_OPT_SIZE) {
2458 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2459
2460 switch (type) {
2461 case L2CAP_CONF_MTU:
2462 if (val < L2CAP_DEFAULT_MIN_MTU) {
2463 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002464 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002465 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002466 pi->imtu = val;
2467 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002468 break;
2469
2470 case L2CAP_CONF_FLUSH_TO:
2471 pi->flush_to = val;
2472 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2473 2, pi->flush_to);
2474 break;
2475
2476 case L2CAP_CONF_RFC:
2477 if (olen == sizeof(rfc))
2478 memcpy(&rfc, (void *)val, olen);
2479
2480 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2481 rfc.mode != pi->mode)
2482 return -ECONNREFUSED;
2483
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002484 pi->fcs = 0;
2485
2486 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2487 sizeof(rfc), (unsigned long) &rfc);
2488 break;
2489 }
2490 }
2491
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002492 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
2493 return -ECONNREFUSED;
2494
2495 pi->mode = rfc.mode;
2496
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002497 if (*result == L2CAP_CONF_SUCCESS) {
2498 switch (rfc.mode) {
2499 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002500 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2501 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002502 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002503 break;
2504 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002505 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002506 }
2507 }
2508
2509 req->dcid = cpu_to_le16(pi->dcid);
2510 req->flags = cpu_to_le16(0x0000);
2511
2512 return ptr - data;
2513}
2514
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002515static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516{
2517 struct l2cap_conf_rsp *rsp = data;
2518 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002520 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002522 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002523 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002524 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
2526 return ptr - data;
2527}
2528
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002529static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2530{
2531 struct l2cap_pinfo *pi = l2cap_pi(sk);
2532 int type, olen;
2533 unsigned long val;
2534 struct l2cap_conf_rfc rfc;
2535
2536 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2537
2538 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2539 return;
2540
2541 while (len >= L2CAP_CONF_OPT_SIZE) {
2542 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2543
2544 switch (type) {
2545 case L2CAP_CONF_RFC:
2546 if (olen == sizeof(rfc))
2547 memcpy(&rfc, (void *)val, olen);
2548 goto done;
2549 }
2550 }
2551
2552done:
2553 switch (rfc.mode) {
2554 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002555 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2556 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002557 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2558 break;
2559 case L2CAP_MODE_STREAMING:
2560 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2561 }
2562}
2563
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002564static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2565{
2566 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2567
2568 if (rej->reason != 0x0000)
2569 return 0;
2570
2571 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2572 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002573 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002574
2575 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002576 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002577
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002578 l2cap_conn_start(conn);
2579 }
2580
2581 return 0;
2582}
2583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2585{
2586 struct l2cap_chan_list *list = &conn->chan_list;
2587 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2588 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002589 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002590 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
2592 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002593 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
2595 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2596
2597 /* Check if we have socket listening on psm */
2598 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2599 if (!parent) {
2600 result = L2CAP_CR_BAD_PSM;
2601 goto sendresp;
2602 }
2603
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002604 bh_lock_sock(parent);
2605
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002606 /* Check if the ACL is secure enough (if not SDP) */
2607 if (psm != cpu_to_le16(0x0001) &&
2608 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002609 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002610 result = L2CAP_CR_SEC_BLOCK;
2611 goto response;
2612 }
2613
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 result = L2CAP_CR_NO_MEM;
2615
2616 /* Check for backlog size */
2617 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002618 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 goto response;
2620 }
2621
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002622 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 if (!sk)
2624 goto response;
2625
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002626 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
2628 /* Check if we already have channel with that dcid */
2629 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002630 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 sock_set_flag(sk, SOCK_ZAPPED);
2632 l2cap_sock_kill(sk);
2633 goto response;
2634 }
2635
2636 hci_conn_hold(conn->hcon);
2637
2638 l2cap_sock_init(sk, parent);
2639 bacpy(&bt_sk(sk)->src, conn->src);
2640 bacpy(&bt_sk(sk)->dst, conn->dst);
2641 l2cap_pi(sk)->psm = psm;
2642 l2cap_pi(sk)->dcid = scid;
2643
2644 __l2cap_chan_add(conn, sk, parent);
2645 dcid = l2cap_pi(sk)->scid;
2646
2647 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2648
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 l2cap_pi(sk)->ident = cmd->ident;
2650
Marcel Holtmann984947d2009-02-06 23:35:19 +01002651 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002652 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002653 if (bt_sk(sk)->defer_setup) {
2654 sk->sk_state = BT_CONNECT2;
2655 result = L2CAP_CR_PEND;
2656 status = L2CAP_CS_AUTHOR_PEND;
2657 parent->sk_data_ready(parent, 0);
2658 } else {
2659 sk->sk_state = BT_CONFIG;
2660 result = L2CAP_CR_SUCCESS;
2661 status = L2CAP_CS_NO_INFO;
2662 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002663 } else {
2664 sk->sk_state = BT_CONNECT2;
2665 result = L2CAP_CR_PEND;
2666 status = L2CAP_CS_AUTHEN_PEND;
2667 }
2668 } else {
2669 sk->sk_state = BT_CONNECT2;
2670 result = L2CAP_CR_PEND;
2671 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 }
2673
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002674 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
2676response:
2677 bh_unlock_sock(parent);
2678
2679sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002680 rsp.scid = cpu_to_le16(scid);
2681 rsp.dcid = cpu_to_le16(dcid);
2682 rsp.result = cpu_to_le16(result);
2683 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002685
2686 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2687 struct l2cap_info_req info;
2688 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2689
2690 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2691 conn->info_ident = l2cap_get_ident(conn);
2692
2693 mod_timer(&conn->info_timer, jiffies +
2694 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2695
2696 l2cap_send_cmd(conn, conn->info_ident,
2697 L2CAP_INFO_REQ, sizeof(info), &info);
2698 }
2699
Nathan Holsteind793fe82010-10-15 11:54:02 -04002700 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002701 result == L2CAP_CR_SUCCESS) {
2702 u8 buf[128];
2703 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2704 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2705 l2cap_build_conf_req(sk, buf), buf);
2706 l2cap_pi(sk)->num_conf_req++;
2707 }
2708
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 return 0;
2710}
2711
2712static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2713{
2714 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2715 u16 scid, dcid, result, status;
2716 struct sock *sk;
2717 u8 req[128];
2718
2719 scid = __le16_to_cpu(rsp->scid);
2720 dcid = __le16_to_cpu(rsp->dcid);
2721 result = __le16_to_cpu(rsp->result);
2722 status = __le16_to_cpu(rsp->status);
2723
2724 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2725
2726 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002727 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2728 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002729 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002731 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2732 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002733 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 }
2735
2736 switch (result) {
2737 case L2CAP_CR_SUCCESS:
2738 sk->sk_state = BT_CONFIG;
2739 l2cap_pi(sk)->ident = 0;
2740 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002741 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2742
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002743 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2744 break;
2745
2746 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2747
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2749 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002750 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 break;
2752
2753 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002754 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 break;
2756
2757 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002758 /* don't delete l2cap channel if sk is owned by user */
2759 if (sock_owned_by_user(sk)) {
2760 sk->sk_state = BT_DISCONN;
2761 l2cap_sock_clear_timer(sk);
2762 l2cap_sock_set_timer(sk, HZ / 5);
2763 break;
2764 }
2765
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 l2cap_chan_del(sk, ECONNREFUSED);
2767 break;
2768 }
2769
2770 bh_unlock_sock(sk);
2771 return 0;
2772}
2773
Mat Martineau8c462b62010-08-24 15:35:42 -07002774static inline void set_default_fcs(struct l2cap_pinfo *pi)
2775{
2776 /* FCS is enabled only in ERTM or streaming mode, if one or both
2777 * sides request it.
2778 */
2779 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2780 pi->fcs = L2CAP_FCS_NONE;
2781 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2782 pi->fcs = L2CAP_FCS_CRC16;
2783}
2784
Al Viro88219a02007-07-29 00:17:25 -07002785static 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 -07002786{
2787 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2788 u16 dcid, flags;
2789 u8 rsp[64];
2790 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002791 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
2793 dcid = __le16_to_cpu(req->dcid);
2794 flags = __le16_to_cpu(req->flags);
2795
2796 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2797
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002798 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2799 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 return -ENOENT;
2801
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002802 if (sk->sk_state != BT_CONFIG) {
2803 struct l2cap_cmd_rej rej;
2804
2805 rej.reason = cpu_to_le16(0x0002);
2806 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2807 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002808 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002809 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002810
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002811 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002812 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002813 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2814 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2815 l2cap_build_conf_rsp(sk, rsp,
2816 L2CAP_CONF_REJECT, flags), rsp);
2817 goto unlock;
2818 }
2819
2820 /* Store config. */
2821 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2822 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
2824 if (flags & 0x0001) {
2825 /* Incomplete config. Send empty response. */
2826 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002827 l2cap_build_conf_rsp(sk, rsp,
2828 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 goto unlock;
2830 }
2831
2832 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002833 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002834 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002835 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002839 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002840 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002841
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002842 /* Reset config buffer. */
2843 l2cap_pi(sk)->conf_len = 0;
2844
Marcel Holtmann876d9482007-10-20 13:35:42 +02002845 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2846 goto unlock;
2847
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002849 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002850
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002852
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002853 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002854 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002855 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002856 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2857 l2cap_ertm_init(sk);
2858
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002860 goto unlock;
2861 }
2862
2863 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002864 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002865 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002867 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002868 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 }
2870
2871unlock:
2872 bh_unlock_sock(sk);
2873 return 0;
2874}
2875
2876static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2877{
2878 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2879 u16 scid, flags, result;
2880 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002881 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
2883 scid = __le16_to_cpu(rsp->scid);
2884 flags = __le16_to_cpu(rsp->flags);
2885 result = __le16_to_cpu(rsp->result);
2886
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002887 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2888 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002890 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2891 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 return 0;
2893
2894 switch (result) {
2895 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002896 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 break;
2898
2899 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002900 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002901 char req[64];
2902
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002903 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002904 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002905 goto done;
2906 }
2907
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002908 /* throw out any old stored conf requests */
2909 result = L2CAP_CONF_SUCCESS;
2910 len = l2cap_parse_conf_rsp(sk, rsp->data,
2911 len, req, &result);
2912 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002913 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002914 goto done;
2915 }
2916
2917 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2918 L2CAP_CONF_REQ, len, req);
2919 l2cap_pi(sk)->num_conf_req++;
2920 if (result != L2CAP_CONF_SUCCESS)
2921 goto done;
2922 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 }
2924
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002925 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002926 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002928 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 goto done;
2930 }
2931
2932 if (flags & 0x01)
2933 goto done;
2934
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2936
2937 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002938 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002939
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002941 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002942 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002943 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002944 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2945 l2cap_ertm_init(sk);
2946
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 l2cap_chan_ready(sk);
2948 }
2949
2950done:
2951 bh_unlock_sock(sk);
2952 return 0;
2953}
2954
2955static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2956{
2957 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2958 struct l2cap_disconn_rsp rsp;
2959 u16 dcid, scid;
2960 struct sock *sk;
2961
2962 scid = __le16_to_cpu(req->scid);
2963 dcid = __le16_to_cpu(req->dcid);
2964
2965 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2966
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002967 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2968 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 return 0;
2970
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002971 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2972 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2974
2975 sk->sk_shutdown = SHUTDOWN_MASK;
2976
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002977 /* don't delete l2cap channel if sk is owned by user */
2978 if (sock_owned_by_user(sk)) {
2979 sk->sk_state = BT_DISCONN;
2980 l2cap_sock_clear_timer(sk);
2981 l2cap_sock_set_timer(sk, HZ / 5);
2982 bh_unlock_sock(sk);
2983 return 0;
2984 }
2985
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 l2cap_chan_del(sk, ECONNRESET);
2987 bh_unlock_sock(sk);
2988
2989 l2cap_sock_kill(sk);
2990 return 0;
2991}
2992
2993static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2994{
2995 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2996 u16 dcid, scid;
2997 struct sock *sk;
2998
2999 scid = __le16_to_cpu(rsp->scid);
3000 dcid = __le16_to_cpu(rsp->dcid);
3001
3002 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3003
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003004 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3005 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 return 0;
3007
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003008 /* don't delete l2cap channel if sk is owned by user */
3009 if (sock_owned_by_user(sk)) {
3010 sk->sk_state = BT_DISCONN;
3011 l2cap_sock_clear_timer(sk);
3012 l2cap_sock_set_timer(sk, HZ / 5);
3013 bh_unlock_sock(sk);
3014 return 0;
3015 }
3016
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 l2cap_chan_del(sk, 0);
3018 bh_unlock_sock(sk);
3019
3020 l2cap_sock_kill(sk);
3021 return 0;
3022}
3023
3024static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3025{
3026 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 u16 type;
3028
3029 type = __le16_to_cpu(req->type);
3030
3031 BT_DBG("type 0x%4.4x", type);
3032
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003033 if (type == L2CAP_IT_FEAT_MASK) {
3034 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003035 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003036 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3037 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3038 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003039 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003040 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3041 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003042 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003043 l2cap_send_cmd(conn, cmd->ident,
3044 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003045 } else if (type == L2CAP_IT_FIXED_CHAN) {
3046 u8 buf[12];
3047 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3048 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3049 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3050 memcpy(buf + 4, l2cap_fixed_chan, 8);
3051 l2cap_send_cmd(conn, cmd->ident,
3052 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003053 } else {
3054 struct l2cap_info_rsp rsp;
3055 rsp.type = cpu_to_le16(type);
3056 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3057 l2cap_send_cmd(conn, cmd->ident,
3058 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
3061 return 0;
3062}
3063
3064static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3065{
3066 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3067 u16 type, result;
3068
3069 type = __le16_to_cpu(rsp->type);
3070 result = __le16_to_cpu(rsp->result);
3071
3072 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3073
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003074 del_timer(&conn->info_timer);
3075
Ville Tervoadb08ed2010-08-04 09:43:33 +03003076 if (result != L2CAP_IR_SUCCESS) {
3077 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3078 conn->info_ident = 0;
3079
3080 l2cap_conn_start(conn);
3081
3082 return 0;
3083 }
3084
Marcel Holtmann984947d2009-02-06 23:35:19 +01003085 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003086 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003087
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003088 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003089 struct l2cap_info_req req;
3090 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3091
3092 conn->info_ident = l2cap_get_ident(conn);
3093
3094 l2cap_send_cmd(conn, conn->info_ident,
3095 L2CAP_INFO_REQ, sizeof(req), &req);
3096 } else {
3097 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3098 conn->info_ident = 0;
3099
3100 l2cap_conn_start(conn);
3101 }
3102 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003103 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003104 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003105
3106 l2cap_conn_start(conn);
3107 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003108
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 return 0;
3110}
3111
3112static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3113{
3114 u8 *data = skb->data;
3115 int len = skb->len;
3116 struct l2cap_cmd_hdr cmd;
3117 int err = 0;
3118
3119 l2cap_raw_recv(conn, skb);
3120
3121 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003122 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3124 data += L2CAP_CMD_HDR_SIZE;
3125 len -= L2CAP_CMD_HDR_SIZE;
3126
Al Viro88219a02007-07-29 00:17:25 -07003127 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Al Viro88219a02007-07-29 00:17:25 -07003129 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 -07003130
Al Viro88219a02007-07-29 00:17:25 -07003131 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 BT_DBG("corrupted command");
3133 break;
3134 }
3135
3136 switch (cmd.code) {
3137 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003138 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 break;
3140
3141 case L2CAP_CONN_REQ:
3142 err = l2cap_connect_req(conn, &cmd, data);
3143 break;
3144
3145 case L2CAP_CONN_RSP:
3146 err = l2cap_connect_rsp(conn, &cmd, data);
3147 break;
3148
3149 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003150 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 break;
3152
3153 case L2CAP_CONF_RSP:
3154 err = l2cap_config_rsp(conn, &cmd, data);
3155 break;
3156
3157 case L2CAP_DISCONN_REQ:
3158 err = l2cap_disconnect_req(conn, &cmd, data);
3159 break;
3160
3161 case L2CAP_DISCONN_RSP:
3162 err = l2cap_disconnect_rsp(conn, &cmd, data);
3163 break;
3164
3165 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003166 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 break;
3168
3169 case L2CAP_ECHO_RSP:
3170 break;
3171
3172 case L2CAP_INFO_REQ:
3173 err = l2cap_information_req(conn, &cmd, data);
3174 break;
3175
3176 case L2CAP_INFO_RSP:
3177 err = l2cap_information_rsp(conn, &cmd, data);
3178 break;
3179
3180 default:
3181 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3182 err = -EINVAL;
3183 break;
3184 }
3185
3186 if (err) {
3187 struct l2cap_cmd_rej rej;
3188 BT_DBG("error %d", err);
3189
3190 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003191 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3193 }
3194
Al Viro88219a02007-07-29 00:17:25 -07003195 data += cmd_len;
3196 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 }
3198
3199 kfree_skb(skb);
3200}
3201
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003202static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3203{
3204 u16 our_fcs, rcv_fcs;
3205 int hdr_size = L2CAP_HDR_SIZE + 2;
3206
3207 if (pi->fcs == L2CAP_FCS_CRC16) {
3208 skb_trim(skb, skb->len - 2);
3209 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3210 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3211
3212 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003213 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003214 }
3215 return 0;
3216}
3217
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003218static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3219{
3220 struct l2cap_pinfo *pi = l2cap_pi(sk);
3221 u16 control = 0;
3222
3223 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003224
3225 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3226
3227 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003228 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003229 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003230 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003231 }
3232
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003233 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3234 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003235
3236 l2cap_ertm_send(sk);
3237
3238 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3239 pi->frames_sent == 0) {
3240 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003241 l2cap_send_sframe(pi, control);
3242 }
3243}
3244
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003245static 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 -03003246{
3247 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003248 struct l2cap_pinfo *pi = l2cap_pi(sk);
3249 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003250
3251 bt_cb(skb)->tx_seq = tx_seq;
3252 bt_cb(skb)->sar = sar;
3253
3254 next_skb = skb_peek(SREJ_QUEUE(sk));
3255 if (!next_skb) {
3256 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003257 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003258 }
3259
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003260 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3261 if (tx_seq_offset < 0)
3262 tx_seq_offset += 64;
3263
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003264 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003265 if (bt_cb(next_skb)->tx_seq == tx_seq)
3266 return -EINVAL;
3267
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003268 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3269 pi->buffer_seq) % 64;
3270 if (next_tx_seq_offset < 0)
3271 next_tx_seq_offset += 64;
3272
3273 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003274 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003275 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003276 }
3277
3278 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3279 break;
3280
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003281 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003282
3283 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003284
3285 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003286}
3287
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003288static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3289{
3290 struct l2cap_pinfo *pi = l2cap_pi(sk);
3291 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003292 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003293
3294 switch (control & L2CAP_CTRL_SAR) {
3295 case L2CAP_SDU_UNSEGMENTED:
3296 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3297 goto drop;
3298
3299 err = sock_queue_rcv_skb(sk, skb);
3300 if (!err)
3301 return err;
3302
3303 break;
3304
3305 case L2CAP_SDU_START:
3306 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3307 goto drop;
3308
3309 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003310
3311 if (pi->sdu_len > pi->imtu)
3312 goto disconnect;
3313
3314 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003315 if (!pi->sdu)
3316 return -ENOMEM;
3317
3318 /* pull sdu_len bytes only after alloc, because of Local Busy
3319 * condition we have to be sure that this will be executed
3320 * only once, i.e., when alloc does not fail */
3321 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003322
3323 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3324
3325 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3326 pi->partial_sdu_len = skb->len;
3327 break;
3328
3329 case L2CAP_SDU_CONTINUE:
3330 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3331 goto disconnect;
3332
3333 if (!pi->sdu)
3334 goto disconnect;
3335
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003336 pi->partial_sdu_len += skb->len;
3337 if (pi->partial_sdu_len > pi->sdu_len)
3338 goto drop;
3339
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003340 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3341
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003342 break;
3343
3344 case L2CAP_SDU_END:
3345 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3346 goto disconnect;
3347
3348 if (!pi->sdu)
3349 goto disconnect;
3350
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003351 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003352 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003353
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003354 if (pi->partial_sdu_len > pi->imtu)
3355 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003356
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003357 if (pi->partial_sdu_len != pi->sdu_len)
3358 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003359
3360 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003361 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003362
3363 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003364 if (!_skb) {
3365 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3366 return -ENOMEM;
3367 }
3368
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003369 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003370 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003371 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003372 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3373 return err;
3374 }
3375
3376 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3377 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003378
3379 kfree_skb(pi->sdu);
3380 break;
3381 }
3382
3383 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003384 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003385
3386drop:
3387 kfree_skb(pi->sdu);
3388 pi->sdu = NULL;
3389
3390disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003391 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003392 kfree_skb(skb);
3393 return 0;
3394}
3395
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003396static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003397{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003398 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003399 struct sk_buff *skb;
3400 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003401 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003402
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003403 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3404 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3405 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3406 if (err < 0) {
3407 skb_queue_head(BUSY_QUEUE(sk), skb);
3408 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003409 }
3410
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003411 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003412 }
3413
3414 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3415 goto done;
3416
3417 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3418 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3419 l2cap_send_sframe(pi, control);
3420 l2cap_pi(sk)->retry_count = 1;
3421
3422 del_timer(&pi->retrans_timer);
3423 __mod_monitor_timer();
3424
3425 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3426
3427done:
3428 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3429 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3430
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003431 BT_DBG("sk %p, Exit local busy", sk);
3432
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003433 return 0;
3434}
3435
3436static void l2cap_busy_work(struct work_struct *work)
3437{
3438 DECLARE_WAITQUEUE(wait, current);
3439 struct l2cap_pinfo *pi =
3440 container_of(work, struct l2cap_pinfo, busy_work);
3441 struct sock *sk = (struct sock *)pi;
3442 int n_tries = 0, timeo = HZ/5, err;
3443 struct sk_buff *skb;
3444
3445 lock_sock(sk);
3446
3447 add_wait_queue(sk_sleep(sk), &wait);
3448 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3449 set_current_state(TASK_INTERRUPTIBLE);
3450
3451 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3452 err = -EBUSY;
3453 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3454 break;
3455 }
3456
3457 if (!timeo)
3458 timeo = HZ/5;
3459
3460 if (signal_pending(current)) {
3461 err = sock_intr_errno(timeo);
3462 break;
3463 }
3464
3465 release_sock(sk);
3466 timeo = schedule_timeout(timeo);
3467 lock_sock(sk);
3468
3469 err = sock_error(sk);
3470 if (err)
3471 break;
3472
3473 if (l2cap_try_push_rx_skb(sk) == 0)
3474 break;
3475 }
3476
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003477 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003478 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003479
3480 release_sock(sk);
3481}
3482
3483static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3484{
3485 struct l2cap_pinfo *pi = l2cap_pi(sk);
3486 int sctrl, err;
3487
3488 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3489 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3490 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003491 return l2cap_try_push_rx_skb(sk);
3492
3493
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003494 }
3495
3496 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3497 if (err >= 0) {
3498 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3499 return err;
3500 }
3501
3502 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003503 BT_DBG("sk %p, Enter local busy", sk);
3504
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003505 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3506 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3507 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3508
3509 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3510 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3511 l2cap_send_sframe(pi, sctrl);
3512
3513 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3514
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003515 del_timer(&pi->ack_timer);
3516
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003517 queue_work(_busy_wq, &pi->busy_work);
3518
3519 return err;
3520}
3521
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003522static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003523{
3524 struct l2cap_pinfo *pi = l2cap_pi(sk);
3525 struct sk_buff *_skb;
3526 int err = -EINVAL;
3527
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003528 /*
3529 * TODO: We have to notify the userland if some data is lost with the
3530 * Streaming Mode.
3531 */
3532
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003533 switch (control & L2CAP_CTRL_SAR) {
3534 case L2CAP_SDU_UNSEGMENTED:
3535 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3536 kfree_skb(pi->sdu);
3537 break;
3538 }
3539
3540 err = sock_queue_rcv_skb(sk, skb);
3541 if (!err)
3542 return 0;
3543
3544 break;
3545
3546 case L2CAP_SDU_START:
3547 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3548 kfree_skb(pi->sdu);
3549 break;
3550 }
3551
3552 pi->sdu_len = get_unaligned_le16(skb->data);
3553 skb_pull(skb, 2);
3554
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003555 if (pi->sdu_len > pi->imtu) {
3556 err = -EMSGSIZE;
3557 break;
3558 }
3559
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003560 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3561 if (!pi->sdu) {
3562 err = -ENOMEM;
3563 break;
3564 }
3565
3566 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3567
3568 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3569 pi->partial_sdu_len = skb->len;
3570 err = 0;
3571 break;
3572
3573 case L2CAP_SDU_CONTINUE:
3574 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3575 break;
3576
3577 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3578
3579 pi->partial_sdu_len += skb->len;
3580 if (pi->partial_sdu_len > pi->sdu_len)
3581 kfree_skb(pi->sdu);
3582 else
3583 err = 0;
3584
3585 break;
3586
3587 case L2CAP_SDU_END:
3588 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3589 break;
3590
3591 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3592
3593 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3594 pi->partial_sdu_len += skb->len;
3595
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003596 if (pi->partial_sdu_len > pi->imtu)
3597 goto drop;
3598
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003599 if (pi->partial_sdu_len == pi->sdu_len) {
3600 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3601 err = sock_queue_rcv_skb(sk, _skb);
3602 if (err < 0)
3603 kfree_skb(_skb);
3604 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003605 err = 0;
3606
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003607drop:
3608 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003609 break;
3610 }
3611
3612 kfree_skb(skb);
3613 return err;
3614}
3615
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003616static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3617{
3618 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003619 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003620
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003621 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003622 if (bt_cb(skb)->tx_seq != tx_seq)
3623 break;
3624
3625 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003626 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003627 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003628 l2cap_pi(sk)->buffer_seq_srej =
3629 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003630 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003631 }
3632}
3633
3634static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3635{
3636 struct l2cap_pinfo *pi = l2cap_pi(sk);
3637 struct srej_list *l, *tmp;
3638 u16 control;
3639
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003640 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003641 if (l->tx_seq == tx_seq) {
3642 list_del(&l->list);
3643 kfree(l);
3644 return;
3645 }
3646 control = L2CAP_SUPER_SELECT_REJECT;
3647 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3648 l2cap_send_sframe(pi, control);
3649 list_del(&l->list);
3650 list_add_tail(&l->list, SREJ_LIST(sk));
3651 }
3652}
3653
3654static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3655{
3656 struct l2cap_pinfo *pi = l2cap_pi(sk);
3657 struct srej_list *new;
3658 u16 control;
3659
3660 while (tx_seq != pi->expected_tx_seq) {
3661 control = L2CAP_SUPER_SELECT_REJECT;
3662 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3663 l2cap_send_sframe(pi, control);
3664
3665 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003666 new->tx_seq = pi->expected_tx_seq;
3667 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003668 list_add_tail(&new->list, SREJ_LIST(sk));
3669 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003670 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003671}
3672
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003673static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3674{
3675 struct l2cap_pinfo *pi = l2cap_pi(sk);
3676 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003677 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003678 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003679 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003680 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003681 int err = 0;
3682
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003683 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3684 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003685
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003686 if (L2CAP_CTRL_FINAL & rx_control &&
3687 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003688 del_timer(&pi->monitor_timer);
3689 if (pi->unacked_frames > 0)
3690 __mod_retrans_timer();
3691 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3692 }
3693
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003694 pi->expected_ack_seq = req_seq;
3695 l2cap_drop_acked_frames(sk);
3696
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003697 if (tx_seq == pi->expected_tx_seq)
3698 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003699
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003700 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3701 if (tx_seq_offset < 0)
3702 tx_seq_offset += 64;
3703
3704 /* invalid tx_seq */
3705 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003706 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003707 goto drop;
3708 }
3709
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003710 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3711 goto drop;
3712
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003713 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3714 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003715
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003716 first = list_first_entry(SREJ_LIST(sk),
3717 struct srej_list, list);
3718 if (tx_seq == first->tx_seq) {
3719 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3720 l2cap_check_srej_gap(sk, tx_seq);
3721
3722 list_del(&first->list);
3723 kfree(first);
3724
3725 if (list_empty(SREJ_LIST(sk))) {
3726 pi->buffer_seq = pi->buffer_seq_srej;
3727 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003728 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003729 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003730 }
3731 } else {
3732 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003733
3734 /* duplicated tx_seq */
3735 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3736 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003737
3738 list_for_each_entry(l, SREJ_LIST(sk), list) {
3739 if (l->tx_seq == tx_seq) {
3740 l2cap_resend_srejframe(sk, tx_seq);
3741 return 0;
3742 }
3743 }
3744 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003745 }
3746 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003747 expected_tx_seq_offset =
3748 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3749 if (expected_tx_seq_offset < 0)
3750 expected_tx_seq_offset += 64;
3751
3752 /* duplicated tx_seq */
3753 if (tx_seq_offset < expected_tx_seq_offset)
3754 goto drop;
3755
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003756 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003757
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003758 BT_DBG("sk %p, Enter SREJ", sk);
3759
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003760 INIT_LIST_HEAD(SREJ_LIST(sk));
3761 pi->buffer_seq_srej = pi->buffer_seq;
3762
3763 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003765 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3766
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003767 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3768
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003769 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003770
3771 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003772 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003773 return 0;
3774
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003775expected:
3776 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3777
3778 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003779 bt_cb(skb)->tx_seq = tx_seq;
3780 bt_cb(skb)->sar = sar;
3781 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003782 return 0;
3783 }
3784
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003785 err = l2cap_push_rx_skb(sk, skb, rx_control);
3786 if (err < 0)
3787 return 0;
3788
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003789 if (rx_control & L2CAP_CTRL_FINAL) {
3790 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3791 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003792 else
3793 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003794 }
3795
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003796 __mod_ack_timer();
3797
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003798 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3799 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003800 l2cap_send_ack(pi);
3801
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003802 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003803
3804drop:
3805 kfree_skb(skb);
3806 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003807}
3808
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003809static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003810{
3811 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003812
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003813 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3814 rx_control);
3815
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003816 pi->expected_ack_seq = __get_reqseq(rx_control);
3817 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003818
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003819 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003820 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003821 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3822 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3823 (pi->unacked_frames > 0))
3824 __mod_retrans_timer();
3825
3826 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3827 l2cap_send_srejtail(sk);
3828 } else {
3829 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003830 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003831
3832 } else if (rx_control & L2CAP_CTRL_FINAL) {
3833 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003834
3835 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3836 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003837 else
3838 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003839
3840 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003841 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3842 (pi->unacked_frames > 0))
3843 __mod_retrans_timer();
3844
3845 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003846 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003847 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003848 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003849 l2cap_ertm_send(sk);
3850 }
3851}
3852
3853static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3854{
3855 struct l2cap_pinfo *pi = l2cap_pi(sk);
3856 u8 tx_seq = __get_reqseq(rx_control);
3857
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003858 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3859
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003860 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3861
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003862 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003863 l2cap_drop_acked_frames(sk);
3864
3865 if (rx_control & L2CAP_CTRL_FINAL) {
3866 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3867 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003868 else
3869 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003870 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003871 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003872
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003873 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003874 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003875 }
3876}
3877static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3878{
3879 struct l2cap_pinfo *pi = l2cap_pi(sk);
3880 u8 tx_seq = __get_reqseq(rx_control);
3881
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003882 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3883
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003884 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3885
3886 if (rx_control & L2CAP_CTRL_POLL) {
3887 pi->expected_ack_seq = tx_seq;
3888 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003889
3890 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003891 l2cap_retransmit_one_frame(sk, tx_seq);
3892
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003893 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003894
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003895 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3896 pi->srej_save_reqseq = tx_seq;
3897 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3898 }
3899 } else if (rx_control & L2CAP_CTRL_FINAL) {
3900 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3901 pi->srej_save_reqseq == tx_seq)
3902 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3903 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003904 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003905 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003906 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003907 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3908 pi->srej_save_reqseq = tx_seq;
3909 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3910 }
3911 }
3912}
3913
3914static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3915{
3916 struct l2cap_pinfo *pi = l2cap_pi(sk);
3917 u8 tx_seq = __get_reqseq(rx_control);
3918
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003919 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3920
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003921 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3922 pi->expected_ack_seq = tx_seq;
3923 l2cap_drop_acked_frames(sk);
3924
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003925 if (rx_control & L2CAP_CTRL_POLL)
3926 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3927
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003928 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3929 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003930 if (rx_control & L2CAP_CTRL_POLL)
3931 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003932 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003933 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003934
3935 if (rx_control & L2CAP_CTRL_POLL)
3936 l2cap_send_srejtail(sk);
3937 else
3938 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003939}
3940
3941static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3942{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003943 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3944
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003945 if (L2CAP_CTRL_FINAL & rx_control &&
3946 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003947 del_timer(&l2cap_pi(sk)->monitor_timer);
3948 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003949 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003950 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003951 }
3952
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003953 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3954 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003955 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003956 break;
3957
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003958 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003959 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003960 break;
3961
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003962 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003963 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003964 break;
3965
3966 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003967 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003968 break;
3969 }
3970
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003971 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003972 return 0;
3973}
3974
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003975static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3976{
3977 struct l2cap_pinfo *pi = l2cap_pi(sk);
3978 u16 control;
3979 u8 req_seq;
3980 int len, next_tx_seq_offset, req_seq_offset;
3981
3982 control = get_unaligned_le16(skb->data);
3983 skb_pull(skb, 2);
3984 len = skb->len;
3985
3986 /*
3987 * We can just drop the corrupted I-frame here.
3988 * Receiver will miss it and start proper recovery
3989 * procedures and ask retransmission.
3990 */
3991 if (l2cap_check_fcs(pi, skb))
3992 goto drop;
3993
3994 if (__is_sar_start(control) && __is_iframe(control))
3995 len -= 2;
3996
3997 if (pi->fcs == L2CAP_FCS_CRC16)
3998 len -= 2;
3999
4000 if (len > pi->mps) {
4001 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4002 goto drop;
4003 }
4004
4005 req_seq = __get_reqseq(control);
4006 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4007 if (req_seq_offset < 0)
4008 req_seq_offset += 64;
4009
4010 next_tx_seq_offset =
4011 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4012 if (next_tx_seq_offset < 0)
4013 next_tx_seq_offset += 64;
4014
4015 /* check for invalid req-seq */
4016 if (req_seq_offset > next_tx_seq_offset) {
4017 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4018 goto drop;
4019 }
4020
4021 if (__is_iframe(control)) {
4022 if (len < 0) {
4023 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4024 goto drop;
4025 }
4026
4027 l2cap_data_channel_iframe(sk, control, skb);
4028 } else {
4029 if (len != 0) {
4030 BT_ERR("%d", len);
4031 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4032 goto drop;
4033 }
4034
4035 l2cap_data_channel_sframe(sk, control, skb);
4036 }
4037
4038 return 0;
4039
4040drop:
4041 kfree_skb(skb);
4042 return 0;
4043}
4044
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4046{
4047 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004048 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004049 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004050 u8 tx_seq;
4051 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
4053 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4054 if (!sk) {
4055 BT_DBG("unknown cid 0x%4.4x", cid);
4056 goto drop;
4057 }
4058
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004059 pi = l2cap_pi(sk);
4060
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 BT_DBG("sk %p, len %d", sk, skb->len);
4062
4063 if (sk->sk_state != BT_CONNECTED)
4064 goto drop;
4065
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004066 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004067 case L2CAP_MODE_BASIC:
4068 /* If socket recv buffers overflows we drop data here
4069 * which is *bad* because L2CAP has to be reliable.
4070 * But we don't have any other choice. L2CAP doesn't
4071 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004073 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004074 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004076 if (!sock_queue_rcv_skb(sk, skb))
4077 goto done;
4078 break;
4079
4080 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004081 if (!sock_owned_by_user(sk)) {
4082 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004083 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004084 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004085 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004086 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004087
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004088 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004089
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004090 case L2CAP_MODE_STREAMING:
4091 control = get_unaligned_le16(skb->data);
4092 skb_pull(skb, 2);
4093 len = skb->len;
4094
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004095 if (l2cap_check_fcs(pi, skb))
4096 goto drop;
4097
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004098 if (__is_sar_start(control))
4099 len -= 2;
4100
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004101 if (pi->fcs == L2CAP_FCS_CRC16)
4102 len -= 2;
4103
Nathan Holstein51893f82010-06-09 15:46:25 -04004104 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004105 goto drop;
4106
4107 tx_seq = __get_txseq(control);
4108
4109 if (pi->expected_tx_seq == tx_seq)
4110 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4111 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004112 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004113
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004114 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004115
4116 goto done;
4117
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004118 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004119 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004120 break;
4121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
4123drop:
4124 kfree_skb(skb);
4125
4126done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004127 if (sk)
4128 bh_unlock_sock(sk);
4129
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 return 0;
4131}
4132
Al Viro8e036fc2007-07-29 00:16:36 -07004133static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134{
4135 struct sock *sk;
4136
4137 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4138 if (!sk)
4139 goto drop;
4140
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004141 bh_lock_sock(sk);
4142
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 BT_DBG("sk %p, len %d", sk, skb->len);
4144
4145 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4146 goto drop;
4147
4148 if (l2cap_pi(sk)->imtu < skb->len)
4149 goto drop;
4150
4151 if (!sock_queue_rcv_skb(sk, skb))
4152 goto done;
4153
4154drop:
4155 kfree_skb(skb);
4156
4157done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004158 if (sk)
4159 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 return 0;
4161}
4162
4163static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4164{
4165 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004166 u16 cid, len;
4167 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
4169 skb_pull(skb, L2CAP_HDR_SIZE);
4170 cid = __le16_to_cpu(lh->cid);
4171 len = __le16_to_cpu(lh->len);
4172
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004173 if (len != skb->len) {
4174 kfree_skb(skb);
4175 return;
4176 }
4177
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4179
4180 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004181 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 l2cap_sig_channel(conn, skb);
4183 break;
4184
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004185 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004186 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 skb_pull(skb, 2);
4188 l2cap_conless_channel(conn, psm, skb);
4189 break;
4190
4191 default:
4192 l2cap_data_channel(conn, cid, skb);
4193 break;
4194 }
4195}
4196
4197/* ---- L2CAP interface with lower layer (HCI) ---- */
4198
4199static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4200{
4201 int exact = 0, lm1 = 0, lm2 = 0;
4202 register struct sock *sk;
4203 struct hlist_node *node;
4204
4205 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004206 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207
4208 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4209
4210 /* Find listening sockets and check their link_mode */
4211 read_lock(&l2cap_sk_list.lock);
4212 sk_for_each(sk, node, &l2cap_sk_list.head) {
4213 if (sk->sk_state != BT_LISTEN)
4214 continue;
4215
4216 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004217 lm1 |= HCI_LM_ACCEPT;
4218 if (l2cap_pi(sk)->role_switch)
4219 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004221 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4222 lm2 |= HCI_LM_ACCEPT;
4223 if (l2cap_pi(sk)->role_switch)
4224 lm2 |= HCI_LM_MASTER;
4225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 }
4227 read_unlock(&l2cap_sk_list.lock);
4228
4229 return exact ? lm1 : lm2;
4230}
4231
4232static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4233{
Marcel Holtmann01394182006-07-03 10:02:46 +02004234 struct l2cap_conn *conn;
4235
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4237
4238 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004239 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
4241 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 conn = l2cap_conn_add(hcon, status);
4243 if (conn)
4244 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004245 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 l2cap_conn_del(hcon, bt_err(status));
4247
4248 return 0;
4249}
4250
Marcel Holtmann2950f212009-02-12 14:02:50 +01004251static int l2cap_disconn_ind(struct hci_conn *hcon)
4252{
4253 struct l2cap_conn *conn = hcon->l2cap_data;
4254
4255 BT_DBG("hcon %p", hcon);
4256
4257 if (hcon->type != ACL_LINK || !conn)
4258 return 0x13;
4259
4260 return conn->disc_reason;
4261}
4262
4263static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264{
4265 BT_DBG("hcon %p reason %d", hcon, reason);
4266
4267 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004268 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
4270 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004271
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 return 0;
4273}
4274
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004275static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4276{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004277 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004278 return;
4279
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004280 if (encrypt == 0x00) {
4281 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4282 l2cap_sock_clear_timer(sk);
4283 l2cap_sock_set_timer(sk, HZ * 5);
4284 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4285 __l2cap_sock_close(sk, ECONNREFUSED);
4286 } else {
4287 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4288 l2cap_sock_clear_timer(sk);
4289 }
4290}
4291
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004292static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293{
4294 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004295 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Marcel Holtmann01394182006-07-03 10:02:46 +02004298 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004300
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 l = &conn->chan_list;
4302
4303 BT_DBG("conn %p", conn);
4304
4305 read_lock(&l->lock);
4306
4307 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4308 bh_lock_sock(sk);
4309
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004310 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4311 bh_unlock_sock(sk);
4312 continue;
4313 }
4314
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004315 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004316 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004317 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004318 bh_unlock_sock(sk);
4319 continue;
4320 }
4321
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004322 if (sk->sk_state == BT_CONNECT) {
4323 if (!status) {
4324 struct l2cap_conn_req req;
4325 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4326 req.psm = l2cap_pi(sk)->psm;
4327
4328 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004329 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004330
4331 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4332 L2CAP_CONN_REQ, sizeof(req), &req);
4333 } else {
4334 l2cap_sock_clear_timer(sk);
4335 l2cap_sock_set_timer(sk, HZ / 10);
4336 }
4337 } else if (sk->sk_state == BT_CONNECT2) {
4338 struct l2cap_conn_rsp rsp;
4339 __u16 result;
4340
4341 if (!status) {
4342 sk->sk_state = BT_CONFIG;
4343 result = L2CAP_CR_SUCCESS;
4344 } else {
4345 sk->sk_state = BT_DISCONN;
4346 l2cap_sock_set_timer(sk, HZ / 10);
4347 result = L2CAP_CR_SEC_BLOCK;
4348 }
4349
4350 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4351 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4352 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004353 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004354 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4355 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 }
4357
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358 bh_unlock_sock(sk);
4359 }
4360
4361 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004362
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363 return 0;
4364}
4365
4366static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4367{
4368 struct l2cap_conn *conn = hcon->l2cap_data;
4369
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004370 if (!conn)
4371 conn = l2cap_conn_add(hcon, 0);
4372
4373 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 goto drop;
4375
4376 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4377
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004378 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004380 struct sock *sk;
4381 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 int len;
4383
4384 if (conn->rx_len) {
4385 BT_ERR("Unexpected start frame (len %d)", skb->len);
4386 kfree_skb(conn->rx_skb);
4387 conn->rx_skb = NULL;
4388 conn->rx_len = 0;
4389 l2cap_conn_unreliable(conn, ECOMM);
4390 }
4391
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004392 /* Start fragment always begin with Basic L2CAP header */
4393 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 BT_ERR("Frame is too short (len %d)", skb->len);
4395 l2cap_conn_unreliable(conn, ECOMM);
4396 goto drop;
4397 }
4398
4399 hdr = (struct l2cap_hdr *) skb->data;
4400 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004401 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402
4403 if (len == skb->len) {
4404 /* Complete frame received */
4405 l2cap_recv_frame(conn, skb);
4406 return 0;
4407 }
4408
4409 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4410
4411 if (skb->len > len) {
4412 BT_ERR("Frame is too long (len %d, expected len %d)",
4413 skb->len, len);
4414 l2cap_conn_unreliable(conn, ECOMM);
4415 goto drop;
4416 }
4417
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004418 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4419
4420 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4421 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
4422 len, l2cap_pi(sk)->imtu);
4423 bh_unlock_sock(sk);
4424 l2cap_conn_unreliable(conn, ECOMM);
4425 goto drop;
4426 }
4427
4428 if (sk)
4429 bh_unlock_sock(sk);
4430
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004432 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4433 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 goto drop;
4435
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004436 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004437 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 conn->rx_len = len - skb->len;
4439 } else {
4440 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4441
4442 if (!conn->rx_len) {
4443 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4444 l2cap_conn_unreliable(conn, ECOMM);
4445 goto drop;
4446 }
4447
4448 if (skb->len > conn->rx_len) {
4449 BT_ERR("Fragment is too long (len %d, expected %d)",
4450 skb->len, conn->rx_len);
4451 kfree_skb(conn->rx_skb);
4452 conn->rx_skb = NULL;
4453 conn->rx_len = 0;
4454 l2cap_conn_unreliable(conn, ECOMM);
4455 goto drop;
4456 }
4457
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004458 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004459 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460 conn->rx_len -= skb->len;
4461
4462 if (!conn->rx_len) {
4463 /* Complete frame received */
4464 l2cap_recv_frame(conn, conn->rx_skb);
4465 conn->rx_skb = NULL;
4466 }
4467 }
4468
4469drop:
4470 kfree_skb(skb);
4471 return 0;
4472}
4473
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004474static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475{
4476 struct sock *sk;
4477 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478
4479 read_lock_bh(&l2cap_sk_list.lock);
4480
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004481 sk_for_each(sk, node, &l2cap_sk_list.head) {
4482 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004484 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4485 batostr(&bt_sk(sk)->src),
4486 batostr(&bt_sk(sk)->dst),
4487 sk->sk_state, __le16_to_cpu(pi->psm),
4488 pi->scid, pi->dcid,
4489 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004493
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004494 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495}
4496
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004497static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4498{
4499 return single_open(file, l2cap_debugfs_show, inode->i_private);
4500}
4501
4502static const struct file_operations l2cap_debugfs_fops = {
4503 .open = l2cap_debugfs_open,
4504 .read = seq_read,
4505 .llseek = seq_lseek,
4506 .release = single_release,
4507};
4508
4509static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511static struct hci_proto l2cap_hci_proto = {
4512 .name = "L2CAP",
4513 .id = HCI_PROTO_L2CAP,
4514 .connect_ind = l2cap_connect_ind,
4515 .connect_cfm = l2cap_connect_cfm,
4516 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004517 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004518 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 .recv_acldata = l2cap_recv_acldata
4520};
4521
4522static int __init l2cap_init(void)
4523{
4524 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004525
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004526 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 if (err < 0)
4528 return err;
4529
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004530 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004531 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004532 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533 goto error;
4534 }
4535
4536 err = hci_register_proto(&l2cap_hci_proto);
4537 if (err < 0) {
4538 BT_ERR("L2CAP protocol registration failed");
4539 bt_sock_unregister(BTPROTO_L2CAP);
4540 goto error;
4541 }
4542
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004543 if (bt_debugfs) {
4544 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4545 bt_debugfs, NULL, &l2cap_debugfs_fops);
4546 if (!l2cap_debugfs)
4547 BT_ERR("Failed to create L2CAP debug file");
4548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549
4550 BT_INFO("L2CAP ver %s", VERSION);
4551 BT_INFO("L2CAP socket layer initialized");
4552
4553 return 0;
4554
4555error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004556 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004557 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 return err;
4559}
4560
4561static void __exit l2cap_exit(void)
4562{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004563 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004565 flush_workqueue(_busy_wq);
4566 destroy_workqueue(_busy_wq);
4567
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4569 BT_ERR("L2CAP protocol unregistration failed");
4570
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004571 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572}
4573
4574void l2cap_load(void)
4575{
4576 /* Dummy function to trigger automatic L2CAP module loading by
4577 * other modules that use L2CAP sockets but don't use any other
4578 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579}
4580EXPORT_SYMBOL(l2cap_load);
4581
4582module_init(l2cap_init);
4583module_exit(l2cap_exit);
4584
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004585module_param(disable_ertm, bool, 0644);
4586MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004587
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004588MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4590MODULE_VERSION(VERSION);
4591MODULE_LICENSE("GPL");
4592MODULE_ALIAS("bt-proto-0");