blob: 74a3ea3625d6b4665e98b6e651814155c42c5983 [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 ---- */
Al Viro8e036fc2007-07-29 00:16:36 -0700725static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
727 struct sock *sk;
728 struct hlist_node *node;
729 sk_for_each(sk, node, &l2cap_sk_list.head)
730 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
731 goto found;
732 sk = NULL;
733found:
734 return sk;
735}
736
737/* Find socket with psm and source bdaddr.
738 * Returns closest match.
739 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000740static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
742 struct sock *sk = NULL, *sk1 = NULL;
743 struct hlist_node *node;
744
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000745 read_lock(&l2cap_sk_list.lock);
746
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 sk_for_each(sk, node, &l2cap_sk_list.head) {
748 if (state && sk->sk_state != state)
749 continue;
750
751 if (l2cap_pi(sk)->psm == psm) {
752 /* Exact match. */
753 if (!bacmp(&bt_sk(sk)->src, src))
754 break;
755
756 /* Closest match */
757 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
758 sk1 = sk;
759 }
760 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000763
764 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765}
766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767static void l2cap_sock_cleanup_listen(struct sock *parent)
768{
769 struct sock *sk;
770
771 BT_DBG("parent %p", parent);
772
773 /* Close not yet accepted channels */
774 while ((sk = bt_accept_dequeue(parent, NULL)))
775 l2cap_sock_close(sk);
776
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200777 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 sock_set_flag(parent, SOCK_ZAPPED);
779}
780
781/* Kill socket (only if zapped and orphan)
782 * Must be called on unlocked socket.
783 */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200784void l2cap_sock_kill(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
787 return;
788
789 BT_DBG("sk %p state %d", sk, sk->sk_state);
790
791 /* Kill poor orphan */
792 bt_sock_unlink(&l2cap_sk_list, sk);
793 sock_set_flag(sk, SOCK_DEAD);
794 sock_put(sk);
795}
796
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200797void __l2cap_sock_close(struct sock *sk, int reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
799 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
800
801 switch (sk->sk_state) {
802 case BT_LISTEN:
803 l2cap_sock_cleanup_listen(sk);
804 break;
805
806 case BT_CONNECTED:
807 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300808 if (sk->sk_type == SOCK_SEQPACKET ||
809 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300813 l2cap_send_disconn_req(conn, sk, reason);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200814 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 break;
817
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100818 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300819 if (sk->sk_type == SOCK_SEQPACKET ||
820 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100821 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
822 struct l2cap_conn_rsp rsp;
823 __u16 result;
824
825 if (bt_sk(sk)->defer_setup)
826 result = L2CAP_CR_SEC_BLOCK;
827 else
828 result = L2CAP_CR_BAD_PSM;
Bao Liange733fb62011-01-29 21:39:37 +0800829 sk->sk_state = BT_DISCONN;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100830
831 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
832 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
833 rsp.result = cpu_to_le16(result);
834 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
835 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
836 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
837 } else
838 l2cap_chan_del(sk, reason);
839 break;
840
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 case BT_CONNECT:
842 case BT_DISCONN:
843 l2cap_chan_del(sk, reason);
844 break;
845
846 default:
847 sock_set_flag(sk, SOCK_ZAPPED);
848 break;
849 }
850}
851
852/* Must be called on unlocked socket. */
853static void l2cap_sock_close(struct sock *sk)
854{
855 l2cap_sock_clear_timer(sk);
856 lock_sock(sk);
857 __l2cap_sock_close(sk, ECONNRESET);
858 release_sock(sk);
859 l2cap_sock_kill(sk);
860}
861
Gustavo F. Padovan65390582011-02-04 02:33:56 -0200862int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100865 struct sockaddr_l2 la;
866 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100868 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870 if (!addr || addr->sa_family != AF_BLUETOOTH)
871 return -EINVAL;
872
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100873 memset(&la, 0, sizeof(la));
874 len = min_t(unsigned int, sizeof(la), alen);
875 memcpy(&la, addr, len);
876
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100877 if (la.l2_cid)
878 return -EINVAL;
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 lock_sock(sk);
881
882 if (sk->sk_state != BT_OPEN) {
883 err = -EBADFD;
884 goto done;
885 }
886
Mat Martineau0fba2552010-09-08 10:05:26 -0700887 if (la.l2_psm) {
888 __u16 psm = __le16_to_cpu(la.l2_psm);
889
890 /* PSM must be odd and lsb of upper byte must be 0 */
891 if ((psm & 0x0101) != 0x0001) {
892 err = -EINVAL;
893 goto done;
894 }
895
896 /* Restrict usage of well-known PSMs */
897 if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
898 err = -EACCES;
899 goto done;
900 }
Marcel Holtmann847641d2007-01-22 22:00:45 +0100901 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 write_lock_bh(&l2cap_sk_list.lock);
904
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100905 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 err = -EADDRINUSE;
907 } else {
908 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100909 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
910 l2cap_pi(sk)->psm = la.l2_psm;
911 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100913
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200914 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
915 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100916 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 }
918
919 write_unlock_bh(&l2cap_sk_list.lock);
920
921done:
922 release_sock(sk);
923 return err;
924}
925
926static int l2cap_do_connect(struct sock *sk)
927{
928 bdaddr_t *src = &bt_sk(sk)->src;
929 bdaddr_t *dst = &bt_sk(sk)->dst;
930 struct l2cap_conn *conn;
931 struct hci_conn *hcon;
932 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200933 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200934 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100936 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
937 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300939 hdev = hci_get_route(dst, src);
940 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 return -EHOSTUNREACH;
942
943 hci_dev_lock_bh(hdev);
944
945 err = -ENOMEM;
946
Johan Hedberg8556edd32011-01-19 12:06:50 +0530947 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200948
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100949 hcon = hci_connect(hdev, ACL_LINK, dst,
950 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (!hcon)
952 goto done;
953
954 conn = l2cap_conn_add(hcon, 0);
955 if (!conn) {
956 hci_conn_put(hcon);
957 goto done;
958 }
959
960 err = 0;
961
962 /* Update source addr of the socket */
963 bacpy(src, conn->src);
964
965 l2cap_chan_add(conn, sk, NULL);
966
967 sk->sk_state = BT_CONNECT;
968 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
969
970 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300971 if (sk->sk_type != SOCK_SEQPACKET &&
972 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530974 if (l2cap_check_security(sk))
975 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200976 } else
977 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
979
980done:
981 hci_dev_unlock_bh(hdev);
982 hci_dev_put(hdev);
983 return err;
984}
985
Gustavo F. Padovan65390582011-02-04 02:33:56 -0200986int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100989 struct sockaddr_l2 la;
990 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 BT_DBG("sk %p", sk);
993
Changli Gao6503d962010-03-31 22:58:26 +0000994 if (!addr || alen < sizeof(addr->sa_family) ||
995 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100996 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100998 memset(&la, 0, sizeof(la));
999 len = min_t(unsigned int, sizeof(la), alen);
1000 memcpy(&la, addr, len);
1001
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001002 if (la.l2_cid)
1003 return -EINVAL;
1004
1005 lock_sock(sk);
1006
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001007 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
1008 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 err = -EINVAL;
1010 goto done;
1011 }
1012
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001013 switch (l2cap_pi(sk)->mode) {
1014 case L2CAP_MODE_BASIC:
1015 break;
1016 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001017 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001018 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001019 break;
1020 /* fall through */
1021 default:
1022 err = -ENOTSUPP;
1023 goto done;
1024 }
1025
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001026 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 case BT_CONNECT:
1028 case BT_CONNECT2:
1029 case BT_CONFIG:
1030 /* Already connecting */
1031 goto wait;
1032
1033 case BT_CONNECTED:
1034 /* Already connected */
João Paulo Rechi Vita8b0dc6d2010-06-22 13:56:22 -03001035 err = -EISCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 goto done;
1037
1038 case BT_OPEN:
1039 case BT_BOUND:
1040 /* Can connect */
1041 break;
1042
1043 default:
1044 err = -EBADFD;
1045 goto done;
1046 }
1047
Mat Martineau0fba2552010-09-08 10:05:26 -07001048 /* PSM must be odd and lsb of upper byte must be 0 */
1049 if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
1050 sk->sk_type != SOCK_RAW) {
1051 err = -EINVAL;
1052 goto done;
1053 }
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001056 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1057 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001059 err = l2cap_do_connect(sk);
1060 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 goto done;
1062
1063wait:
1064 err = bt_sock_wait_state(sk, BT_CONNECTED,
1065 sock_sndtimeo(sk, flags & O_NONBLOCK));
1066done:
1067 release_sock(sk);
1068 return err;
1069}
1070
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001071int l2cap_sock_listen(struct socket *sock, int backlog)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072{
1073 struct sock *sk = sock->sk;
1074 int err = 0;
1075
1076 BT_DBG("sk %p backlog %d", sk, backlog);
1077
1078 lock_sock(sk);
1079
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001080 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1081 || sk->sk_state != BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 err = -EBADFD;
1083 goto done;
1084 }
1085
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001086 switch (l2cap_pi(sk)->mode) {
1087 case L2CAP_MODE_BASIC:
1088 break;
1089 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001090 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001091 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001092 break;
1093 /* fall through */
1094 default:
1095 err = -ENOTSUPP;
1096 goto done;
1097 }
1098
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 if (!l2cap_pi(sk)->psm) {
1100 bdaddr_t *src = &bt_sk(sk)->src;
1101 u16 psm;
1102
1103 err = -EINVAL;
1104
1105 write_lock_bh(&l2cap_sk_list.lock);
1106
1107 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001108 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1109 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1110 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 err = 0;
1112 break;
1113 }
1114
1115 write_unlock_bh(&l2cap_sk_list.lock);
1116
1117 if (err < 0)
1118 goto done;
1119 }
1120
1121 sk->sk_max_ack_backlog = backlog;
1122 sk->sk_ack_backlog = 0;
1123 sk->sk_state = BT_LISTEN;
1124
1125done:
1126 release_sock(sk);
1127 return err;
1128}
1129
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001130int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
1132 DECLARE_WAITQUEUE(wait, current);
1133 struct sock *sk = sock->sk, *nsk;
1134 long timeo;
1135 int err = 0;
1136
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001137 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
1139 if (sk->sk_state != BT_LISTEN) {
1140 err = -EBADFD;
1141 goto done;
1142 }
1143
1144 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1145
1146 BT_DBG("sk %p timeo %ld", sk, timeo);
1147
1148 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001149 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1151 set_current_state(TASK_INTERRUPTIBLE);
1152 if (!timeo) {
1153 err = -EAGAIN;
1154 break;
1155 }
1156
1157 release_sock(sk);
1158 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001159 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
1161 if (sk->sk_state != BT_LISTEN) {
1162 err = -EBADFD;
1163 break;
1164 }
1165
1166 if (signal_pending(current)) {
1167 err = sock_intr_errno(timeo);
1168 break;
1169 }
1170 }
1171 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001172 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
1174 if (err)
1175 goto done;
1176
1177 newsock->state = SS_CONNECTED;
1178
1179 BT_DBG("new socket %p", nsk);
1180
1181done:
1182 release_sock(sk);
1183 return err;
1184}
1185
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001186int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187{
1188 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1189 struct sock *sk = sock->sk;
1190
1191 BT_DBG("sock %p, sk %p", sock, sk);
1192
1193 addr->sa_family = AF_BLUETOOTH;
1194 *len = sizeof(struct sockaddr_l2);
1195
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001196 if (peer) {
1197 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001199 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001200 } else {
1201 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001203 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001204 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 return 0;
1207}
1208
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001209static int __l2cap_wait_ack(struct sock *sk)
1210{
1211 DECLARE_WAITQUEUE(wait, current);
1212 int err = 0;
1213 int timeo = HZ/5;
1214
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001215 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001216 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
1217 set_current_state(TASK_INTERRUPTIBLE);
1218
1219 if (!timeo)
1220 timeo = HZ/5;
1221
1222 if (signal_pending(current)) {
1223 err = sock_intr_errno(timeo);
1224 break;
1225 }
1226
1227 release_sock(sk);
1228 timeo = schedule_timeout(timeo);
1229 lock_sock(sk);
1230
1231 err = sock_error(sk);
1232 if (err)
1233 break;
1234 }
1235 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001236 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001237 return err;
1238}
1239
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001240static void l2cap_monitor_timeout(unsigned long arg)
1241{
1242 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001243
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001244 BT_DBG("sk %p", sk);
1245
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001246 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001247 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001248 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001249 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001250 return;
1251 }
1252
1253 l2cap_pi(sk)->retry_count++;
1254 __mod_monitor_timer();
1255
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001256 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001257 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001258}
1259
1260static void l2cap_retrans_timeout(unsigned long arg)
1261{
1262 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001263
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001264 BT_DBG("sk %p", sk);
1265
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001266 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001267 l2cap_pi(sk)->retry_count = 1;
1268 __mod_monitor_timer();
1269
1270 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1271
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001272 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001273 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001274}
1275
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001276static void l2cap_drop_acked_frames(struct sock *sk)
1277{
1278 struct sk_buff *skb;
1279
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001280 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1281 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001282 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1283 break;
1284
1285 skb = skb_dequeue(TX_QUEUE(sk));
1286 kfree_skb(skb);
1287
1288 l2cap_pi(sk)->unacked_frames--;
1289 }
1290
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001291 if (!l2cap_pi(sk)->unacked_frames)
1292 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001293}
1294
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001295static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001296{
1297 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001298 struct hci_conn *hcon = pi->conn->hcon;
1299 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001300
1301 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1302
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001303 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1304 flags = ACL_START_NO_FLUSH;
1305 else
1306 flags = ACL_START;
1307
1308 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001309}
1310
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001311static void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001312{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001313 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001314 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001315 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001316
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001317 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1318 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001319 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001320 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001321
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001322 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001323 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1324 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001325 }
1326
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001327 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001328
1329 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001330 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001331}
1332
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001333static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001334{
1335 struct l2cap_pinfo *pi = l2cap_pi(sk);
1336 struct sk_buff *skb, *tx_skb;
1337 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001338
1339 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001340 if (!skb)
1341 return;
1342
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001343 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001344 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001345 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001346
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001347 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1348 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001349
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001350 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001351
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001352 if (pi->remote_max_tx &&
1353 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001354 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001355 return;
1356 }
1357
1358 tx_skb = skb_clone(skb, GFP_ATOMIC);
1359 bt_cb(skb)->retries++;
1360 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001361
1362 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1363 control |= L2CAP_CTRL_FINAL;
1364 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1365 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001366
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001367 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1368 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001369
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001370 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1371
1372 if (pi->fcs == L2CAP_FCS_CRC16) {
1373 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1374 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1375 }
1376
1377 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001378}
1379
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380static int l2cap_ertm_send(struct sock *sk)
1381{
1382 struct sk_buff *skb, *tx_skb;
1383 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001384 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001385 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001387 if (sk->sk_state != BT_CONNECTED)
1388 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001389
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001390 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001391
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001392 if (pi->remote_max_tx &&
1393 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001394 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001395 break;
1396 }
1397
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001398 tx_skb = skb_clone(skb, GFP_ATOMIC);
1399
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001400 bt_cb(skb)->retries++;
1401
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001402 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001403 control &= L2CAP_CTRL_SAR;
1404
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001405 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1406 control |= L2CAP_CTRL_FINAL;
1407 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1408 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001409 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001410 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1411 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1412
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001413
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001414 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001415 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1416 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1417 }
1418
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001419 l2cap_do_send(sk, tx_skb);
1420
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001421 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422
1423 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1424 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1425
1426 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001427 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428
1429 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1430 sk->sk_send_head = NULL;
1431 else
1432 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001433
1434 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435 }
1436
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001437 return nsent;
1438}
1439
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001440static int l2cap_retransmit_frames(struct sock *sk)
1441{
1442 struct l2cap_pinfo *pi = l2cap_pi(sk);
1443 int ret;
1444
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001445 if (!skb_queue_empty(TX_QUEUE(sk)))
1446 sk->sk_send_head = TX_QUEUE(sk)->next;
1447
1448 pi->next_tx_seq = pi->expected_ack_seq;
1449 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001450 return ret;
1451}
1452
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001453static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001454{
1455 struct sock *sk = (struct sock *)pi;
1456 u16 control = 0;
1457
1458 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1459
1460 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1461 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001462 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001463 l2cap_send_sframe(pi, control);
1464 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001465 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001466
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001467 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001468 return;
1469
1470 control |= L2CAP_SUPER_RCV_READY;
1471 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472}
1473
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001474static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001475{
1476 struct srej_list *tail;
1477 u16 control;
1478
1479 control = L2CAP_SUPER_SELECT_REJECT;
1480 control |= L2CAP_CTRL_FINAL;
1481
1482 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1483 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1484
1485 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001486}
1487
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001488static 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 -07001489{
1490 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001491 struct sk_buff **frag;
1492 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001494 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001495 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
1497 sent += count;
1498 len -= count;
1499
1500 /* Continuation fragments (no L2CAP header) */
1501 frag = &skb_shinfo(skb)->frag_list;
1502 while (len) {
1503 count = min_t(unsigned int, conn->mtu, len);
1504
1505 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1506 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001507 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001508 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1509 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
1511 sent += count;
1512 len -= count;
1513
1514 frag = &(*frag)->next;
1515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
1517 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001518}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001520static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1521{
1522 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1523 struct sk_buff *skb;
1524 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1525 struct l2cap_hdr *lh;
1526
1527 BT_DBG("sk %p len %d", sk, (int)len);
1528
1529 count = min_t(unsigned int, (conn->mtu - hlen), len);
1530 skb = bt_skb_send_alloc(sk, count + hlen,
1531 msg->msg_flags & MSG_DONTWAIT, &err);
1532 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001533 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001534
1535 /* Create L2CAP header */
1536 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1537 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1538 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1539 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1540
1541 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1542 if (unlikely(err < 0)) {
1543 kfree_skb(skb);
1544 return ERR_PTR(err);
1545 }
1546 return skb;
1547}
1548
1549static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1550{
1551 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1552 struct sk_buff *skb;
1553 int err, count, hlen = L2CAP_HDR_SIZE;
1554 struct l2cap_hdr *lh;
1555
1556 BT_DBG("sk %p len %d", sk, (int)len);
1557
1558 count = min_t(unsigned int, (conn->mtu - hlen), len);
1559 skb = bt_skb_send_alloc(sk, count + hlen,
1560 msg->msg_flags & MSG_DONTWAIT, &err);
1561 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001562 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563
1564 /* Create L2CAP header */
1565 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1566 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1567 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1568
1569 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1570 if (unlikely(err < 0)) {
1571 kfree_skb(skb);
1572 return ERR_PTR(err);
1573 }
1574 return skb;
1575}
1576
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001577static 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 -03001578{
1579 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1580 struct sk_buff *skb;
1581 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1582 struct l2cap_hdr *lh;
1583
1584 BT_DBG("sk %p len %d", sk, (int)len);
1585
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001586 if (!conn)
1587 return ERR_PTR(-ENOTCONN);
1588
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001589 if (sdulen)
1590 hlen += 2;
1591
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001592 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1593 hlen += 2;
1594
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595 count = min_t(unsigned int, (conn->mtu - hlen), len);
1596 skb = bt_skb_send_alloc(sk, count + hlen,
1597 msg->msg_flags & MSG_DONTWAIT, &err);
1598 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001599 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001600
1601 /* Create L2CAP header */
1602 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1603 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1604 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1605 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001606 if (sdulen)
1607 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001608
1609 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1610 if (unlikely(err < 0)) {
1611 kfree_skb(skb);
1612 return ERR_PTR(err);
1613 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001614
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001615 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1616 put_unaligned_le16(0, skb_put(skb, 2));
1617
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001618 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001619 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620}
1621
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001622static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1623{
1624 struct l2cap_pinfo *pi = l2cap_pi(sk);
1625 struct sk_buff *skb;
1626 struct sk_buff_head sar_queue;
1627 u16 control;
1628 size_t size = 0;
1629
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001630 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001631 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001632 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001633 if (IS_ERR(skb))
1634 return PTR_ERR(skb);
1635
1636 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001637 len -= pi->remote_mps;
1638 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001639
1640 while (len > 0) {
1641 size_t buflen;
1642
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001643 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001644 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001645 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001646 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001647 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001648 buflen = len;
1649 }
1650
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001651 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001652 if (IS_ERR(skb)) {
1653 skb_queue_purge(&sar_queue);
1654 return PTR_ERR(skb);
1655 }
1656
1657 __skb_queue_tail(&sar_queue, skb);
1658 len -= buflen;
1659 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001660 }
1661 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1662 if (sk->sk_send_head == NULL)
1663 sk->sk_send_head = sar_queue.next;
1664
1665 return size;
1666}
1667
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001668int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
1670 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001671 struct l2cap_pinfo *pi = l2cap_pi(sk);
1672 struct sk_buff *skb;
1673 u16 control;
1674 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
1676 BT_DBG("sock %p, sk %p", sock, sk);
1677
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001678 err = sock_error(sk);
1679 if (err)
1680 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
1682 if (msg->msg_flags & MSG_OOB)
1683 return -EOPNOTSUPP;
1684
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 lock_sock(sk);
1686
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001687 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001689 goto done;
1690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001692 /* Connectionless channel */
1693 if (sk->sk_type == SOCK_DGRAM) {
1694 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001695 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001696 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001697 } else {
1698 l2cap_do_send(sk, skb);
1699 err = len;
1700 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001701 goto done;
1702 }
1703
1704 switch (pi->mode) {
1705 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001706 /* Check outgoing MTU */
1707 if (len > pi->omtu) {
João Paulo Rechi Vitaf9dd11b2010-06-22 13:56:24 -03001708 err = -EMSGSIZE;
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001709 goto done;
1710 }
1711
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001712 /* Create a basic PDU */
1713 skb = l2cap_create_basic_pdu(sk, msg, len);
1714 if (IS_ERR(skb)) {
1715 err = PTR_ERR(skb);
1716 goto done;
1717 }
1718
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001719 l2cap_do_send(sk, skb);
1720 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001721 break;
1722
1723 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001724 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001725 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001726 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001727 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001728 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001729 if (IS_ERR(skb)) {
1730 err = PTR_ERR(skb);
1731 goto done;
1732 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001733 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001734
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001735 if (sk->sk_send_head == NULL)
1736 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001737
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001738 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001739 /* Segment SDU into multiples PDUs */
1740 err = l2cap_sar_segment_sdu(sk, msg, len);
1741 if (err < 0)
1742 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001743 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001744
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001745 if (pi->mode == L2CAP_MODE_STREAMING) {
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001746 l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001747 } else {
David Sterba45719282011-01-14 14:59:44 +01001748 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1749 (pi->conn_state & L2CAP_CONN_WAIT_F)) {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001750 err = len;
1751 break;
1752 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001753 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001754 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001755
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001756 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001757 err = len;
1758 break;
1759
1760 default:
1761 BT_DBG("bad state %1.1x", pi->mode);
João Paulo Rechi Vitabc766db22010-06-22 13:56:25 -03001762 err = -EBADFD;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001763 }
1764
1765done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 release_sock(sk);
1767 return err;
1768}
1769
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001770int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001771{
1772 struct sock *sk = sock->sk;
1773
1774 lock_sock(sk);
1775
1776 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1777 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001778 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1779 u8 buf[128];
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001780
1781 sk->sk_state = BT_CONFIG;
1782
1783 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1784 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1785 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1786 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1787 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1788 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1789
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001790 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
1791 release_sock(sk);
1792 return 0;
1793 }
1794
1795 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1796 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1797 l2cap_build_conf_req(sk, buf), buf);
1798 l2cap_pi(sk)->num_conf_req++;
1799
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001800 release_sock(sk);
1801 return 0;
1802 }
1803
1804 release_sock(sk);
1805
Mat Martineau6fdf4822010-09-08 10:05:29 -07001806 if (sock->type == SOCK_STREAM)
1807 return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
1808
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001809 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1810}
1811
David S. Millerb7058842009-09-30 16:12:20 -07001812static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
1814 struct sock *sk = sock->sk;
1815 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001816 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 u32 opt;
1818
1819 BT_DBG("sk %p", sk);
1820
1821 lock_sock(sk);
1822
1823 switch (optname) {
1824 case L2CAP_OPTIONS:
Gustavo F. Padovaneaa71b32010-10-04 19:28:52 -03001825 if (sk->sk_state == BT_CONNECTED) {
1826 err = -EINVAL;
1827 break;
1828 }
1829
Marcel Holtmann0878b662007-05-05 00:35:59 +02001830 opts.imtu = l2cap_pi(sk)->imtu;
1831 opts.omtu = l2cap_pi(sk)->omtu;
1832 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001833 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001834 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001835 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001836 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001837
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 len = min_t(unsigned int, sizeof(opts), optlen);
1839 if (copy_from_user((char *) &opts, optval, len)) {
1840 err = -EFAULT;
1841 break;
1842 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001843
Gustavo F. Padovan45d65c42010-06-07 19:21:30 -03001844 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
1845 err = -EINVAL;
1846 break;
1847 }
1848
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001849 l2cap_pi(sk)->mode = opts.mode;
1850 switch (l2cap_pi(sk)->mode) {
1851 case L2CAP_MODE_BASIC:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001852 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001853 break;
1854 case L2CAP_MODE_ERTM:
1855 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001856 if (!disable_ertm)
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001857 break;
1858 /* fall through */
1859 default:
1860 err = -EINVAL;
1861 break;
1862 }
1863
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001864 l2cap_pi(sk)->imtu = opts.imtu;
1865 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001866 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001867 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001868 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 break;
1870
1871 case L2CAP_LM:
1872 if (get_user(opt, (u32 __user *) optval)) {
1873 err = -EFAULT;
1874 break;
1875 }
1876
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001877 if (opt & L2CAP_LM_AUTH)
1878 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
1879 if (opt & L2CAP_LM_ENCRYPT)
1880 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
1881 if (opt & L2CAP_LM_SECURE)
1882 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
1883
1884 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
1885 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 break;
1887
1888 default:
1889 err = -ENOPROTOOPT;
1890 break;
1891 }
1892
1893 release_sock(sk);
1894 return err;
1895}
1896
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001897int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001898{
1899 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001900 struct bt_security sec;
1901 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001902 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001903
1904 BT_DBG("sk %p", sk);
1905
1906 if (level == SOL_L2CAP)
1907 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
1908
Marcel Holtmann0588d942009-01-16 10:06:13 +01001909 if (level != SOL_BLUETOOTH)
1910 return -ENOPROTOOPT;
1911
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001912 lock_sock(sk);
1913
1914 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001915 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001916 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
1917 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01001918 err = -EINVAL;
1919 break;
1920 }
1921
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001922 sec.level = BT_SECURITY_LOW;
1923
1924 len = min_t(unsigned int, sizeof(sec), optlen);
1925 if (copy_from_user((char *) &sec, optval, len)) {
1926 err = -EFAULT;
1927 break;
1928 }
1929
1930 if (sec.level < BT_SECURITY_LOW ||
1931 sec.level > BT_SECURITY_HIGH) {
1932 err = -EINVAL;
1933 break;
1934 }
1935
1936 l2cap_pi(sk)->sec_level = sec.level;
1937 break;
1938
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001939 case BT_DEFER_SETUP:
1940 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1941 err = -EINVAL;
1942 break;
1943 }
1944
1945 if (get_user(opt, (u32 __user *) optval)) {
1946 err = -EFAULT;
1947 break;
1948 }
1949
1950 bt_sk(sk)->defer_setup = opt;
1951 break;
1952
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001953 case BT_FLUSHABLE:
1954 if (get_user(opt, (u32 __user *) optval)) {
1955 err = -EFAULT;
1956 break;
1957 }
1958
1959 if (opt > BT_FLUSHABLE_ON) {
1960 err = -EINVAL;
1961 break;
1962 }
1963
1964 if (opt == BT_FLUSHABLE_OFF) {
1965 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1966 /* proceed futher only when we have l2cap_conn and
1967 No Flush support in the LM */
1968 if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
1969 err = -EINVAL;
1970 break;
1971 }
1972 }
1973
1974 l2cap_pi(sk)->flushable = opt;
1975 break;
1976
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001977 default:
1978 err = -ENOPROTOOPT;
1979 break;
1980 }
1981
1982 release_sock(sk);
1983 return err;
1984}
1985
1986static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987{
1988 struct sock *sk = sock->sk;
1989 struct l2cap_options opts;
1990 struct l2cap_conninfo cinfo;
1991 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001992 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
1994 BT_DBG("sk %p", sk);
1995
1996 if (get_user(len, optlen))
1997 return -EFAULT;
1998
1999 lock_sock(sk);
2000
2001 switch (optname) {
2002 case L2CAP_OPTIONS:
2003 opts.imtu = l2cap_pi(sk)->imtu;
2004 opts.omtu = l2cap_pi(sk)->omtu;
2005 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07002006 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002007 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002008 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002009 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
2011 len = min_t(unsigned int, len, sizeof(opts));
2012 if (copy_to_user(optval, (char *) &opts, len))
2013 err = -EFAULT;
2014
2015 break;
2016
2017 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002018 switch (l2cap_pi(sk)->sec_level) {
2019 case BT_SECURITY_LOW:
2020 opt = L2CAP_LM_AUTH;
2021 break;
2022 case BT_SECURITY_MEDIUM:
2023 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
2024 break;
2025 case BT_SECURITY_HIGH:
2026 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
2027 L2CAP_LM_SECURE;
2028 break;
2029 default:
2030 opt = 0;
2031 break;
2032 }
2033
2034 if (l2cap_pi(sk)->role_switch)
2035 opt |= L2CAP_LM_MASTER;
2036
2037 if (l2cap_pi(sk)->force_reliable)
2038 opt |= L2CAP_LM_RELIABLE;
2039
2040 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 err = -EFAULT;
2042 break;
2043
2044 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002045 if (sk->sk_state != BT_CONNECTED &&
2046 !(sk->sk_state == BT_CONNECT2 &&
2047 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 err = -ENOTCONN;
2049 break;
2050 }
2051
2052 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
2053 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
2054
2055 len = min_t(unsigned int, len, sizeof(cinfo));
2056 if (copy_to_user(optval, (char *) &cinfo, len))
2057 err = -EFAULT;
2058
2059 break;
2060
2061 default:
2062 err = -ENOPROTOOPT;
2063 break;
2064 }
2065
2066 release_sock(sk);
2067 return err;
2068}
2069
Gustavo F. Padovan65390582011-02-04 02:33:56 -02002070int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002071{
2072 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002073 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002074 int len, err = 0;
2075
2076 BT_DBG("sk %p", sk);
2077
2078 if (level == SOL_L2CAP)
2079 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
2080
Marcel Holtmann0588d942009-01-16 10:06:13 +01002081 if (level != SOL_BLUETOOTH)
2082 return -ENOPROTOOPT;
2083
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002084 if (get_user(len, optlen))
2085 return -EFAULT;
2086
2087 lock_sock(sk);
2088
2089 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002090 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002091 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2092 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002093 err = -EINVAL;
2094 break;
2095 }
2096
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002097 sec.level = l2cap_pi(sk)->sec_level;
2098
2099 len = min_t(unsigned int, len, sizeof(sec));
2100 if (copy_to_user(optval, (char *) &sec, len))
2101 err = -EFAULT;
2102
2103 break;
2104
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002105 case BT_DEFER_SETUP:
2106 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2107 err = -EINVAL;
2108 break;
2109 }
2110
2111 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
2112 err = -EFAULT;
2113
2114 break;
2115
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02002116 case BT_FLUSHABLE:
2117 if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
2118 err = -EFAULT;
2119
2120 break;
2121
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002122 default:
2123 err = -ENOPROTOOPT;
2124 break;
2125 }
2126
2127 release_sock(sk);
2128 return err;
2129}
2130
Gustavo F. Padovan65390582011-02-04 02:33:56 -02002131int l2cap_sock_shutdown(struct socket *sock, int how)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132{
2133 struct sock *sk = sock->sk;
2134 int err = 0;
2135
2136 BT_DBG("sock %p, sk %p", sock, sk);
2137
2138 if (!sk)
2139 return 0;
2140
2141 lock_sock(sk);
2142 if (!sk->sk_shutdown) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03002143 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2144 err = __l2cap_wait_ack(sk);
2145
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 sk->sk_shutdown = SHUTDOWN_MASK;
2147 l2cap_sock_clear_timer(sk);
2148 __l2cap_sock_close(sk, 0);
2149
2150 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002151 err = bt_sock_wait_state(sk, BT_CLOSED,
2152 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 }
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002154
2155 if (!err && sk->sk_err)
2156 err = -sk->sk_err;
2157
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 release_sock(sk);
2159 return err;
2160}
2161
Gustavo F. Padovan65390582011-02-04 02:33:56 -02002162int l2cap_sock_release(struct socket *sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163{
2164 struct sock *sk = sock->sk;
2165 int err;
2166
2167 BT_DBG("sock %p, sk %p", sock, sk);
2168
2169 if (!sk)
2170 return 0;
2171
2172 err = l2cap_sock_shutdown(sock, 2);
2173
2174 sock_orphan(sk);
2175 l2cap_sock_kill(sk);
2176 return err;
2177}
2178
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179static void l2cap_chan_ready(struct sock *sk)
2180{
2181 struct sock *parent = bt_sk(sk)->parent;
2182
2183 BT_DBG("sk %p, parent %p", sk, parent);
2184
2185 l2cap_pi(sk)->conf_state = 0;
2186 l2cap_sock_clear_timer(sk);
2187
2188 if (!parent) {
2189 /* Outgoing channel.
2190 * Wake up socket sleeping on connect.
2191 */
2192 sk->sk_state = BT_CONNECTED;
2193 sk->sk_state_change(sk);
2194 } else {
2195 /* Incoming channel.
2196 * Wake up socket sleeping on accept.
2197 */
2198 parent->sk_data_ready(parent, 0);
2199 }
2200}
2201
2202/* Copy frame to all raw sockets on that connection */
2203static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2204{
2205 struct l2cap_chan_list *l = &conn->chan_list;
2206 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002207 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208
2209 BT_DBG("conn %p", conn);
2210
2211 read_lock(&l->lock);
2212 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2213 if (sk->sk_type != SOCK_RAW)
2214 continue;
2215
2216 /* Don't send frame to the socket it came from */
2217 if (skb->sk == sk)
2218 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002219 nskb = skb_clone(skb, GFP_ATOMIC);
2220 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 continue;
2222
2223 if (sock_queue_rcv_skb(sk, nskb))
2224 kfree_skb(nskb);
2225 }
2226 read_unlock(&l->lock);
2227}
2228
2229/* ---- L2CAP signalling commands ---- */
2230static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2231 u8 code, u8 ident, u16 dlen, void *data)
2232{
2233 struct sk_buff *skb, **frag;
2234 struct l2cap_cmd_hdr *cmd;
2235 struct l2cap_hdr *lh;
2236 int len, count;
2237
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002238 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2239 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2242 count = min_t(unsigned int, conn->mtu, len);
2243
2244 skb = bt_skb_alloc(count, GFP_ATOMIC);
2245 if (!skb)
2246 return NULL;
2247
2248 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002249 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002250 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2253 cmd->code = code;
2254 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002255 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
2257 if (dlen) {
2258 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2259 memcpy(skb_put(skb, count), data, count);
2260 data += count;
2261 }
2262
2263 len -= skb->len;
2264
2265 /* Continuation fragments (no L2CAP header) */
2266 frag = &skb_shinfo(skb)->frag_list;
2267 while (len) {
2268 count = min_t(unsigned int, conn->mtu, len);
2269
2270 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2271 if (!*frag)
2272 goto fail;
2273
2274 memcpy(skb_put(*frag, count), data, count);
2275
2276 len -= count;
2277 data += count;
2278
2279 frag = &(*frag)->next;
2280 }
2281
2282 return skb;
2283
2284fail:
2285 kfree_skb(skb);
2286 return NULL;
2287}
2288
2289static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2290{
2291 struct l2cap_conf_opt *opt = *ptr;
2292 int len;
2293
2294 len = L2CAP_CONF_OPT_SIZE + opt->len;
2295 *ptr += len;
2296
2297 *type = opt->type;
2298 *olen = opt->len;
2299
2300 switch (opt->len) {
2301 case 1:
2302 *val = *((u8 *) opt->val);
2303 break;
2304
2305 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002306 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 break;
2308
2309 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002310 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 break;
2312
2313 default:
2314 *val = (unsigned long) opt->val;
2315 break;
2316 }
2317
2318 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2319 return len;
2320}
2321
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2323{
2324 struct l2cap_conf_opt *opt = *ptr;
2325
2326 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2327
2328 opt->type = type;
2329 opt->len = len;
2330
2331 switch (len) {
2332 case 1:
2333 *((u8 *) opt->val) = val;
2334 break;
2335
2336 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002337 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 break;
2339
2340 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002341 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 break;
2343
2344 default:
2345 memcpy(opt->val, (void *) val, len);
2346 break;
2347 }
2348
2349 *ptr += L2CAP_CONF_OPT_SIZE + len;
2350}
2351
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002352static void l2cap_ack_timeout(unsigned long arg)
2353{
2354 struct sock *sk = (void *) arg;
2355
2356 bh_lock_sock(sk);
2357 l2cap_send_ack(l2cap_pi(sk));
2358 bh_unlock_sock(sk);
2359}
2360
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002361static inline void l2cap_ertm_init(struct sock *sk)
2362{
2363 l2cap_pi(sk)->expected_ack_seq = 0;
2364 l2cap_pi(sk)->unacked_frames = 0;
2365 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002366 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002367 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002368
2369 setup_timer(&l2cap_pi(sk)->retrans_timer,
2370 l2cap_retrans_timeout, (unsigned long) sk);
2371 setup_timer(&l2cap_pi(sk)->monitor_timer,
2372 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002373 setup_timer(&l2cap_pi(sk)->ack_timer,
2374 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002375
2376 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002377 __skb_queue_head_init(BUSY_QUEUE(sk));
2378
2379 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03002380
2381 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002382}
2383
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002384static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2385{
2386 switch (mode) {
2387 case L2CAP_MODE_STREAMING:
2388 case L2CAP_MODE_ERTM:
2389 if (l2cap_mode_supported(mode, remote_feat_mask))
2390 return mode;
2391 /* fall through */
2392 default:
2393 return L2CAP_MODE_BASIC;
2394 }
2395}
2396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397static int l2cap_build_conf_req(struct sock *sk, void *data)
2398{
2399 struct l2cap_pinfo *pi = l2cap_pi(sk);
2400 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002401 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 void *ptr = req->data;
2403
2404 BT_DBG("sk %p", sk);
2405
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002406 if (pi->num_conf_req || pi->num_conf_rsp)
2407 goto done;
2408
2409 switch (pi->mode) {
2410 case L2CAP_MODE_STREAMING:
2411 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002412 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002413 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002414
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002415 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002416 default:
2417 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2418 break;
2419 }
2420
2421done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002422 if (pi->imtu != L2CAP_DEFAULT_MTU)
2423 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
2424
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002425 switch (pi->mode) {
2426 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002427 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2428 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
2429 break;
2430
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002431 rfc.mode = L2CAP_MODE_BASIC;
2432 rfc.txwin_size = 0;
2433 rfc.max_transmit = 0;
2434 rfc.retrans_timeout = 0;
2435 rfc.monitor_timeout = 0;
2436 rfc.max_pdu_size = 0;
2437
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002438 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2439 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002440 break;
2441
2442 case L2CAP_MODE_ERTM:
2443 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002444 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002445 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002446 rfc.retrans_timeout = 0;
2447 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002448 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002449 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002450 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002451
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002452 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2453 (unsigned long) &rfc);
2454
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002455 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2456 break;
2457
2458 if (pi->fcs == L2CAP_FCS_NONE ||
2459 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2460 pi->fcs = L2CAP_FCS_NONE;
2461 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2462 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002463 break;
2464
2465 case L2CAP_MODE_STREAMING:
2466 rfc.mode = L2CAP_MODE_STREAMING;
2467 rfc.txwin_size = 0;
2468 rfc.max_transmit = 0;
2469 rfc.retrans_timeout = 0;
2470 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002471 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002472 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002473 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002474
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002475 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2476 (unsigned long) &rfc);
2477
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002478 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2479 break;
2480
2481 if (pi->fcs == L2CAP_FCS_NONE ||
2482 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2483 pi->fcs = L2CAP_FCS_NONE;
2484 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2485 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002486 break;
2487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
2489 /* FIXME: Need actual value of the flush timeout */
2490 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2491 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2492
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002493 req->dcid = cpu_to_le16(pi->dcid);
2494 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
2496 return ptr - data;
2497}
2498
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002499static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500{
2501 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002502 struct l2cap_conf_rsp *rsp = data;
2503 void *ptr = rsp->data;
2504 void *req = pi->conf_req;
2505 int len = pi->conf_len;
2506 int type, hint, olen;
2507 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002508 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002509 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002510 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002512 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002513
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002514 while (len >= L2CAP_CONF_OPT_SIZE) {
2515 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002517 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002518 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002519
2520 switch (type) {
2521 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002522 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002523 break;
2524
2525 case L2CAP_CONF_FLUSH_TO:
2526 pi->flush_to = val;
2527 break;
2528
2529 case L2CAP_CONF_QOS:
2530 break;
2531
Marcel Holtmann6464f352007-10-20 13:39:51 +02002532 case L2CAP_CONF_RFC:
2533 if (olen == sizeof(rfc))
2534 memcpy(&rfc, (void *) val, olen);
2535 break;
2536
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002537 case L2CAP_CONF_FCS:
2538 if (val == L2CAP_FCS_NONE)
2539 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2540
2541 break;
2542
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002543 default:
2544 if (hint)
2545 break;
2546
2547 result = L2CAP_CONF_UNKNOWN;
2548 *((u8 *) ptr++) = type;
2549 break;
2550 }
2551 }
2552
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002553 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002554 goto done;
2555
2556 switch (pi->mode) {
2557 case L2CAP_MODE_STREAMING:
2558 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002559 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
2560 pi->mode = l2cap_select_mode(rfc.mode,
2561 pi->conn->feat_mask);
2562 break;
2563 }
2564
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002565 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002566 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002567
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002568 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002569 }
2570
2571done:
2572 if (pi->mode != rfc.mode) {
2573 result = L2CAP_CONF_UNACCEPT;
2574 rfc.mode = pi->mode;
2575
2576 if (pi->num_conf_rsp == 1)
2577 return -ECONNREFUSED;
2578
2579 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2580 sizeof(rfc), (unsigned long) &rfc);
2581 }
2582
2583
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002584 if (result == L2CAP_CONF_SUCCESS) {
2585 /* Configure output options and let the other side know
2586 * which ones we don't like. */
2587
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002588 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2589 result = L2CAP_CONF_UNACCEPT;
2590 else {
2591 pi->omtu = mtu;
2592 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2593 }
2594 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002595
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002596 switch (rfc.mode) {
2597 case L2CAP_MODE_BASIC:
2598 pi->fcs = L2CAP_FCS_NONE;
2599 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2600 break;
2601
2602 case L2CAP_MODE_ERTM:
2603 pi->remote_tx_win = rfc.txwin_size;
2604 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002605
2606 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2607 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002608
2609 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002610
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002611 rfc.retrans_timeout =
2612 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2613 rfc.monitor_timeout =
2614 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002615
2616 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002617
2618 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2619 sizeof(rfc), (unsigned long) &rfc);
2620
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002621 break;
2622
2623 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07002624 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2625 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002626
2627 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002628
2629 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002630
2631 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2632 sizeof(rfc), (unsigned long) &rfc);
2633
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002634 break;
2635
2636 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002637 result = L2CAP_CONF_UNACCEPT;
2638
2639 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002640 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002641 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002642
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002643 if (result == L2CAP_CONF_SUCCESS)
2644 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2645 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002646 rsp->scid = cpu_to_le16(pi->dcid);
2647 rsp->result = cpu_to_le16(result);
2648 rsp->flags = cpu_to_le16(0x0000);
2649
2650 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651}
2652
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002653static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2654{
2655 struct l2cap_pinfo *pi = l2cap_pi(sk);
2656 struct l2cap_conf_req *req = data;
2657 void *ptr = req->data;
2658 int type, olen;
2659 unsigned long val;
2660 struct l2cap_conf_rfc rfc;
2661
2662 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2663
2664 while (len >= L2CAP_CONF_OPT_SIZE) {
2665 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2666
2667 switch (type) {
2668 case L2CAP_CONF_MTU:
2669 if (val < L2CAP_DEFAULT_MIN_MTU) {
2670 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002671 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002672 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002673 pi->imtu = val;
2674 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002675 break;
2676
2677 case L2CAP_CONF_FLUSH_TO:
2678 pi->flush_to = val;
2679 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2680 2, pi->flush_to);
2681 break;
2682
2683 case L2CAP_CONF_RFC:
2684 if (olen == sizeof(rfc))
2685 memcpy(&rfc, (void *)val, olen);
2686
2687 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2688 rfc.mode != pi->mode)
2689 return -ECONNREFUSED;
2690
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002691 pi->fcs = 0;
2692
2693 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2694 sizeof(rfc), (unsigned long) &rfc);
2695 break;
2696 }
2697 }
2698
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002699 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
2700 return -ECONNREFUSED;
2701
2702 pi->mode = rfc.mode;
2703
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002704 if (*result == L2CAP_CONF_SUCCESS) {
2705 switch (rfc.mode) {
2706 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002707 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2708 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002709 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002710 break;
2711 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002712 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002713 }
2714 }
2715
2716 req->dcid = cpu_to_le16(pi->dcid);
2717 req->flags = cpu_to_le16(0x0000);
2718
2719 return ptr - data;
2720}
2721
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002722static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723{
2724 struct l2cap_conf_rsp *rsp = data;
2725 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002727 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002729 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002730 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002731 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
2733 return ptr - data;
2734}
2735
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002736static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2737{
2738 struct l2cap_pinfo *pi = l2cap_pi(sk);
2739 int type, olen;
2740 unsigned long val;
2741 struct l2cap_conf_rfc rfc;
2742
2743 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2744
2745 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2746 return;
2747
2748 while (len >= L2CAP_CONF_OPT_SIZE) {
2749 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2750
2751 switch (type) {
2752 case L2CAP_CONF_RFC:
2753 if (olen == sizeof(rfc))
2754 memcpy(&rfc, (void *)val, olen);
2755 goto done;
2756 }
2757 }
2758
2759done:
2760 switch (rfc.mode) {
2761 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002762 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2763 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002764 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2765 break;
2766 case L2CAP_MODE_STREAMING:
2767 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2768 }
2769}
2770
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002771static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2772{
2773 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2774
2775 if (rej->reason != 0x0000)
2776 return 0;
2777
2778 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2779 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002780 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002781
2782 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002783 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002784
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002785 l2cap_conn_start(conn);
2786 }
2787
2788 return 0;
2789}
2790
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2792{
2793 struct l2cap_chan_list *list = &conn->chan_list;
2794 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2795 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002796 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002797 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002800 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2803
2804 /* Check if we have socket listening on psm */
2805 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2806 if (!parent) {
2807 result = L2CAP_CR_BAD_PSM;
2808 goto sendresp;
2809 }
2810
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002811 bh_lock_sock(parent);
2812
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002813 /* Check if the ACL is secure enough (if not SDP) */
2814 if (psm != cpu_to_le16(0x0001) &&
2815 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002816 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002817 result = L2CAP_CR_SEC_BLOCK;
2818 goto response;
2819 }
2820
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 result = L2CAP_CR_NO_MEM;
2822
2823 /* Check for backlog size */
2824 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002825 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 goto response;
2827 }
2828
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002829 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 if (!sk)
2831 goto response;
2832
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002833 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
2835 /* Check if we already have channel with that dcid */
2836 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002837 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 sock_set_flag(sk, SOCK_ZAPPED);
2839 l2cap_sock_kill(sk);
2840 goto response;
2841 }
2842
2843 hci_conn_hold(conn->hcon);
2844
2845 l2cap_sock_init(sk, parent);
2846 bacpy(&bt_sk(sk)->src, conn->src);
2847 bacpy(&bt_sk(sk)->dst, conn->dst);
2848 l2cap_pi(sk)->psm = psm;
2849 l2cap_pi(sk)->dcid = scid;
2850
2851 __l2cap_chan_add(conn, sk, parent);
2852 dcid = l2cap_pi(sk)->scid;
2853
2854 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2855
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 l2cap_pi(sk)->ident = cmd->ident;
2857
Marcel Holtmann984947d2009-02-06 23:35:19 +01002858 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002859 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002860 if (bt_sk(sk)->defer_setup) {
2861 sk->sk_state = BT_CONNECT2;
2862 result = L2CAP_CR_PEND;
2863 status = L2CAP_CS_AUTHOR_PEND;
2864 parent->sk_data_ready(parent, 0);
2865 } else {
2866 sk->sk_state = BT_CONFIG;
2867 result = L2CAP_CR_SUCCESS;
2868 status = L2CAP_CS_NO_INFO;
2869 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002870 } else {
2871 sk->sk_state = BT_CONNECT2;
2872 result = L2CAP_CR_PEND;
2873 status = L2CAP_CS_AUTHEN_PEND;
2874 }
2875 } else {
2876 sk->sk_state = BT_CONNECT2;
2877 result = L2CAP_CR_PEND;
2878 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 }
2880
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002881 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
2883response:
2884 bh_unlock_sock(parent);
2885
2886sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002887 rsp.scid = cpu_to_le16(scid);
2888 rsp.dcid = cpu_to_le16(dcid);
2889 rsp.result = cpu_to_le16(result);
2890 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002892
2893 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2894 struct l2cap_info_req info;
2895 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2896
2897 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2898 conn->info_ident = l2cap_get_ident(conn);
2899
2900 mod_timer(&conn->info_timer, jiffies +
2901 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2902
2903 l2cap_send_cmd(conn, conn->info_ident,
2904 L2CAP_INFO_REQ, sizeof(info), &info);
2905 }
2906
Nathan Holsteind793fe82010-10-15 11:54:02 -04002907 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002908 result == L2CAP_CR_SUCCESS) {
2909 u8 buf[128];
2910 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2911 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2912 l2cap_build_conf_req(sk, buf), buf);
2913 l2cap_pi(sk)->num_conf_req++;
2914 }
2915
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 return 0;
2917}
2918
2919static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2920{
2921 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2922 u16 scid, dcid, result, status;
2923 struct sock *sk;
2924 u8 req[128];
2925
2926 scid = __le16_to_cpu(rsp->scid);
2927 dcid = __le16_to_cpu(rsp->dcid);
2928 result = __le16_to_cpu(rsp->result);
2929 status = __le16_to_cpu(rsp->status);
2930
2931 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2932
2933 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002934 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2935 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002936 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002938 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2939 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002940 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 }
2942
2943 switch (result) {
2944 case L2CAP_CR_SUCCESS:
2945 sk->sk_state = BT_CONFIG;
2946 l2cap_pi(sk)->ident = 0;
2947 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002948 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2949
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002950 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2951 break;
2952
2953 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2954
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2956 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002957 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 break;
2959
2960 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002961 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 break;
2963
2964 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002965 /* don't delete l2cap channel if sk is owned by user */
2966 if (sock_owned_by_user(sk)) {
2967 sk->sk_state = BT_DISCONN;
2968 l2cap_sock_clear_timer(sk);
2969 l2cap_sock_set_timer(sk, HZ / 5);
2970 break;
2971 }
2972
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 l2cap_chan_del(sk, ECONNREFUSED);
2974 break;
2975 }
2976
2977 bh_unlock_sock(sk);
2978 return 0;
2979}
2980
Mat Martineau8c462b62010-08-24 15:35:42 -07002981static inline void set_default_fcs(struct l2cap_pinfo *pi)
2982{
2983 /* FCS is enabled only in ERTM or streaming mode, if one or both
2984 * sides request it.
2985 */
2986 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2987 pi->fcs = L2CAP_FCS_NONE;
2988 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2989 pi->fcs = L2CAP_FCS_CRC16;
2990}
2991
Al Viro88219a02007-07-29 00:17:25 -07002992static 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 -07002993{
2994 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2995 u16 dcid, flags;
2996 u8 rsp[64];
2997 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002998 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
3000 dcid = __le16_to_cpu(req->dcid);
3001 flags = __le16_to_cpu(req->flags);
3002
3003 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3004
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003005 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3006 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return -ENOENT;
3008
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003009 if (sk->sk_state != BT_CONFIG) {
3010 struct l2cap_cmd_rej rej;
3011
3012 rej.reason = cpu_to_le16(0x0002);
3013 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3014 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003015 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003016 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003017
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003018 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003019 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003020 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
3021 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3022 l2cap_build_conf_rsp(sk, rsp,
3023 L2CAP_CONF_REJECT, flags), rsp);
3024 goto unlock;
3025 }
3026
3027 /* Store config. */
3028 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
3029 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
3031 if (flags & 0x0001) {
3032 /* Incomplete config. Send empty response. */
3033 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003034 l2cap_build_conf_rsp(sk, rsp,
3035 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 goto unlock;
3037 }
3038
3039 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003040 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003041 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003042 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003046 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003047 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003048
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003049 /* Reset config buffer. */
3050 l2cap_pi(sk)->conf_len = 0;
3051
Marcel Holtmann876d9482007-10-20 13:35:42 +02003052 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
3053 goto unlock;
3054
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003056 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003057
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003059
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003060 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003061 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003062 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003063 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3064 l2cap_ertm_init(sk);
3065
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02003067 goto unlock;
3068 }
3069
3070 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003071 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08003072 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003074 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003075 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
3077
3078unlock:
3079 bh_unlock_sock(sk);
3080 return 0;
3081}
3082
3083static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3084{
3085 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3086 u16 scid, flags, result;
3087 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003088 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
3090 scid = __le16_to_cpu(rsp->scid);
3091 flags = __le16_to_cpu(rsp->flags);
3092 result = __le16_to_cpu(rsp->result);
3093
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003094 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
3095 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003097 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3098 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 return 0;
3100
3101 switch (result) {
3102 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003103 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 break;
3105
3106 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003107 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003108 char req[64];
3109
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003110 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003111 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003112 goto done;
3113 }
3114
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003115 /* throw out any old stored conf requests */
3116 result = L2CAP_CONF_SUCCESS;
3117 len = l2cap_parse_conf_rsp(sk, rsp->data,
3118 len, req, &result);
3119 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003120 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003121 goto done;
3122 }
3123
3124 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3125 L2CAP_CONF_REQ, len, req);
3126 l2cap_pi(sk)->num_conf_req++;
3127 if (result != L2CAP_CONF_SUCCESS)
3128 goto done;
3129 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 }
3131
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003132 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003133 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003135 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 goto done;
3137 }
3138
3139 if (flags & 0x01)
3140 goto done;
3141
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3143
3144 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003145 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003146
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003148 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003149 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003150 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003151 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3152 l2cap_ertm_init(sk);
3153
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 l2cap_chan_ready(sk);
3155 }
3156
3157done:
3158 bh_unlock_sock(sk);
3159 return 0;
3160}
3161
3162static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3163{
3164 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3165 struct l2cap_disconn_rsp rsp;
3166 u16 dcid, scid;
3167 struct sock *sk;
3168
3169 scid = __le16_to_cpu(req->scid);
3170 dcid = __le16_to_cpu(req->dcid);
3171
3172 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3173
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003174 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3175 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 return 0;
3177
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003178 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3179 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3181
3182 sk->sk_shutdown = SHUTDOWN_MASK;
3183
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003184 /* don't delete l2cap channel if sk is owned by user */
3185 if (sock_owned_by_user(sk)) {
3186 sk->sk_state = BT_DISCONN;
3187 l2cap_sock_clear_timer(sk);
3188 l2cap_sock_set_timer(sk, HZ / 5);
3189 bh_unlock_sock(sk);
3190 return 0;
3191 }
3192
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 l2cap_chan_del(sk, ECONNRESET);
3194 bh_unlock_sock(sk);
3195
3196 l2cap_sock_kill(sk);
3197 return 0;
3198}
3199
3200static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3201{
3202 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3203 u16 dcid, scid;
3204 struct sock *sk;
3205
3206 scid = __le16_to_cpu(rsp->scid);
3207 dcid = __le16_to_cpu(rsp->dcid);
3208
3209 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3210
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003211 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3212 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 return 0;
3214
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003215 /* don't delete l2cap channel if sk is owned by user */
3216 if (sock_owned_by_user(sk)) {
3217 sk->sk_state = BT_DISCONN;
3218 l2cap_sock_clear_timer(sk);
3219 l2cap_sock_set_timer(sk, HZ / 5);
3220 bh_unlock_sock(sk);
3221 return 0;
3222 }
3223
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 l2cap_chan_del(sk, 0);
3225 bh_unlock_sock(sk);
3226
3227 l2cap_sock_kill(sk);
3228 return 0;
3229}
3230
3231static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3232{
3233 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 u16 type;
3235
3236 type = __le16_to_cpu(req->type);
3237
3238 BT_DBG("type 0x%4.4x", type);
3239
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003240 if (type == L2CAP_IT_FEAT_MASK) {
3241 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003242 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003243 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3244 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3245 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003246 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003247 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3248 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003249 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003250 l2cap_send_cmd(conn, cmd->ident,
3251 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003252 } else if (type == L2CAP_IT_FIXED_CHAN) {
3253 u8 buf[12];
3254 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3255 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3256 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3257 memcpy(buf + 4, l2cap_fixed_chan, 8);
3258 l2cap_send_cmd(conn, cmd->ident,
3259 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003260 } else {
3261 struct l2cap_info_rsp rsp;
3262 rsp.type = cpu_to_le16(type);
3263 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3264 l2cap_send_cmd(conn, cmd->ident,
3265 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
3268 return 0;
3269}
3270
3271static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3272{
3273 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3274 u16 type, result;
3275
3276 type = __le16_to_cpu(rsp->type);
3277 result = __le16_to_cpu(rsp->result);
3278
3279 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3280
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003281 del_timer(&conn->info_timer);
3282
Ville Tervoadb08ed2010-08-04 09:43:33 +03003283 if (result != L2CAP_IR_SUCCESS) {
3284 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3285 conn->info_ident = 0;
3286
3287 l2cap_conn_start(conn);
3288
3289 return 0;
3290 }
3291
Marcel Holtmann984947d2009-02-06 23:35:19 +01003292 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003293 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003294
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003295 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003296 struct l2cap_info_req req;
3297 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3298
3299 conn->info_ident = l2cap_get_ident(conn);
3300
3301 l2cap_send_cmd(conn, conn->info_ident,
3302 L2CAP_INFO_REQ, sizeof(req), &req);
3303 } else {
3304 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3305 conn->info_ident = 0;
3306
3307 l2cap_conn_start(conn);
3308 }
3309 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003310 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003311 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003312
3313 l2cap_conn_start(conn);
3314 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 return 0;
3317}
3318
3319static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3320{
3321 u8 *data = skb->data;
3322 int len = skb->len;
3323 struct l2cap_cmd_hdr cmd;
3324 int err = 0;
3325
3326 l2cap_raw_recv(conn, skb);
3327
3328 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003329 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3331 data += L2CAP_CMD_HDR_SIZE;
3332 len -= L2CAP_CMD_HDR_SIZE;
3333
Al Viro88219a02007-07-29 00:17:25 -07003334 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
Al Viro88219a02007-07-29 00:17:25 -07003336 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 -07003337
Al Viro88219a02007-07-29 00:17:25 -07003338 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 BT_DBG("corrupted command");
3340 break;
3341 }
3342
3343 switch (cmd.code) {
3344 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003345 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 break;
3347
3348 case L2CAP_CONN_REQ:
3349 err = l2cap_connect_req(conn, &cmd, data);
3350 break;
3351
3352 case L2CAP_CONN_RSP:
3353 err = l2cap_connect_rsp(conn, &cmd, data);
3354 break;
3355
3356 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003357 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 break;
3359
3360 case L2CAP_CONF_RSP:
3361 err = l2cap_config_rsp(conn, &cmd, data);
3362 break;
3363
3364 case L2CAP_DISCONN_REQ:
3365 err = l2cap_disconnect_req(conn, &cmd, data);
3366 break;
3367
3368 case L2CAP_DISCONN_RSP:
3369 err = l2cap_disconnect_rsp(conn, &cmd, data);
3370 break;
3371
3372 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003373 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 break;
3375
3376 case L2CAP_ECHO_RSP:
3377 break;
3378
3379 case L2CAP_INFO_REQ:
3380 err = l2cap_information_req(conn, &cmd, data);
3381 break;
3382
3383 case L2CAP_INFO_RSP:
3384 err = l2cap_information_rsp(conn, &cmd, data);
3385 break;
3386
3387 default:
3388 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3389 err = -EINVAL;
3390 break;
3391 }
3392
3393 if (err) {
3394 struct l2cap_cmd_rej rej;
3395 BT_DBG("error %d", err);
3396
3397 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003398 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3400 }
3401
Al Viro88219a02007-07-29 00:17:25 -07003402 data += cmd_len;
3403 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404 }
3405
3406 kfree_skb(skb);
3407}
3408
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003409static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3410{
3411 u16 our_fcs, rcv_fcs;
3412 int hdr_size = L2CAP_HDR_SIZE + 2;
3413
3414 if (pi->fcs == L2CAP_FCS_CRC16) {
3415 skb_trim(skb, skb->len - 2);
3416 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3417 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3418
3419 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003420 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003421 }
3422 return 0;
3423}
3424
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003425static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3426{
3427 struct l2cap_pinfo *pi = l2cap_pi(sk);
3428 u16 control = 0;
3429
3430 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003431
3432 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3433
3434 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003435 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003436 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003437 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003438 }
3439
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003440 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3441 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003442
3443 l2cap_ertm_send(sk);
3444
3445 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3446 pi->frames_sent == 0) {
3447 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003448 l2cap_send_sframe(pi, control);
3449 }
3450}
3451
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003452static 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 -03003453{
3454 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003455 struct l2cap_pinfo *pi = l2cap_pi(sk);
3456 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003457
3458 bt_cb(skb)->tx_seq = tx_seq;
3459 bt_cb(skb)->sar = sar;
3460
3461 next_skb = skb_peek(SREJ_QUEUE(sk));
3462 if (!next_skb) {
3463 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003464 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003465 }
3466
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003467 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3468 if (tx_seq_offset < 0)
3469 tx_seq_offset += 64;
3470
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003471 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003472 if (bt_cb(next_skb)->tx_seq == tx_seq)
3473 return -EINVAL;
3474
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003475 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3476 pi->buffer_seq) % 64;
3477 if (next_tx_seq_offset < 0)
3478 next_tx_seq_offset += 64;
3479
3480 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003481 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003482 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003483 }
3484
3485 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3486 break;
3487
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003488 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489
3490 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003491
3492 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003493}
3494
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003495static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3496{
3497 struct l2cap_pinfo *pi = l2cap_pi(sk);
3498 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003499 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003500
3501 switch (control & L2CAP_CTRL_SAR) {
3502 case L2CAP_SDU_UNSEGMENTED:
3503 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3504 goto drop;
3505
3506 err = sock_queue_rcv_skb(sk, skb);
3507 if (!err)
3508 return err;
3509
3510 break;
3511
3512 case L2CAP_SDU_START:
3513 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3514 goto drop;
3515
3516 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003517
3518 if (pi->sdu_len > pi->imtu)
3519 goto disconnect;
3520
3521 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003522 if (!pi->sdu)
3523 return -ENOMEM;
3524
3525 /* pull sdu_len bytes only after alloc, because of Local Busy
3526 * condition we have to be sure that this will be executed
3527 * only once, i.e., when alloc does not fail */
3528 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003529
3530 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3531
3532 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3533 pi->partial_sdu_len = skb->len;
3534 break;
3535
3536 case L2CAP_SDU_CONTINUE:
3537 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3538 goto disconnect;
3539
3540 if (!pi->sdu)
3541 goto disconnect;
3542
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003543 pi->partial_sdu_len += skb->len;
3544 if (pi->partial_sdu_len > pi->sdu_len)
3545 goto drop;
3546
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003547 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3548
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003549 break;
3550
3551 case L2CAP_SDU_END:
3552 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3553 goto disconnect;
3554
3555 if (!pi->sdu)
3556 goto disconnect;
3557
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003558 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003559 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003560
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003561 if (pi->partial_sdu_len > pi->imtu)
3562 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003563
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003564 if (pi->partial_sdu_len != pi->sdu_len)
3565 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003566
3567 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003568 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003569
3570 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003571 if (!_skb) {
3572 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3573 return -ENOMEM;
3574 }
3575
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003576 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003577 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003578 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003579 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3580 return err;
3581 }
3582
3583 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3584 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003585
3586 kfree_skb(pi->sdu);
3587 break;
3588 }
3589
3590 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003591 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003592
3593drop:
3594 kfree_skb(pi->sdu);
3595 pi->sdu = NULL;
3596
3597disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003598 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003599 kfree_skb(skb);
3600 return 0;
3601}
3602
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003603static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003604{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003605 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003606 struct sk_buff *skb;
3607 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003608 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003609
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003610 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3611 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3612 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3613 if (err < 0) {
3614 skb_queue_head(BUSY_QUEUE(sk), skb);
3615 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003616 }
3617
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003618 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003619 }
3620
3621 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3622 goto done;
3623
3624 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3625 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3626 l2cap_send_sframe(pi, control);
3627 l2cap_pi(sk)->retry_count = 1;
3628
3629 del_timer(&pi->retrans_timer);
3630 __mod_monitor_timer();
3631
3632 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3633
3634done:
3635 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3636 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3637
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003638 BT_DBG("sk %p, Exit local busy", sk);
3639
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003640 return 0;
3641}
3642
3643static void l2cap_busy_work(struct work_struct *work)
3644{
3645 DECLARE_WAITQUEUE(wait, current);
3646 struct l2cap_pinfo *pi =
3647 container_of(work, struct l2cap_pinfo, busy_work);
3648 struct sock *sk = (struct sock *)pi;
3649 int n_tries = 0, timeo = HZ/5, err;
3650 struct sk_buff *skb;
3651
3652 lock_sock(sk);
3653
3654 add_wait_queue(sk_sleep(sk), &wait);
3655 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3656 set_current_state(TASK_INTERRUPTIBLE);
3657
3658 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3659 err = -EBUSY;
3660 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3661 break;
3662 }
3663
3664 if (!timeo)
3665 timeo = HZ/5;
3666
3667 if (signal_pending(current)) {
3668 err = sock_intr_errno(timeo);
3669 break;
3670 }
3671
3672 release_sock(sk);
3673 timeo = schedule_timeout(timeo);
3674 lock_sock(sk);
3675
3676 err = sock_error(sk);
3677 if (err)
3678 break;
3679
3680 if (l2cap_try_push_rx_skb(sk) == 0)
3681 break;
3682 }
3683
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003684 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003685 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003686
3687 release_sock(sk);
3688}
3689
3690static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3691{
3692 struct l2cap_pinfo *pi = l2cap_pi(sk);
3693 int sctrl, err;
3694
3695 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3696 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3697 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003698 return l2cap_try_push_rx_skb(sk);
3699
3700
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003701 }
3702
3703 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3704 if (err >= 0) {
3705 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3706 return err;
3707 }
3708
3709 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003710 BT_DBG("sk %p, Enter local busy", sk);
3711
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003712 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3713 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3714 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3715
3716 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3717 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3718 l2cap_send_sframe(pi, sctrl);
3719
3720 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3721
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003722 del_timer(&pi->ack_timer);
3723
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003724 queue_work(_busy_wq, &pi->busy_work);
3725
3726 return err;
3727}
3728
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003729static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003730{
3731 struct l2cap_pinfo *pi = l2cap_pi(sk);
3732 struct sk_buff *_skb;
3733 int err = -EINVAL;
3734
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003735 /*
3736 * TODO: We have to notify the userland if some data is lost with the
3737 * Streaming Mode.
3738 */
3739
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003740 switch (control & L2CAP_CTRL_SAR) {
3741 case L2CAP_SDU_UNSEGMENTED:
3742 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3743 kfree_skb(pi->sdu);
3744 break;
3745 }
3746
3747 err = sock_queue_rcv_skb(sk, skb);
3748 if (!err)
3749 return 0;
3750
3751 break;
3752
3753 case L2CAP_SDU_START:
3754 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3755 kfree_skb(pi->sdu);
3756 break;
3757 }
3758
3759 pi->sdu_len = get_unaligned_le16(skb->data);
3760 skb_pull(skb, 2);
3761
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003762 if (pi->sdu_len > pi->imtu) {
3763 err = -EMSGSIZE;
3764 break;
3765 }
3766
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003767 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3768 if (!pi->sdu) {
3769 err = -ENOMEM;
3770 break;
3771 }
3772
3773 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3774
3775 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3776 pi->partial_sdu_len = skb->len;
3777 err = 0;
3778 break;
3779
3780 case L2CAP_SDU_CONTINUE:
3781 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3782 break;
3783
3784 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3785
3786 pi->partial_sdu_len += skb->len;
3787 if (pi->partial_sdu_len > pi->sdu_len)
3788 kfree_skb(pi->sdu);
3789 else
3790 err = 0;
3791
3792 break;
3793
3794 case L2CAP_SDU_END:
3795 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3796 break;
3797
3798 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3799
3800 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3801 pi->partial_sdu_len += skb->len;
3802
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003803 if (pi->partial_sdu_len > pi->imtu)
3804 goto drop;
3805
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003806 if (pi->partial_sdu_len == pi->sdu_len) {
3807 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3808 err = sock_queue_rcv_skb(sk, _skb);
3809 if (err < 0)
3810 kfree_skb(_skb);
3811 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003812 err = 0;
3813
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003814drop:
3815 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003816 break;
3817 }
3818
3819 kfree_skb(skb);
3820 return err;
3821}
3822
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003823static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3824{
3825 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003826 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003827
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003828 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003829 if (bt_cb(skb)->tx_seq != tx_seq)
3830 break;
3831
3832 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003833 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003834 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003835 l2cap_pi(sk)->buffer_seq_srej =
3836 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003837 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003838 }
3839}
3840
3841static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3842{
3843 struct l2cap_pinfo *pi = l2cap_pi(sk);
3844 struct srej_list *l, *tmp;
3845 u16 control;
3846
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003847 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003848 if (l->tx_seq == tx_seq) {
3849 list_del(&l->list);
3850 kfree(l);
3851 return;
3852 }
3853 control = L2CAP_SUPER_SELECT_REJECT;
3854 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3855 l2cap_send_sframe(pi, control);
3856 list_del(&l->list);
3857 list_add_tail(&l->list, SREJ_LIST(sk));
3858 }
3859}
3860
3861static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3862{
3863 struct l2cap_pinfo *pi = l2cap_pi(sk);
3864 struct srej_list *new;
3865 u16 control;
3866
3867 while (tx_seq != pi->expected_tx_seq) {
3868 control = L2CAP_SUPER_SELECT_REJECT;
3869 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3870 l2cap_send_sframe(pi, control);
3871
3872 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003873 new->tx_seq = pi->expected_tx_seq;
3874 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003875 list_add_tail(&new->list, SREJ_LIST(sk));
3876 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003877 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003878}
3879
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003880static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3881{
3882 struct l2cap_pinfo *pi = l2cap_pi(sk);
3883 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003884 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003885 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003886 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003887 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003888 int err = 0;
3889
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003890 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3891 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003892
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003893 if (L2CAP_CTRL_FINAL & rx_control &&
3894 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003895 del_timer(&pi->monitor_timer);
3896 if (pi->unacked_frames > 0)
3897 __mod_retrans_timer();
3898 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3899 }
3900
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003901 pi->expected_ack_seq = req_seq;
3902 l2cap_drop_acked_frames(sk);
3903
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003904 if (tx_seq == pi->expected_tx_seq)
3905 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003906
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003907 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3908 if (tx_seq_offset < 0)
3909 tx_seq_offset += 64;
3910
3911 /* invalid tx_seq */
3912 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003913 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003914 goto drop;
3915 }
3916
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003917 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3918 goto drop;
3919
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003920 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3921 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003922
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003923 first = list_first_entry(SREJ_LIST(sk),
3924 struct srej_list, list);
3925 if (tx_seq == first->tx_seq) {
3926 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3927 l2cap_check_srej_gap(sk, tx_seq);
3928
3929 list_del(&first->list);
3930 kfree(first);
3931
3932 if (list_empty(SREJ_LIST(sk))) {
3933 pi->buffer_seq = pi->buffer_seq_srej;
3934 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003935 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003936 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003937 }
3938 } else {
3939 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003940
3941 /* duplicated tx_seq */
3942 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3943 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003944
3945 list_for_each_entry(l, SREJ_LIST(sk), list) {
3946 if (l->tx_seq == tx_seq) {
3947 l2cap_resend_srejframe(sk, tx_seq);
3948 return 0;
3949 }
3950 }
3951 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003952 }
3953 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003954 expected_tx_seq_offset =
3955 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3956 if (expected_tx_seq_offset < 0)
3957 expected_tx_seq_offset += 64;
3958
3959 /* duplicated tx_seq */
3960 if (tx_seq_offset < expected_tx_seq_offset)
3961 goto drop;
3962
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003963 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003964
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003965 BT_DBG("sk %p, Enter SREJ", sk);
3966
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003967 INIT_LIST_HEAD(SREJ_LIST(sk));
3968 pi->buffer_seq_srej = pi->buffer_seq;
3969
3970 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003971 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003972 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3973
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003974 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3975
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003976 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003977
3978 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003979 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003980 return 0;
3981
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003982expected:
3983 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3984
3985 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003986 bt_cb(skb)->tx_seq = tx_seq;
3987 bt_cb(skb)->sar = sar;
3988 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003989 return 0;
3990 }
3991
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003992 err = l2cap_push_rx_skb(sk, skb, rx_control);
3993 if (err < 0)
3994 return 0;
3995
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003996 if (rx_control & L2CAP_CTRL_FINAL) {
3997 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3998 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003999 else
4000 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004001 }
4002
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004003 __mod_ack_timer();
4004
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03004005 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
4006 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004007 l2cap_send_ack(pi);
4008
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004009 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004010
4011drop:
4012 kfree_skb(skb);
4013 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004014}
4015
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004016static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004017{
4018 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004019
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004020 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
4021 rx_control);
4022
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004023 pi->expected_ack_seq = __get_reqseq(rx_control);
4024 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004025
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004026 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004027 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004028 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4029 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4030 (pi->unacked_frames > 0))
4031 __mod_retrans_timer();
4032
4033 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4034 l2cap_send_srejtail(sk);
4035 } else {
4036 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004037 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004038
4039 } else if (rx_control & L2CAP_CTRL_FINAL) {
4040 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004041
4042 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4043 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004044 else
4045 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004046
4047 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004048 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4049 (pi->unacked_frames > 0))
4050 __mod_retrans_timer();
4051
4052 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004053 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004054 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004055 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004056 l2cap_ertm_send(sk);
4057 }
4058}
4059
4060static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
4061{
4062 struct l2cap_pinfo *pi = l2cap_pi(sk);
4063 u8 tx_seq = __get_reqseq(rx_control);
4064
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004065 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4066
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004067 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4068
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03004069 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004070 l2cap_drop_acked_frames(sk);
4071
4072 if (rx_control & L2CAP_CTRL_FINAL) {
4073 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4074 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004075 else
4076 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004077 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004078 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004079
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03004080 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004081 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004082 }
4083}
4084static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
4085{
4086 struct l2cap_pinfo *pi = l2cap_pi(sk);
4087 u8 tx_seq = __get_reqseq(rx_control);
4088
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004089 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4090
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004091 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4092
4093 if (rx_control & L2CAP_CTRL_POLL) {
4094 pi->expected_ack_seq = tx_seq;
4095 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004096
4097 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004098 l2cap_retransmit_one_frame(sk, tx_seq);
4099
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004100 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004101
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004102 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4103 pi->srej_save_reqseq = tx_seq;
4104 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4105 }
4106 } else if (rx_control & L2CAP_CTRL_FINAL) {
4107 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
4108 pi->srej_save_reqseq == tx_seq)
4109 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
4110 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004111 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004112 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004113 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004114 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4115 pi->srej_save_reqseq = tx_seq;
4116 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4117 }
4118 }
4119}
4120
4121static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
4122{
4123 struct l2cap_pinfo *pi = l2cap_pi(sk);
4124 u8 tx_seq = __get_reqseq(rx_control);
4125
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004126 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4127
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004128 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
4129 pi->expected_ack_seq = tx_seq;
4130 l2cap_drop_acked_frames(sk);
4131
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004132 if (rx_control & L2CAP_CTRL_POLL)
4133 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
4134
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004135 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
4136 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03004137 if (rx_control & L2CAP_CTRL_POLL)
4138 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004139 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004140 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004141
4142 if (rx_control & L2CAP_CTRL_POLL)
4143 l2cap_send_srejtail(sk);
4144 else
4145 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004146}
4147
4148static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
4149{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004150 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
4151
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03004152 if (L2CAP_CTRL_FINAL & rx_control &&
4153 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004154 del_timer(&l2cap_pi(sk)->monitor_timer);
4155 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004156 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004157 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004158 }
4159
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004160 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
4161 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004162 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004163 break;
4164
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004165 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004166 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004167 break;
4168
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004169 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004170 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004171 break;
4172
4173 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004174 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004175 break;
4176 }
4177
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004178 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004179 return 0;
4180}
4181
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004182static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4183{
4184 struct l2cap_pinfo *pi = l2cap_pi(sk);
4185 u16 control;
4186 u8 req_seq;
4187 int len, next_tx_seq_offset, req_seq_offset;
4188
4189 control = get_unaligned_le16(skb->data);
4190 skb_pull(skb, 2);
4191 len = skb->len;
4192
4193 /*
4194 * We can just drop the corrupted I-frame here.
4195 * Receiver will miss it and start proper recovery
4196 * procedures and ask retransmission.
4197 */
4198 if (l2cap_check_fcs(pi, skb))
4199 goto drop;
4200
4201 if (__is_sar_start(control) && __is_iframe(control))
4202 len -= 2;
4203
4204 if (pi->fcs == L2CAP_FCS_CRC16)
4205 len -= 2;
4206
4207 if (len > pi->mps) {
4208 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4209 goto drop;
4210 }
4211
4212 req_seq = __get_reqseq(control);
4213 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4214 if (req_seq_offset < 0)
4215 req_seq_offset += 64;
4216
4217 next_tx_seq_offset =
4218 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4219 if (next_tx_seq_offset < 0)
4220 next_tx_seq_offset += 64;
4221
4222 /* check for invalid req-seq */
4223 if (req_seq_offset > next_tx_seq_offset) {
4224 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4225 goto drop;
4226 }
4227
4228 if (__is_iframe(control)) {
4229 if (len < 0) {
4230 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4231 goto drop;
4232 }
4233
4234 l2cap_data_channel_iframe(sk, control, skb);
4235 } else {
4236 if (len != 0) {
4237 BT_ERR("%d", len);
4238 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4239 goto drop;
4240 }
4241
4242 l2cap_data_channel_sframe(sk, control, skb);
4243 }
4244
4245 return 0;
4246
4247drop:
4248 kfree_skb(skb);
4249 return 0;
4250}
4251
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4253{
4254 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004255 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004256 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004257 u8 tx_seq;
4258 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259
4260 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4261 if (!sk) {
4262 BT_DBG("unknown cid 0x%4.4x", cid);
4263 goto drop;
4264 }
4265
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004266 pi = l2cap_pi(sk);
4267
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 BT_DBG("sk %p, len %d", sk, skb->len);
4269
4270 if (sk->sk_state != BT_CONNECTED)
4271 goto drop;
4272
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004273 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004274 case L2CAP_MODE_BASIC:
4275 /* If socket recv buffers overflows we drop data here
4276 * which is *bad* because L2CAP has to be reliable.
4277 * But we don't have any other choice. L2CAP doesn't
4278 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004280 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004281 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004283 if (!sock_queue_rcv_skb(sk, skb))
4284 goto done;
4285 break;
4286
4287 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004288 if (!sock_owned_by_user(sk)) {
4289 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004290 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004291 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004292 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004293 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004294
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004295 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004296
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004297 case L2CAP_MODE_STREAMING:
4298 control = get_unaligned_le16(skb->data);
4299 skb_pull(skb, 2);
4300 len = skb->len;
4301
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004302 if (l2cap_check_fcs(pi, skb))
4303 goto drop;
4304
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004305 if (__is_sar_start(control))
4306 len -= 2;
4307
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004308 if (pi->fcs == L2CAP_FCS_CRC16)
4309 len -= 2;
4310
Nathan Holstein51893f82010-06-09 15:46:25 -04004311 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004312 goto drop;
4313
4314 tx_seq = __get_txseq(control);
4315
4316 if (pi->expected_tx_seq == tx_seq)
4317 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4318 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004319 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004320
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004321 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004322
4323 goto done;
4324
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004325 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004326 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004327 break;
4328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329
4330drop:
4331 kfree_skb(skb);
4332
4333done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004334 if (sk)
4335 bh_unlock_sock(sk);
4336
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 return 0;
4338}
4339
Al Viro8e036fc2007-07-29 00:16:36 -07004340static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341{
4342 struct sock *sk;
4343
4344 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4345 if (!sk)
4346 goto drop;
4347
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004348 bh_lock_sock(sk);
4349
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 BT_DBG("sk %p, len %d", sk, skb->len);
4351
4352 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4353 goto drop;
4354
4355 if (l2cap_pi(sk)->imtu < skb->len)
4356 goto drop;
4357
4358 if (!sock_queue_rcv_skb(sk, skb))
4359 goto done;
4360
4361drop:
4362 kfree_skb(skb);
4363
4364done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004365 if (sk)
4366 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 return 0;
4368}
4369
4370static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4371{
4372 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004373 u16 cid, len;
4374 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
4376 skb_pull(skb, L2CAP_HDR_SIZE);
4377 cid = __le16_to_cpu(lh->cid);
4378 len = __le16_to_cpu(lh->len);
4379
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004380 if (len != skb->len) {
4381 kfree_skb(skb);
4382 return;
4383 }
4384
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4386
4387 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004388 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389 l2cap_sig_channel(conn, skb);
4390 break;
4391
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004392 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004393 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 skb_pull(skb, 2);
4395 l2cap_conless_channel(conn, psm, skb);
4396 break;
4397
4398 default:
4399 l2cap_data_channel(conn, cid, skb);
4400 break;
4401 }
4402}
4403
4404/* ---- L2CAP interface with lower layer (HCI) ---- */
4405
4406static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4407{
4408 int exact = 0, lm1 = 0, lm2 = 0;
4409 register struct sock *sk;
4410 struct hlist_node *node;
4411
4412 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004413 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414
4415 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4416
4417 /* Find listening sockets and check their link_mode */
4418 read_lock(&l2cap_sk_list.lock);
4419 sk_for_each(sk, node, &l2cap_sk_list.head) {
4420 if (sk->sk_state != BT_LISTEN)
4421 continue;
4422
4423 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004424 lm1 |= HCI_LM_ACCEPT;
4425 if (l2cap_pi(sk)->role_switch)
4426 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004428 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4429 lm2 |= HCI_LM_ACCEPT;
4430 if (l2cap_pi(sk)->role_switch)
4431 lm2 |= HCI_LM_MASTER;
4432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 }
4434 read_unlock(&l2cap_sk_list.lock);
4435
4436 return exact ? lm1 : lm2;
4437}
4438
4439static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4440{
Marcel Holtmann01394182006-07-03 10:02:46 +02004441 struct l2cap_conn *conn;
4442
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4444
4445 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004446 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
4448 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449 conn = l2cap_conn_add(hcon, status);
4450 if (conn)
4451 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004452 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 l2cap_conn_del(hcon, bt_err(status));
4454
4455 return 0;
4456}
4457
Marcel Holtmann2950f212009-02-12 14:02:50 +01004458static int l2cap_disconn_ind(struct hci_conn *hcon)
4459{
4460 struct l2cap_conn *conn = hcon->l2cap_data;
4461
4462 BT_DBG("hcon %p", hcon);
4463
4464 if (hcon->type != ACL_LINK || !conn)
4465 return 0x13;
4466
4467 return conn->disc_reason;
4468}
4469
4470static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471{
4472 BT_DBG("hcon %p reason %d", hcon, reason);
4473
4474 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004475 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476
4477 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004478
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479 return 0;
4480}
4481
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004482static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4483{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004484 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004485 return;
4486
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004487 if (encrypt == 0x00) {
4488 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4489 l2cap_sock_clear_timer(sk);
4490 l2cap_sock_set_timer(sk, HZ * 5);
4491 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4492 __l2cap_sock_close(sk, ECONNREFUSED);
4493 } else {
4494 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4495 l2cap_sock_clear_timer(sk);
4496 }
4497}
4498
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004499static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500{
4501 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004502 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Marcel Holtmann01394182006-07-03 10:02:46 +02004505 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004507
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 l = &conn->chan_list;
4509
4510 BT_DBG("conn %p", conn);
4511
4512 read_lock(&l->lock);
4513
4514 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4515 bh_lock_sock(sk);
4516
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004517 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4518 bh_unlock_sock(sk);
4519 continue;
4520 }
4521
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004522 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004523 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004524 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004525 bh_unlock_sock(sk);
4526 continue;
4527 }
4528
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004529 if (sk->sk_state == BT_CONNECT) {
4530 if (!status) {
4531 struct l2cap_conn_req req;
4532 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4533 req.psm = l2cap_pi(sk)->psm;
4534
4535 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004536 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004537
4538 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4539 L2CAP_CONN_REQ, sizeof(req), &req);
4540 } else {
4541 l2cap_sock_clear_timer(sk);
4542 l2cap_sock_set_timer(sk, HZ / 10);
4543 }
4544 } else if (sk->sk_state == BT_CONNECT2) {
4545 struct l2cap_conn_rsp rsp;
4546 __u16 result;
4547
4548 if (!status) {
4549 sk->sk_state = BT_CONFIG;
4550 result = L2CAP_CR_SUCCESS;
4551 } else {
4552 sk->sk_state = BT_DISCONN;
4553 l2cap_sock_set_timer(sk, HZ / 10);
4554 result = L2CAP_CR_SEC_BLOCK;
4555 }
4556
4557 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4558 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4559 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004560 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004561 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4562 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 }
4564
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565 bh_unlock_sock(sk);
4566 }
4567
4568 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004569
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 return 0;
4571}
4572
4573static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4574{
4575 struct l2cap_conn *conn = hcon->l2cap_data;
4576
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004577 if (!conn)
4578 conn = l2cap_conn_add(hcon, 0);
4579
4580 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 goto drop;
4582
4583 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4584
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004585 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004587 struct sock *sk;
4588 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589 int len;
4590
4591 if (conn->rx_len) {
4592 BT_ERR("Unexpected start frame (len %d)", skb->len);
4593 kfree_skb(conn->rx_skb);
4594 conn->rx_skb = NULL;
4595 conn->rx_len = 0;
4596 l2cap_conn_unreliable(conn, ECOMM);
4597 }
4598
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004599 /* Start fragment always begin with Basic L2CAP header */
4600 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 BT_ERR("Frame is too short (len %d)", skb->len);
4602 l2cap_conn_unreliable(conn, ECOMM);
4603 goto drop;
4604 }
4605
4606 hdr = (struct l2cap_hdr *) skb->data;
4607 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004608 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609
4610 if (len == skb->len) {
4611 /* Complete frame received */
4612 l2cap_recv_frame(conn, skb);
4613 return 0;
4614 }
4615
4616 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4617
4618 if (skb->len > len) {
4619 BT_ERR("Frame is too long (len %d, expected len %d)",
4620 skb->len, len);
4621 l2cap_conn_unreliable(conn, ECOMM);
4622 goto drop;
4623 }
4624
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004625 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4626
4627 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4628 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
4629 len, l2cap_pi(sk)->imtu);
4630 bh_unlock_sock(sk);
4631 l2cap_conn_unreliable(conn, ECOMM);
4632 goto drop;
4633 }
4634
4635 if (sk)
4636 bh_unlock_sock(sk);
4637
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004639 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4640 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641 goto drop;
4642
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004643 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004644 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645 conn->rx_len = len - skb->len;
4646 } else {
4647 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4648
4649 if (!conn->rx_len) {
4650 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4651 l2cap_conn_unreliable(conn, ECOMM);
4652 goto drop;
4653 }
4654
4655 if (skb->len > conn->rx_len) {
4656 BT_ERR("Fragment is too long (len %d, expected %d)",
4657 skb->len, conn->rx_len);
4658 kfree_skb(conn->rx_skb);
4659 conn->rx_skb = NULL;
4660 conn->rx_len = 0;
4661 l2cap_conn_unreliable(conn, ECOMM);
4662 goto drop;
4663 }
4664
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004665 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004666 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667 conn->rx_len -= skb->len;
4668
4669 if (!conn->rx_len) {
4670 /* Complete frame received */
4671 l2cap_recv_frame(conn, conn->rx_skb);
4672 conn->rx_skb = NULL;
4673 }
4674 }
4675
4676drop:
4677 kfree_skb(skb);
4678 return 0;
4679}
4680
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004681static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682{
4683 struct sock *sk;
4684 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685
4686 read_lock_bh(&l2cap_sk_list.lock);
4687
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004688 sk_for_each(sk, node, &l2cap_sk_list.head) {
4689 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004690
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004691 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4692 batostr(&bt_sk(sk)->src),
4693 batostr(&bt_sk(sk)->dst),
4694 sk->sk_state, __le16_to_cpu(pi->psm),
4695 pi->scid, pi->dcid,
4696 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004700
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004701 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702}
4703
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004704static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4705{
4706 return single_open(file, l2cap_debugfs_show, inode->i_private);
4707}
4708
4709static const struct file_operations l2cap_debugfs_fops = {
4710 .open = l2cap_debugfs_open,
4711 .read = seq_read,
4712 .llseek = seq_lseek,
4713 .release = single_release,
4714};
4715
4716static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718static struct hci_proto l2cap_hci_proto = {
4719 .name = "L2CAP",
4720 .id = HCI_PROTO_L2CAP,
4721 .connect_ind = l2cap_connect_ind,
4722 .connect_cfm = l2cap_connect_cfm,
4723 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004724 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004725 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 .recv_acldata = l2cap_recv_acldata
4727};
4728
4729static int __init l2cap_init(void)
4730{
4731 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004732
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004733 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734 if (err < 0)
4735 return err;
4736
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004737 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004738 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004739 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740 goto error;
4741 }
4742
4743 err = hci_register_proto(&l2cap_hci_proto);
4744 if (err < 0) {
4745 BT_ERR("L2CAP protocol registration failed");
4746 bt_sock_unregister(BTPROTO_L2CAP);
4747 goto error;
4748 }
4749
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004750 if (bt_debugfs) {
4751 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4752 bt_debugfs, NULL, &l2cap_debugfs_fops);
4753 if (!l2cap_debugfs)
4754 BT_ERR("Failed to create L2CAP debug file");
4755 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756
4757 BT_INFO("L2CAP ver %s", VERSION);
4758 BT_INFO("L2CAP socket layer initialized");
4759
4760 return 0;
4761
4762error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004763 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004764 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004765 return err;
4766}
4767
4768static void __exit l2cap_exit(void)
4769{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004770 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004772 flush_workqueue(_busy_wq);
4773 destroy_workqueue(_busy_wq);
4774
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4776 BT_ERR("L2CAP protocol unregistration failed");
4777
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004778 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779}
4780
4781void l2cap_load(void)
4782{
4783 /* Dummy function to trigger automatic L2CAP module loading by
4784 * other modules that use L2CAP sockets but don't use any other
4785 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786}
4787EXPORT_SYMBOL(l2cap_load);
4788
4789module_init(l2cap_init);
4790module_exit(l2cap_exit);
4791
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004792module_param(disable_ertm, bool, 0644);
4793MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004794
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004795MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4797MODULE_VERSION(VERSION);
4798MODULE_LICENSE("GPL");
4799MODULE_ALIAS("bt-proto-0");