blob: 6a33d269389e63de6f7243e241826e334a09307e [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
4
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth L2CAP core and sockets. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080030#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
32#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/sched.h>
34#include <linux/slab.h>
35#include <linux/poll.h>
36#include <linux/fcntl.h>
37#include <linux/init.h>
38#include <linux/interrupt.h>
39#include <linux/socket.h>
40#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080042#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010043#include <linux/debugfs.h>
44#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030045#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030046#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <net/sock.h>
48
49#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <asm/unaligned.h>
51
52#include <net/bluetooth/bluetooth.h>
53#include <net/bluetooth/hci_core.h>
54#include <net/bluetooth/l2cap.h>
55
Marcel Holtmann44dd46d2009-05-02 19:09:01 -070056#define VERSION "2.14"
57
58static int enable_ertm = 0;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Eric Dumazet90ddc4f2005-12-22 12:49:22 -080063static const struct proto_ops l2cap_sock_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030065static struct workqueue_struct *_busy_wq;
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct 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, int reason);
74static void l2cap_sock_close(struct sock *sk);
75static void l2cap_sock_kill(struct sock *sk);
76
77static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
78 u8 code, u8 ident, u16 dlen, void *data);
79
80/* ---- L2CAP timers ---- */
81static void l2cap_sock_timeout(unsigned long arg)
82{
83 struct sock *sk = (struct sock *) arg;
Marcel Holtmannb1235d72008-07-14 20:13:54 +020084 int reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86 BT_DBG("sock %p state %d", sk, sk->sk_state);
87
88 bh_lock_sock(sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +020089
Marcel Holtmannf62e4322009-01-15 21:58:44 +010090 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
91 reason = ECONNREFUSED;
92 else if (sk->sk_state == BT_CONNECT &&
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +010093 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
Marcel Holtmannb1235d72008-07-14 20:13:54 +020094 reason = ECONNREFUSED;
95 else
96 reason = ETIMEDOUT;
97
98 __l2cap_sock_close(sk, reason);
99
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 bh_unlock_sock(sk);
101
102 l2cap_sock_kill(sk);
103 sock_put(sk);
104}
105
106static void l2cap_sock_set_timer(struct sock *sk, long timeout)
107{
108 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
109 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
110}
111
112static void l2cap_sock_clear_timer(struct sock *sk)
113{
114 BT_DBG("sock %p state %d", sk, sk->sk_state);
115 sk_stop_timer(sk, &sk->sk_timer);
116}
117
Marcel Holtmann01394182006-07-03 10:02:46 +0200118/* ---- L2CAP channels ---- */
119static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
120{
121 struct sock *s;
122 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
123 if (l2cap_pi(s)->dcid == cid)
124 break;
125 }
126 return s;
127}
128
129static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
130{
131 struct sock *s;
132 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
133 if (l2cap_pi(s)->scid == cid)
134 break;
135 }
136 return s;
137}
138
139/* Find channel with given SCID.
140 * Returns locked socket */
141static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
142{
143 struct sock *s;
144 read_lock(&l->lock);
145 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300146 if (s)
147 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200148 read_unlock(&l->lock);
149 return s;
150}
151
152static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
153{
154 struct sock *s;
155 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
156 if (l2cap_pi(s)->ident == ident)
157 break;
158 }
159 return s;
160}
161
162static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
163{
164 struct sock *s;
165 read_lock(&l->lock);
166 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300167 if (s)
168 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200169 read_unlock(&l->lock);
170 return s;
171}
172
173static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
174{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300175 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200176
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300177 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300178 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200179 return cid;
180 }
181
182 return 0;
183}
184
185static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
186{
187 sock_hold(sk);
188
189 if (l->head)
190 l2cap_pi(l->head)->prev_c = sk;
191
192 l2cap_pi(sk)->next_c = l->head;
193 l2cap_pi(sk)->prev_c = NULL;
194 l->head = sk;
195}
196
197static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
198{
199 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
200
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200201 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202 if (sk == l->head)
203 l->head = next;
204
205 if (next)
206 l2cap_pi(next)->prev_c = prev;
207 if (prev)
208 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200209 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200210
211 __sock_put(sk);
212}
213
214static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
215{
216 struct l2cap_chan_list *l = &conn->chan_list;
217
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300218 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
219 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200220
Marcel Holtmann2950f212009-02-12 14:02:50 +0100221 conn->disc_reason = 0x13;
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = conn;
224
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300225 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200226 /* Alloc CID for connection-oriented socket */
227 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
228 } else if (sk->sk_type == SOCK_DGRAM) {
229 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300230 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
231 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200232 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
233 } else {
234 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300235 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
236 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200237 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
238 }
239
240 __l2cap_chan_link(l, sk);
241
242 if (parent)
243 bt_accept_enqueue(parent, sk);
244}
245
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900246/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200247 * Must be called on the locked socket. */
248static void l2cap_chan_del(struct sock *sk, int err)
249{
250 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
251 struct sock *parent = bt_sk(sk)->parent;
252
253 l2cap_sock_clear_timer(sk);
254
255 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
256
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900257 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200258 /* Unlink from channel list */
259 l2cap_chan_unlink(&conn->chan_list, sk);
260 l2cap_pi(sk)->conn = NULL;
261 hci_conn_put(conn->hcon);
262 }
263
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200264 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200265 sock_set_flag(sk, SOCK_ZAPPED);
266
267 if (err)
268 sk->sk_err = err;
269
270 if (parent) {
271 bt_accept_unlink(sk);
272 parent->sk_data_ready(parent, 0);
273 } else
274 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300275
276 skb_queue_purge(TX_QUEUE(sk));
277
278 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
279 struct srej_list *l, *tmp;
280
281 del_timer(&l2cap_pi(sk)->retrans_timer);
282 del_timer(&l2cap_pi(sk)->monitor_timer);
283 del_timer(&l2cap_pi(sk)->ack_timer);
284
285 skb_queue_purge(SREJ_QUEUE(sk));
286 skb_queue_purge(BUSY_QUEUE(sk));
287
288 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
289 list_del(&l->list);
290 kfree(l);
291 }
292 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200293}
294
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200295/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100296static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200297{
298 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100299 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200300
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100301 if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
302 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
303 auth_type = HCI_AT_NO_BONDING_MITM;
304 else
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300305 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100306
307 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
308 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
309 } else {
310 switch (l2cap_pi(sk)->sec_level) {
311 case BT_SECURITY_HIGH:
312 auth_type = HCI_AT_GENERAL_BONDING_MITM;
313 break;
314 case BT_SECURITY_MEDIUM:
315 auth_type = HCI_AT_GENERAL_BONDING;
316 break;
317 default:
318 auth_type = HCI_AT_NO_BONDING;
319 break;
320 }
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100321 }
322
323 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
324 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200325}
326
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200327static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
328{
329 u8 id;
330
331 /* Get next available identificator.
332 * 1 - 128 are used by kernel.
333 * 129 - 199 are reserved.
334 * 200 - 254 are used by utilities like l2ping, etc.
335 */
336
337 spin_lock_bh(&conn->lock);
338
339 if (++conn->tx_ident > 128)
340 conn->tx_ident = 1;
341
342 id = conn->tx_ident;
343
344 spin_unlock_bh(&conn->lock);
345
346 return id;
347}
348
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300349static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200350{
351 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
352
353 BT_DBG("code 0x%2.2x", code);
354
355 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300356 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200357
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300358 hci_send_acl(conn->hcon, skb, 0);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200359}
360
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300361static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300362{
363 struct sk_buff *skb;
364 struct l2cap_hdr *lh;
365 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300366 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300367 int count, hlen = L2CAP_HDR_SIZE + 2;
368
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300369 if (sk->sk_state != BT_CONNECTED)
370 return;
371
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300372 if (pi->fcs == L2CAP_FCS_CRC16)
373 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374
375 BT_DBG("pi %p, control 0x%2.2x", pi, control);
376
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300377 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300378 control |= L2CAP_CTRL_FRAME_TYPE;
379
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300380 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
381 control |= L2CAP_CTRL_FINAL;
382 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
383 }
384
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300385 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
386 control |= L2CAP_CTRL_POLL;
387 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
388 }
389
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300390 skb = bt_skb_alloc(count, GFP_ATOMIC);
391 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300392 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300393
394 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300395 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300396 lh->cid = cpu_to_le16(pi->dcid);
397 put_unaligned_le16(control, skb_put(skb, 2));
398
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300399 if (pi->fcs == L2CAP_FCS_CRC16) {
400 u16 fcs = crc16(0, (u8 *)lh, count - 2);
401 put_unaligned_le16(fcs, skb_put(skb, 2));
402 }
403
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300404 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300405}
406
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300407static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300408{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300409 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300410 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300411 pi->conn_state |= L2CAP_CONN_RNR_SENT;
412 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300413 control |= L2CAP_SUPER_RCV_READY;
414
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300415 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
416
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300417 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300418}
419
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300420static inline int __l2cap_no_conn_pending(struct sock *sk)
421{
422 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
423}
424
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200425static void l2cap_do_start(struct sock *sk)
426{
427 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
428
429 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100430 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
431 return;
432
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300433 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200434 struct l2cap_conn_req req;
435 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
436 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200437
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300439 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200440
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200441 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200442 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200443 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200444 } else {
445 struct l2cap_info_req req;
446 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
447
448 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
449 conn->info_ident = l2cap_get_ident(conn);
450
451 mod_timer(&conn->info_timer, jiffies +
452 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
453
454 l2cap_send_cmd(conn, conn->info_ident,
455 L2CAP_INFO_REQ, sizeof(req), &req);
456 }
457}
458
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300459static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
460{
461 u32 local_feat_mask = l2cap_feat_mask;
462 if (enable_ertm)
463 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
464
465 switch (mode) {
466 case L2CAP_MODE_ERTM:
467 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
468 case L2CAP_MODE_STREAMING:
469 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
470 default:
471 return 0x00;
472 }
473}
474
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300475static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300476{
477 struct l2cap_disconn_req req;
478
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300479 if (!conn)
480 return;
481
482 skb_queue_purge(TX_QUEUE(sk));
483
484 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
485 del_timer(&l2cap_pi(sk)->retrans_timer);
486 del_timer(&l2cap_pi(sk)->monitor_timer);
487 del_timer(&l2cap_pi(sk)->ack_timer);
488 }
489
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300490 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
491 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
492 l2cap_send_cmd(conn, l2cap_get_ident(conn),
493 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300494
495 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300496 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300497}
498
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200500static void l2cap_conn_start(struct l2cap_conn *conn)
501{
502 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300503 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200504 struct sock *sk;
505
506 BT_DBG("conn %p", conn);
507
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300508 INIT_LIST_HEAD(&del.list);
509
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200510 read_lock(&l->lock);
511
512 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
513 bh_lock_sock(sk);
514
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300515 if (sk->sk_type != SOCK_SEQPACKET &&
516 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200517 bh_unlock_sock(sk);
518 continue;
519 }
520
521 if (sk->sk_state == BT_CONNECT) {
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300522 if (l2cap_check_security(sk) &&
523 __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200524 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300525
526 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
527 conn->feat_mask)
528 && l2cap_pi(sk)->conf_state &
529 L2CAP_CONF_STATE2_DEVICE) {
530 tmp1 = kzalloc(sizeof(struct srej_list),
531 GFP_ATOMIC);
532 tmp1->sk = sk;
533 list_add_tail(&tmp1->list, &del.list);
534 bh_unlock_sock(sk);
535 continue;
536 }
537
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200538 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
539 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200540
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200541 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300542 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200543
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200544 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200545 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200546 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200547 } else if (sk->sk_state == BT_CONNECT2) {
548 struct l2cap_conn_rsp rsp;
549 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
550 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
551
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100552 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100553 if (bt_sk(sk)->defer_setup) {
554 struct sock *parent = bt_sk(sk)->parent;
555 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
556 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
557 parent->sk_data_ready(parent, 0);
558
559 } else {
560 sk->sk_state = BT_CONFIG;
561 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
562 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
563 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200564 } else {
565 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
566 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
567 }
568
569 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
570 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
571 }
572
573 bh_unlock_sock(sk);
574 }
575
576 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300577
578 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
579 bh_lock_sock(tmp1->sk);
580 __l2cap_sock_close(tmp1->sk, ECONNRESET);
581 bh_unlock_sock(tmp1->sk);
582 list_del(&tmp1->list);
583 kfree(tmp1);
584 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200585}
586
587static void l2cap_conn_ready(struct l2cap_conn *conn)
588{
589 struct l2cap_chan_list *l = &conn->chan_list;
590 struct sock *sk;
591
592 BT_DBG("conn %p", conn);
593
594 read_lock(&l->lock);
595
596 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
597 bh_lock_sock(sk);
598
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300599 if (sk->sk_type != SOCK_SEQPACKET &&
600 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200601 l2cap_sock_clear_timer(sk);
602 sk->sk_state = BT_CONNECTED;
603 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200604 } else if (sk->sk_state == BT_CONNECT)
605 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200606
607 bh_unlock_sock(sk);
608 }
609
610 read_unlock(&l->lock);
611}
612
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200613/* Notify sockets that we cannot guaranty reliability anymore */
614static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
615{
616 struct l2cap_chan_list *l = &conn->chan_list;
617 struct sock *sk;
618
619 BT_DBG("conn %p", conn);
620
621 read_lock(&l->lock);
622
623 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100624 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200625 sk->sk_err = err;
626 }
627
628 read_unlock(&l->lock);
629}
630
631static void l2cap_info_timeout(unsigned long arg)
632{
633 struct l2cap_conn *conn = (void *) arg;
634
Marcel Holtmann984947d2009-02-06 23:35:19 +0100635 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100636 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100637
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200638 l2cap_conn_start(conn);
639}
640
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
642{
Marcel Holtmann01394182006-07-03 10:02:46 +0200643 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Marcel Holtmann01394182006-07-03 10:02:46 +0200645 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return conn;
647
Marcel Holtmann01394182006-07-03 10:02:46 +0200648 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
649 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
652 hcon->l2cap_data = conn;
653 conn->hcon = hcon;
654
Marcel Holtmann01394182006-07-03 10:02:46 +0200655 BT_DBG("hcon %p conn %p", hcon, conn);
656
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 conn->mtu = hcon->hdev->acl_mtu;
658 conn->src = &hcon->hdev->bdaddr;
659 conn->dst = &hcon->dst;
660
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200661 conn->feat_mask = 0;
662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 spin_lock_init(&conn->lock);
664 rwlock_init(&conn->chan_list.lock);
665
Dave Young45054dc2009-10-18 20:28:30 +0000666 setup_timer(&conn->info_timer, l2cap_info_timeout,
667 (unsigned long) conn);
668
Marcel Holtmann2950f212009-02-12 14:02:50 +0100669 conn->disc_reason = 0x13;
670
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 return conn;
672}
673
Marcel Holtmann01394182006-07-03 10:02:46 +0200674static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
Marcel Holtmann01394182006-07-03 10:02:46 +0200676 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 struct sock *sk;
678
Marcel Holtmann01394182006-07-03 10:02:46 +0200679 if (!conn)
680 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
682 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
683
Wei Yongjun7585b972009-02-25 18:29:52 +0800684 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
686 /* Kill channels */
687 while ((sk = conn->chan_list.head)) {
688 bh_lock_sock(sk);
689 l2cap_chan_del(sk, err);
690 bh_unlock_sock(sk);
691 l2cap_sock_kill(sk);
692 }
693
Dave Young8e8440f2008-03-03 12:18:55 -0800694 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
695 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 hcon->l2cap_data = NULL;
698 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
702{
703 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200704 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200706 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707}
708
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709/* ---- Socket interface ---- */
Al Viro8e036fc2007-07-29 00:16:36 -0700710static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
712 struct sock *sk;
713 struct hlist_node *node;
714 sk_for_each(sk, node, &l2cap_sk_list.head)
715 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
716 goto found;
717 sk = NULL;
718found:
719 return sk;
720}
721
722/* Find socket with psm and source bdaddr.
723 * Returns closest match.
724 */
Al Viro8e036fc2007-07-29 00:16:36 -0700725static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
727 struct sock *sk = NULL, *sk1 = NULL;
728 struct hlist_node *node;
729
730 sk_for_each(sk, node, &l2cap_sk_list.head) {
731 if (state && sk->sk_state != state)
732 continue;
733
734 if (l2cap_pi(sk)->psm == psm) {
735 /* Exact match. */
736 if (!bacmp(&bt_sk(sk)->src, src))
737 break;
738
739 /* Closest match */
740 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
741 sk1 = sk;
742 }
743 }
744 return node ? sk : sk1;
745}
746
747/* Find socket with given address (psm, src).
748 * Returns locked socket */
Al Viro8e036fc2007-07-29 00:16:36 -0700749static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
751 struct sock *s;
752 read_lock(&l2cap_sk_list.lock);
753 s = __l2cap_get_sock_by_psm(state, psm, src);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300754 if (s)
755 bh_lock_sock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 read_unlock(&l2cap_sk_list.lock);
757 return s;
758}
759
760static void l2cap_sock_destruct(struct sock *sk)
761{
762 BT_DBG("sk %p", sk);
763
764 skb_queue_purge(&sk->sk_receive_queue);
765 skb_queue_purge(&sk->sk_write_queue);
766}
767
768static void l2cap_sock_cleanup_listen(struct sock *parent)
769{
770 struct sock *sk;
771
772 BT_DBG("parent %p", parent);
773
774 /* Close not yet accepted channels */
775 while ((sk = bt_accept_dequeue(parent, NULL)))
776 l2cap_sock_close(sk);
777
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200778 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 sock_set_flag(parent, SOCK_ZAPPED);
780}
781
782/* Kill socket (only if zapped and orphan)
783 * Must be called on unlocked socket.
784 */
785static void l2cap_sock_kill(struct sock *sk)
786{
787 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
788 return;
789
790 BT_DBG("sk %p state %d", sk, sk->sk_state);
791
792 /* Kill poor orphan */
793 bt_sock_unlink(&l2cap_sk_list, sk);
794 sock_set_flag(sk, SOCK_DEAD);
795 sock_put(sk);
796}
797
798static void __l2cap_sock_close(struct sock *sk, int reason)
799{
800 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
801
802 switch (sk->sk_state) {
803 case BT_LISTEN:
804 l2cap_sock_cleanup_listen(sk);
805 break;
806
807 case BT_CONNECTED:
808 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300809 if (sk->sk_type == SOCK_SEQPACKET ||
810 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300814 l2cap_send_disconn_req(conn, sk, reason);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200815 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 break;
818
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100819 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300820 if (sk->sk_type == SOCK_SEQPACKET ||
821 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100822 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
823 struct l2cap_conn_rsp rsp;
824 __u16 result;
825
826 if (bt_sk(sk)->defer_setup)
827 result = L2CAP_CR_SEC_BLOCK;
828 else
829 result = L2CAP_CR_BAD_PSM;
830
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
862static void l2cap_sock_init(struct sock *sk, struct sock *parent)
863{
864 struct l2cap_pinfo *pi = l2cap_pi(sk);
865
866 BT_DBG("sk %p", sk);
867
868 if (parent) {
869 sk->sk_type = parent->sk_type;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100870 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 pi->imtu = l2cap_pi(parent)->imtu;
873 pi->omtu = l2cap_pi(parent)->omtu;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300874 pi->conf_state = l2cap_pi(parent)->conf_state;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700875 pi->mode = l2cap_pi(parent)->mode;
876 pi->fcs = l2cap_pi(parent)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -0300877 pi->max_tx = l2cap_pi(parent)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -0300878 pi->tx_win = l2cap_pi(parent)->tx_win;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100879 pi->sec_level = l2cap_pi(parent)->sec_level;
880 pi->role_switch = l2cap_pi(parent)->role_switch;
881 pi->force_reliable = l2cap_pi(parent)->force_reliable;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 } else {
883 pi->imtu = L2CAP_DEFAULT_MTU;
884 pi->omtu = 0;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300885 if (enable_ertm && sk->sk_type == SOCK_STREAM) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300886 pi->mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300887 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
888 } else {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300889 pi->mode = L2CAP_MODE_BASIC;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300890 }
Gustavo F. Padovanfd059b92010-05-10 14:22:56 -0300891 pi->max_tx = L2CAP_DEFAULT_MAX_TX;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700892 pi->fcs = L2CAP_FCS_CRC16;
Gustavo F. Padovanfd059b92010-05-10 14:22:56 -0300893 pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100894 pi->sec_level = BT_SECURITY_LOW;
895 pi->role_switch = 0;
896 pi->force_reliable = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 }
898
899 /* Default config options */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +0200900 pi->conf_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Dave Young45054dc2009-10-18 20:28:30 +0000902 skb_queue_head_init(TX_QUEUE(sk));
903 skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300904 skb_queue_head_init(BUSY_QUEUE(sk));
Dave Young45054dc2009-10-18 20:28:30 +0000905 INIT_LIST_HEAD(SREJ_LIST(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906}
907
908static struct proto l2cap_proto = {
909 .name = "L2CAP",
910 .owner = THIS_MODULE,
911 .obj_size = sizeof(struct l2cap_pinfo)
912};
913
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700914static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915{
916 struct sock *sk;
917
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700918 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 if (!sk)
920 return NULL;
921
922 sock_init_data(sock, sk);
923 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
924
925 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200926 sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 sock_reset_flag(sk, SOCK_ZAPPED);
929
930 sk->sk_protocol = proto;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200931 sk->sk_state = BT_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200933 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
935 bt_sock_link(&l2cap_sk_list, sk);
936 return sk;
937}
938
Eric Paris3f378b62009-11-05 22:18:14 -0800939static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
940 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
942 struct sock *sk;
943
944 BT_DBG("sock %p", sock);
945
946 sock->state = SS_UNCONNECTED;
947
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300948 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
950 return -ESOCKTNOSUPPORT;
951
Eric Parisc84b3262009-11-05 20:45:52 -0800952 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return -EPERM;
954
955 sock->ops = &l2cap_sock_ops;
956
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700957 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 if (!sk)
959 return -ENOMEM;
960
961 l2cap_sock_init(sk, NULL);
962 return 0;
963}
964
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100965static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100968 struct sockaddr_l2 la;
969 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100971 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
973 if (!addr || addr->sa_family != AF_BLUETOOTH)
974 return -EINVAL;
975
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100976 memset(&la, 0, sizeof(la));
977 len = min_t(unsigned int, sizeof(la), alen);
978 memcpy(&la, addr, len);
979
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100980 if (la.l2_cid)
981 return -EINVAL;
982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 lock_sock(sk);
984
985 if (sk->sk_state != BT_OPEN) {
986 err = -EBADFD;
987 goto done;
988 }
989
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200990 if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
Marcel Holtmann847641d2007-01-22 22:00:45 +0100991 !capable(CAP_NET_BIND_SERVICE)) {
992 err = -EACCES;
993 goto done;
994 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 write_lock_bh(&l2cap_sk_list.lock);
997
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100998 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 err = -EADDRINUSE;
1000 } else {
1001 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001002 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
1003 l2cap_pi(sk)->psm = la.l2_psm;
1004 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001006
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001007 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
1008 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001009 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 }
1011
1012 write_unlock_bh(&l2cap_sk_list.lock);
1013
1014done:
1015 release_sock(sk);
1016 return err;
1017}
1018
1019static int l2cap_do_connect(struct sock *sk)
1020{
1021 bdaddr_t *src = &bt_sk(sk)->src;
1022 bdaddr_t *dst = &bt_sk(sk)->dst;
1023 struct l2cap_conn *conn;
1024 struct hci_conn *hcon;
1025 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001026 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001027 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001029 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
1030 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001032 hdev = hci_get_route(dst, src);
1033 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 return -EHOSTUNREACH;
1035
1036 hci_dev_lock_bh(hdev);
1037
1038 err = -ENOMEM;
1039
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001040 if (sk->sk_type == SOCK_RAW) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001041 switch (l2cap_pi(sk)->sec_level) {
1042 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001043 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001044 break;
1045 case BT_SECURITY_MEDIUM:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001046 auth_type = HCI_AT_DEDICATED_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001047 break;
1048 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001049 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001050 break;
1051 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001052 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001053 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001054 auth_type = HCI_AT_NO_BONDING_MITM;
1055 else
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001056 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann435fef22009-02-09 03:55:28 +01001057
1058 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
1059 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001060 } else {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001061 switch (l2cap_pi(sk)->sec_level) {
1062 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001063 auth_type = HCI_AT_GENERAL_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001064 break;
1065 case BT_SECURITY_MEDIUM:
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001066 auth_type = HCI_AT_GENERAL_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001067 break;
1068 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001069 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001070 break;
1071 }
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001072 }
1073
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001074 hcon = hci_connect(hdev, ACL_LINK, dst,
1075 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (!hcon)
1077 goto done;
1078
1079 conn = l2cap_conn_add(hcon, 0);
1080 if (!conn) {
1081 hci_conn_put(hcon);
1082 goto done;
1083 }
1084
1085 err = 0;
1086
1087 /* Update source addr of the socket */
1088 bacpy(src, conn->src);
1089
1090 l2cap_chan_add(conn, sk, NULL);
1091
1092 sk->sk_state = BT_CONNECT;
1093 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1094
1095 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001096 if (sk->sk_type != SOCK_SEQPACKET &&
1097 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 l2cap_sock_clear_timer(sk);
1099 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001100 } else
1101 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 }
1103
1104done:
1105 hci_dev_unlock_bh(hdev);
1106 hci_dev_put(hdev);
1107 return err;
1108}
1109
1110static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
1111{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001113 struct sockaddr_l2 la;
1114 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 BT_DBG("sk %p", sk);
1117
Changli Gao6503d962010-03-31 22:58:26 +00001118 if (!addr || alen < sizeof(addr->sa_family) ||
1119 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001120 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001122 memset(&la, 0, sizeof(la));
1123 len = min_t(unsigned int, sizeof(la), alen);
1124 memcpy(&la, addr, len);
1125
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001126 if (la.l2_cid)
1127 return -EINVAL;
1128
1129 lock_sock(sk);
1130
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001131 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
1132 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 err = -EINVAL;
1134 goto done;
1135 }
1136
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001137 switch (l2cap_pi(sk)->mode) {
1138 case L2CAP_MODE_BASIC:
1139 break;
1140 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001141 case L2CAP_MODE_STREAMING:
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001142 if (enable_ertm)
1143 break;
1144 /* fall through */
1145 default:
1146 err = -ENOTSUPP;
1147 goto done;
1148 }
1149
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001150 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 case BT_CONNECT:
1152 case BT_CONNECT2:
1153 case BT_CONFIG:
1154 /* Already connecting */
1155 goto wait;
1156
1157 case BT_CONNECTED:
1158 /* Already connected */
1159 goto done;
1160
1161 case BT_OPEN:
1162 case BT_BOUND:
1163 /* Can connect */
1164 break;
1165
1166 default:
1167 err = -EBADFD;
1168 goto done;
1169 }
1170
1171 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001172 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1173 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001175 err = l2cap_do_connect(sk);
1176 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 goto done;
1178
1179wait:
1180 err = bt_sock_wait_state(sk, BT_CONNECTED,
1181 sock_sndtimeo(sk, flags & O_NONBLOCK));
1182done:
1183 release_sock(sk);
1184 return err;
1185}
1186
1187static int l2cap_sock_listen(struct socket *sock, int backlog)
1188{
1189 struct sock *sk = sock->sk;
1190 int err = 0;
1191
1192 BT_DBG("sk %p backlog %d", sk, backlog);
1193
1194 lock_sock(sk);
1195
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001196 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1197 || sk->sk_state != BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 err = -EBADFD;
1199 goto done;
1200 }
1201
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001202 switch (l2cap_pi(sk)->mode) {
1203 case L2CAP_MODE_BASIC:
1204 break;
1205 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001206 case L2CAP_MODE_STREAMING:
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001207 if (enable_ertm)
1208 break;
1209 /* fall through */
1210 default:
1211 err = -ENOTSUPP;
1212 goto done;
1213 }
1214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (!l2cap_pi(sk)->psm) {
1216 bdaddr_t *src = &bt_sk(sk)->src;
1217 u16 psm;
1218
1219 err = -EINVAL;
1220
1221 write_lock_bh(&l2cap_sk_list.lock);
1222
1223 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001224 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1225 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1226 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 err = 0;
1228 break;
1229 }
1230
1231 write_unlock_bh(&l2cap_sk_list.lock);
1232
1233 if (err < 0)
1234 goto done;
1235 }
1236
1237 sk->sk_max_ack_backlog = backlog;
1238 sk->sk_ack_backlog = 0;
1239 sk->sk_state = BT_LISTEN;
1240
1241done:
1242 release_sock(sk);
1243 return err;
1244}
1245
1246static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
1247{
1248 DECLARE_WAITQUEUE(wait, current);
1249 struct sock *sk = sock->sk, *nsk;
1250 long timeo;
1251 int err = 0;
1252
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001253 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
1255 if (sk->sk_state != BT_LISTEN) {
1256 err = -EBADFD;
1257 goto done;
1258 }
1259
1260 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1261
1262 BT_DBG("sk %p timeo %ld", sk, timeo);
1263
1264 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001265 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1267 set_current_state(TASK_INTERRUPTIBLE);
1268 if (!timeo) {
1269 err = -EAGAIN;
1270 break;
1271 }
1272
1273 release_sock(sk);
1274 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001275 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 if (sk->sk_state != BT_LISTEN) {
1278 err = -EBADFD;
1279 break;
1280 }
1281
1282 if (signal_pending(current)) {
1283 err = sock_intr_errno(timeo);
1284 break;
1285 }
1286 }
1287 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001288 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
1290 if (err)
1291 goto done;
1292
1293 newsock->state = SS_CONNECTED;
1294
1295 BT_DBG("new socket %p", nsk);
1296
1297done:
1298 release_sock(sk);
1299 return err;
1300}
1301
1302static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
1303{
1304 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1305 struct sock *sk = sock->sk;
1306
1307 BT_DBG("sock %p, sk %p", sock, sk);
1308
1309 addr->sa_family = AF_BLUETOOTH;
1310 *len = sizeof(struct sockaddr_l2);
1311
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001312 if (peer) {
1313 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001315 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001316 } else {
1317 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001319 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 return 0;
1323}
1324
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001325static int __l2cap_wait_ack(struct sock *sk)
1326{
1327 DECLARE_WAITQUEUE(wait, current);
1328 int err = 0;
1329 int timeo = HZ/5;
1330
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001331 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001332 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
1333 set_current_state(TASK_INTERRUPTIBLE);
1334
1335 if (!timeo)
1336 timeo = HZ/5;
1337
1338 if (signal_pending(current)) {
1339 err = sock_intr_errno(timeo);
1340 break;
1341 }
1342
1343 release_sock(sk);
1344 timeo = schedule_timeout(timeo);
1345 lock_sock(sk);
1346
1347 err = sock_error(sk);
1348 if (err)
1349 break;
1350 }
1351 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001352 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001353 return err;
1354}
1355
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001356static void l2cap_monitor_timeout(unsigned long arg)
1357{
1358 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001359
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001360 BT_DBG("sk %p", sk);
1361
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001362 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001363 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001364 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001365 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001366 return;
1367 }
1368
1369 l2cap_pi(sk)->retry_count++;
1370 __mod_monitor_timer();
1371
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001372 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001373 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001374}
1375
1376static void l2cap_retrans_timeout(unsigned long arg)
1377{
1378 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001379
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001380 BT_DBG("sk %p", sk);
1381
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001382 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001383 l2cap_pi(sk)->retry_count = 1;
1384 __mod_monitor_timer();
1385
1386 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1387
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001388 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001389 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001390}
1391
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001392static void l2cap_drop_acked_frames(struct sock *sk)
1393{
1394 struct sk_buff *skb;
1395
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001396 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1397 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001398 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1399 break;
1400
1401 skb = skb_dequeue(TX_QUEUE(sk));
1402 kfree_skb(skb);
1403
1404 l2cap_pi(sk)->unacked_frames--;
1405 }
1406
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001407 if (!l2cap_pi(sk)->unacked_frames)
1408 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409}
1410
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001411static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001412{
1413 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001414
1415 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1416
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001417 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001418}
1419
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001420static int l2cap_streaming_send(struct sock *sk)
1421{
1422 struct sk_buff *skb, *tx_skb;
1423 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001424 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001425
1426 while ((skb = sk->sk_send_head)) {
1427 tx_skb = skb_clone(skb, GFP_ATOMIC);
1428
1429 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1430 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
1431 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1432
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001433 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001434 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1435 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1436 }
1437
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001438 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001439
1440 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1441
1442 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1443 sk->sk_send_head = NULL;
1444 else
1445 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
1446
1447 skb = skb_dequeue(TX_QUEUE(sk));
1448 kfree_skb(skb);
1449 }
1450 return 0;
1451}
1452
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001453static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001454{
1455 struct l2cap_pinfo *pi = l2cap_pi(sk);
1456 struct sk_buff *skb, *tx_skb;
1457 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001458
1459 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001460 if (!skb)
1461 return;
1462
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001463 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001464 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001465 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001466
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001467 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1468 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001469
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001470 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001471
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001472 if (pi->remote_max_tx &&
1473 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001474 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001475 return;
1476 }
1477
1478 tx_skb = skb_clone(skb, GFP_ATOMIC);
1479 bt_cb(skb)->retries++;
1480 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001481
1482 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1483 control |= L2CAP_CTRL_FINAL;
1484 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1485 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001486
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001487 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1488 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001489
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001490 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1491
1492 if (pi->fcs == L2CAP_FCS_CRC16) {
1493 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1494 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1495 }
1496
1497 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001498}
1499
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001500static int l2cap_ertm_send(struct sock *sk)
1501{
1502 struct sk_buff *skb, *tx_skb;
1503 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001504 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001505 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001506
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001507 if (sk->sk_state != BT_CONNECTED)
1508 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001509
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001510 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001511
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001512 if (pi->remote_max_tx &&
1513 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001514 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001515 break;
1516 }
1517
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001518 tx_skb = skb_clone(skb, GFP_ATOMIC);
1519
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001520 bt_cb(skb)->retries++;
1521
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001523 control &= L2CAP_CTRL_SAR;
1524
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001525 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1526 control |= L2CAP_CTRL_FINAL;
1527 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1528 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001529 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1531 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1532
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001533
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001534 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001535 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1536 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1537 }
1538
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001539 l2cap_do_send(sk, tx_skb);
1540
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001541 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001542
1543 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1544 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1545
1546 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001547 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548
1549 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1550 sk->sk_send_head = NULL;
1551 else
1552 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001553
1554 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001555 }
1556
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001557 return nsent;
1558}
1559
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001560static int l2cap_retransmit_frames(struct sock *sk)
1561{
1562 struct l2cap_pinfo *pi = l2cap_pi(sk);
1563 int ret;
1564
1565 spin_lock_bh(&pi->send_lock);
1566
1567 if (!skb_queue_empty(TX_QUEUE(sk)))
1568 sk->sk_send_head = TX_QUEUE(sk)->next;
1569
1570 pi->next_tx_seq = pi->expected_ack_seq;
1571 ret = l2cap_ertm_send(sk);
1572
1573 spin_unlock_bh(&pi->send_lock);
1574
1575 return ret;
1576}
1577
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001578static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001579{
1580 struct sock *sk = (struct sock *)pi;
1581 u16 control = 0;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001582 int nframes;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001583
1584 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1585
1586 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1587 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001588 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001589 l2cap_send_sframe(pi, control);
1590 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001591 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001592
1593 spin_lock_bh(&pi->send_lock);
1594 nframes = l2cap_ertm_send(sk);
1595 spin_unlock_bh(&pi->send_lock);
1596
1597 if (nframes > 0)
1598 return;
1599
1600 control |= L2CAP_SUPER_RCV_READY;
1601 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001602}
1603
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001604static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001605{
1606 struct srej_list *tail;
1607 u16 control;
1608
1609 control = L2CAP_SUPER_SELECT_REJECT;
1610 control |= L2CAP_CTRL_FINAL;
1611
1612 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1613 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1614
1615 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001616}
1617
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001618static 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 -07001619{
1620 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001621 struct sk_buff **frag;
1622 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001624 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001625 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
1627 sent += count;
1628 len -= count;
1629
1630 /* Continuation fragments (no L2CAP header) */
1631 frag = &skb_shinfo(skb)->frag_list;
1632 while (len) {
1633 count = min_t(unsigned int, conn->mtu, len);
1634
1635 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1636 if (!*frag)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001637 return -EFAULT;
1638 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1639 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641 sent += count;
1642 len -= count;
1643
1644 frag = &(*frag)->next;
1645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001648}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001650static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1651{
1652 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1653 struct sk_buff *skb;
1654 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1655 struct l2cap_hdr *lh;
1656
1657 BT_DBG("sk %p len %d", sk, (int)len);
1658
1659 count = min_t(unsigned int, (conn->mtu - hlen), len);
1660 skb = bt_skb_send_alloc(sk, count + hlen,
1661 msg->msg_flags & MSG_DONTWAIT, &err);
1662 if (!skb)
1663 return ERR_PTR(-ENOMEM);
1664
1665 /* Create L2CAP header */
1666 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1667 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1668 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1669 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1670
1671 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1672 if (unlikely(err < 0)) {
1673 kfree_skb(skb);
1674 return ERR_PTR(err);
1675 }
1676 return skb;
1677}
1678
1679static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1680{
1681 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1682 struct sk_buff *skb;
1683 int err, count, hlen = L2CAP_HDR_SIZE;
1684 struct l2cap_hdr *lh;
1685
1686 BT_DBG("sk %p len %d", sk, (int)len);
1687
1688 count = min_t(unsigned int, (conn->mtu - hlen), len);
1689 skb = bt_skb_send_alloc(sk, count + hlen,
1690 msg->msg_flags & MSG_DONTWAIT, &err);
1691 if (!skb)
1692 return ERR_PTR(-ENOMEM);
1693
1694 /* Create L2CAP header */
1695 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1696 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1697 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1698
1699 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1700 if (unlikely(err < 0)) {
1701 kfree_skb(skb);
1702 return ERR_PTR(err);
1703 }
1704 return skb;
1705}
1706
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001707static 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 -03001708{
1709 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1710 struct sk_buff *skb;
1711 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1712 struct l2cap_hdr *lh;
1713
1714 BT_DBG("sk %p len %d", sk, (int)len);
1715
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001716 if (!conn)
1717 return ERR_PTR(-ENOTCONN);
1718
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001719 if (sdulen)
1720 hlen += 2;
1721
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001722 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1723 hlen += 2;
1724
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001725 count = min_t(unsigned int, (conn->mtu - hlen), len);
1726 skb = bt_skb_send_alloc(sk, count + hlen,
1727 msg->msg_flags & MSG_DONTWAIT, &err);
1728 if (!skb)
1729 return ERR_PTR(-ENOMEM);
1730
1731 /* Create L2CAP header */
1732 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1733 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1734 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1735 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001736 if (sdulen)
1737 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001738
1739 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1740 if (unlikely(err < 0)) {
1741 kfree_skb(skb);
1742 return ERR_PTR(err);
1743 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001744
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001745 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1746 put_unaligned_le16(0, skb_put(skb, 2));
1747
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001748 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001749 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750}
1751
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001752static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1753{
1754 struct l2cap_pinfo *pi = l2cap_pi(sk);
1755 struct sk_buff *skb;
1756 struct sk_buff_head sar_queue;
1757 u16 control;
1758 size_t size = 0;
1759
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001760 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001761 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001762 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001763 if (IS_ERR(skb))
1764 return PTR_ERR(skb);
1765
1766 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001767 len -= pi->remote_mps;
1768 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001769
1770 while (len > 0) {
1771 size_t buflen;
1772
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001773 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001774 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001775 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001776 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001777 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001778 buflen = len;
1779 }
1780
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001781 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001782 if (IS_ERR(skb)) {
1783 skb_queue_purge(&sar_queue);
1784 return PTR_ERR(skb);
1785 }
1786
1787 __skb_queue_tail(&sar_queue, skb);
1788 len -= buflen;
1789 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001790 }
1791 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001792 spin_lock_bh(&pi->send_lock);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001793 if (sk->sk_send_head == NULL)
1794 sk->sk_send_head = sar_queue.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001795 spin_unlock_bh(&pi->send_lock);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001796
1797 return size;
1798}
1799
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
1801{
1802 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001803 struct l2cap_pinfo *pi = l2cap_pi(sk);
1804 struct sk_buff *skb;
1805 u16 control;
1806 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 BT_DBG("sock %p, sk %p", sock, sk);
1809
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001810 err = sock_error(sk);
1811 if (err)
1812 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
1814 if (msg->msg_flags & MSG_OOB)
1815 return -EOPNOTSUPP;
1816
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 lock_sock(sk);
1818
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001819 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001821 goto done;
1822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001824 /* Connectionless channel */
1825 if (sk->sk_type == SOCK_DGRAM) {
1826 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001827 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001828 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001829 } else {
1830 l2cap_do_send(sk, skb);
1831 err = len;
1832 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001833 goto done;
1834 }
1835
1836 switch (pi->mode) {
1837 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001838 /* Check outgoing MTU */
1839 if (len > pi->omtu) {
1840 err = -EINVAL;
1841 goto done;
1842 }
1843
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001844 /* Create a basic PDU */
1845 skb = l2cap_create_basic_pdu(sk, msg, len);
1846 if (IS_ERR(skb)) {
1847 err = PTR_ERR(skb);
1848 goto done;
1849 }
1850
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001851 l2cap_do_send(sk, skb);
1852 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001853 break;
1854
1855 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001856 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001857 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001858 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001859 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001860 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001861 if (IS_ERR(skb)) {
1862 err = PTR_ERR(skb);
1863 goto done;
1864 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001865 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001866
1867 if (pi->mode == L2CAP_MODE_ERTM)
1868 spin_lock_bh(&pi->send_lock);
1869
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001870 if (sk->sk_send_head == NULL)
1871 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001872
1873 if (pi->mode == L2CAP_MODE_ERTM)
1874 spin_unlock_bh(&pi->send_lock);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001875 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001876 /* Segment SDU into multiples PDUs */
1877 err = l2cap_sar_segment_sdu(sk, msg, len);
1878 if (err < 0)
1879 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001880 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001881
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001882 if (pi->mode == L2CAP_MODE_STREAMING) {
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001883 err = l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001884 } else {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001885 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
1886 pi->conn_state && L2CAP_CONN_WAIT_F) {
1887 err = len;
1888 break;
1889 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001890 spin_lock_bh(&pi->send_lock);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001891 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001892 spin_unlock_bh(&pi->send_lock);
1893 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001894
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001895 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001896 err = len;
1897 break;
1898
1899 default:
1900 BT_DBG("bad state %1.1x", pi->mode);
1901 err = -EINVAL;
1902 }
1903
1904done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 release_sock(sk);
1906 return err;
1907}
1908
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001909static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1910{
1911 struct sock *sk = sock->sk;
1912
1913 lock_sock(sk);
1914
1915 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1916 struct l2cap_conn_rsp rsp;
1917
1918 sk->sk_state = BT_CONFIG;
1919
1920 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1921 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1922 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1923 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1924 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1925 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1926
1927 release_sock(sk);
1928 return 0;
1929 }
1930
1931 release_sock(sk);
1932
1933 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1934}
1935
David S. Millerb7058842009-09-30 16:12:20 -07001936static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937{
1938 struct sock *sk = sock->sk;
1939 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001940 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 u32 opt;
1942
1943 BT_DBG("sk %p", sk);
1944
1945 lock_sock(sk);
1946
1947 switch (optname) {
1948 case L2CAP_OPTIONS:
Marcel Holtmann0878b662007-05-05 00:35:59 +02001949 opts.imtu = l2cap_pi(sk)->imtu;
1950 opts.omtu = l2cap_pi(sk)->omtu;
1951 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001952 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001953 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001954 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001955 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001956
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 len = min_t(unsigned int, sizeof(opts), optlen);
1958 if (copy_from_user((char *) &opts, optval, len)) {
1959 err = -EFAULT;
1960 break;
1961 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001962
Gustavo F. Padovan45d65c42010-06-07 19:21:30 -03001963 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
1964 err = -EINVAL;
1965 break;
1966 }
1967
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001968 l2cap_pi(sk)->mode = opts.mode;
1969 switch (l2cap_pi(sk)->mode) {
1970 case L2CAP_MODE_BASIC:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001971 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001972 break;
1973 case L2CAP_MODE_ERTM:
1974 case L2CAP_MODE_STREAMING:
1975 if (enable_ertm)
1976 break;
1977 /* fall through */
1978 default:
1979 err = -EINVAL;
1980 break;
1981 }
1982
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001983 l2cap_pi(sk)->imtu = opts.imtu;
1984 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001985 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001986 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001987 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 break;
1989
1990 case L2CAP_LM:
1991 if (get_user(opt, (u32 __user *) optval)) {
1992 err = -EFAULT;
1993 break;
1994 }
1995
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001996 if (opt & L2CAP_LM_AUTH)
1997 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
1998 if (opt & L2CAP_LM_ENCRYPT)
1999 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
2000 if (opt & L2CAP_LM_SECURE)
2001 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
2002
2003 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
2004 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 break;
2006
2007 default:
2008 err = -ENOPROTOOPT;
2009 break;
2010 }
2011
2012 release_sock(sk);
2013 return err;
2014}
2015
David S. Millerb7058842009-09-30 16:12:20 -07002016static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002017{
2018 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002019 struct bt_security sec;
2020 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002021 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002022
2023 BT_DBG("sk %p", sk);
2024
2025 if (level == SOL_L2CAP)
2026 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
2027
Marcel Holtmann0588d942009-01-16 10:06:13 +01002028 if (level != SOL_BLUETOOTH)
2029 return -ENOPROTOOPT;
2030
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002031 lock_sock(sk);
2032
2033 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002034 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002035 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2036 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002037 err = -EINVAL;
2038 break;
2039 }
2040
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002041 sec.level = BT_SECURITY_LOW;
2042
2043 len = min_t(unsigned int, sizeof(sec), optlen);
2044 if (copy_from_user((char *) &sec, optval, len)) {
2045 err = -EFAULT;
2046 break;
2047 }
2048
2049 if (sec.level < BT_SECURITY_LOW ||
2050 sec.level > BT_SECURITY_HIGH) {
2051 err = -EINVAL;
2052 break;
2053 }
2054
2055 l2cap_pi(sk)->sec_level = sec.level;
2056 break;
2057
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002058 case BT_DEFER_SETUP:
2059 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2060 err = -EINVAL;
2061 break;
2062 }
2063
2064 if (get_user(opt, (u32 __user *) optval)) {
2065 err = -EFAULT;
2066 break;
2067 }
2068
2069 bt_sk(sk)->defer_setup = opt;
2070 break;
2071
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002072 default:
2073 err = -ENOPROTOOPT;
2074 break;
2075 }
2076
2077 release_sock(sk);
2078 return err;
2079}
2080
2081static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082{
2083 struct sock *sk = sock->sk;
2084 struct l2cap_options opts;
2085 struct l2cap_conninfo cinfo;
2086 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002087 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
2089 BT_DBG("sk %p", sk);
2090
2091 if (get_user(len, optlen))
2092 return -EFAULT;
2093
2094 lock_sock(sk);
2095
2096 switch (optname) {
2097 case L2CAP_OPTIONS:
2098 opts.imtu = l2cap_pi(sk)->imtu;
2099 opts.omtu = l2cap_pi(sk)->omtu;
2100 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07002101 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002102 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002103 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002104 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
2106 len = min_t(unsigned int, len, sizeof(opts));
2107 if (copy_to_user(optval, (char *) &opts, len))
2108 err = -EFAULT;
2109
2110 break;
2111
2112 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002113 switch (l2cap_pi(sk)->sec_level) {
2114 case BT_SECURITY_LOW:
2115 opt = L2CAP_LM_AUTH;
2116 break;
2117 case BT_SECURITY_MEDIUM:
2118 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
2119 break;
2120 case BT_SECURITY_HIGH:
2121 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
2122 L2CAP_LM_SECURE;
2123 break;
2124 default:
2125 opt = 0;
2126 break;
2127 }
2128
2129 if (l2cap_pi(sk)->role_switch)
2130 opt |= L2CAP_LM_MASTER;
2131
2132 if (l2cap_pi(sk)->force_reliable)
2133 opt |= L2CAP_LM_RELIABLE;
2134
2135 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 err = -EFAULT;
2137 break;
2138
2139 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002140 if (sk->sk_state != BT_CONNECTED &&
2141 !(sk->sk_state == BT_CONNECT2 &&
2142 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 err = -ENOTCONN;
2144 break;
2145 }
2146
2147 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
2148 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
2149
2150 len = min_t(unsigned int, len, sizeof(cinfo));
2151 if (copy_to_user(optval, (char *) &cinfo, len))
2152 err = -EFAULT;
2153
2154 break;
2155
2156 default:
2157 err = -ENOPROTOOPT;
2158 break;
2159 }
2160
2161 release_sock(sk);
2162 return err;
2163}
2164
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002165static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
2166{
2167 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002168 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002169 int len, err = 0;
2170
2171 BT_DBG("sk %p", sk);
2172
2173 if (level == SOL_L2CAP)
2174 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
2175
Marcel Holtmann0588d942009-01-16 10:06:13 +01002176 if (level != SOL_BLUETOOTH)
2177 return -ENOPROTOOPT;
2178
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002179 if (get_user(len, optlen))
2180 return -EFAULT;
2181
2182 lock_sock(sk);
2183
2184 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002185 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002186 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2187 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002188 err = -EINVAL;
2189 break;
2190 }
2191
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002192 sec.level = l2cap_pi(sk)->sec_level;
2193
2194 len = min_t(unsigned int, len, sizeof(sec));
2195 if (copy_to_user(optval, (char *) &sec, len))
2196 err = -EFAULT;
2197
2198 break;
2199
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002200 case BT_DEFER_SETUP:
2201 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2202 err = -EINVAL;
2203 break;
2204 }
2205
2206 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
2207 err = -EFAULT;
2208
2209 break;
2210
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002211 default:
2212 err = -ENOPROTOOPT;
2213 break;
2214 }
2215
2216 release_sock(sk);
2217 return err;
2218}
2219
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220static int l2cap_sock_shutdown(struct socket *sock, int how)
2221{
2222 struct sock *sk = sock->sk;
2223 int err = 0;
2224
2225 BT_DBG("sock %p, sk %p", sock, sk);
2226
2227 if (!sk)
2228 return 0;
2229
2230 lock_sock(sk);
2231 if (!sk->sk_shutdown) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03002232 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2233 err = __l2cap_wait_ack(sk);
2234
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 sk->sk_shutdown = SHUTDOWN_MASK;
2236 l2cap_sock_clear_timer(sk);
2237 __l2cap_sock_close(sk, 0);
2238
2239 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002240 err = bt_sock_wait_state(sk, BT_CLOSED,
2241 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002243
2244 if (!err && sk->sk_err)
2245 err = -sk->sk_err;
2246
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 release_sock(sk);
2248 return err;
2249}
2250
2251static int l2cap_sock_release(struct socket *sock)
2252{
2253 struct sock *sk = sock->sk;
2254 int err;
2255
2256 BT_DBG("sock %p, sk %p", sock, sk);
2257
2258 if (!sk)
2259 return 0;
2260
2261 err = l2cap_sock_shutdown(sock, 2);
2262
2263 sock_orphan(sk);
2264 l2cap_sock_kill(sk);
2265 return err;
2266}
2267
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268static void l2cap_chan_ready(struct sock *sk)
2269{
2270 struct sock *parent = bt_sk(sk)->parent;
2271
2272 BT_DBG("sk %p, parent %p", sk, parent);
2273
2274 l2cap_pi(sk)->conf_state = 0;
2275 l2cap_sock_clear_timer(sk);
2276
2277 if (!parent) {
2278 /* Outgoing channel.
2279 * Wake up socket sleeping on connect.
2280 */
2281 sk->sk_state = BT_CONNECTED;
2282 sk->sk_state_change(sk);
2283 } else {
2284 /* Incoming channel.
2285 * Wake up socket sleeping on accept.
2286 */
2287 parent->sk_data_ready(parent, 0);
2288 }
2289}
2290
2291/* Copy frame to all raw sockets on that connection */
2292static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2293{
2294 struct l2cap_chan_list *l = &conn->chan_list;
2295 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002296 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297
2298 BT_DBG("conn %p", conn);
2299
2300 read_lock(&l->lock);
2301 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2302 if (sk->sk_type != SOCK_RAW)
2303 continue;
2304
2305 /* Don't send frame to the socket it came from */
2306 if (skb->sk == sk)
2307 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002308 nskb = skb_clone(skb, GFP_ATOMIC);
2309 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 continue;
2311
2312 if (sock_queue_rcv_skb(sk, nskb))
2313 kfree_skb(nskb);
2314 }
2315 read_unlock(&l->lock);
2316}
2317
2318/* ---- L2CAP signalling commands ---- */
2319static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2320 u8 code, u8 ident, u16 dlen, void *data)
2321{
2322 struct sk_buff *skb, **frag;
2323 struct l2cap_cmd_hdr *cmd;
2324 struct l2cap_hdr *lh;
2325 int len, count;
2326
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002327 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2328 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
2330 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2331 count = min_t(unsigned int, conn->mtu, len);
2332
2333 skb = bt_skb_alloc(count, GFP_ATOMIC);
2334 if (!skb)
2335 return NULL;
2336
2337 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002338 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002339 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
2341 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2342 cmd->code = code;
2343 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002344 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
2346 if (dlen) {
2347 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2348 memcpy(skb_put(skb, count), data, count);
2349 data += count;
2350 }
2351
2352 len -= skb->len;
2353
2354 /* Continuation fragments (no L2CAP header) */
2355 frag = &skb_shinfo(skb)->frag_list;
2356 while (len) {
2357 count = min_t(unsigned int, conn->mtu, len);
2358
2359 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2360 if (!*frag)
2361 goto fail;
2362
2363 memcpy(skb_put(*frag, count), data, count);
2364
2365 len -= count;
2366 data += count;
2367
2368 frag = &(*frag)->next;
2369 }
2370
2371 return skb;
2372
2373fail:
2374 kfree_skb(skb);
2375 return NULL;
2376}
2377
2378static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2379{
2380 struct l2cap_conf_opt *opt = *ptr;
2381 int len;
2382
2383 len = L2CAP_CONF_OPT_SIZE + opt->len;
2384 *ptr += len;
2385
2386 *type = opt->type;
2387 *olen = opt->len;
2388
2389 switch (opt->len) {
2390 case 1:
2391 *val = *((u8 *) opt->val);
2392 break;
2393
2394 case 2:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002395 *val = __le16_to_cpu(*((__le16 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 break;
2397
2398 case 4:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002399 *val = __le32_to_cpu(*((__le32 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 break;
2401
2402 default:
2403 *val = (unsigned long) opt->val;
2404 break;
2405 }
2406
2407 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2408 return len;
2409}
2410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2412{
2413 struct l2cap_conf_opt *opt = *ptr;
2414
2415 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2416
2417 opt->type = type;
2418 opt->len = len;
2419
2420 switch (len) {
2421 case 1:
2422 *((u8 *) opt->val) = val;
2423 break;
2424
2425 case 2:
Al Viro8e036fc2007-07-29 00:16:36 -07002426 *((__le16 *) opt->val) = cpu_to_le16(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 break;
2428
2429 case 4:
Al Viro8e036fc2007-07-29 00:16:36 -07002430 *((__le32 *) opt->val) = cpu_to_le32(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 break;
2432
2433 default:
2434 memcpy(opt->val, (void *) val, len);
2435 break;
2436 }
2437
2438 *ptr += L2CAP_CONF_OPT_SIZE + len;
2439}
2440
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002441static void l2cap_ack_timeout(unsigned long arg)
2442{
2443 struct sock *sk = (void *) arg;
2444
2445 bh_lock_sock(sk);
2446 l2cap_send_ack(l2cap_pi(sk));
2447 bh_unlock_sock(sk);
2448}
2449
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002450static inline void l2cap_ertm_init(struct sock *sk)
2451{
2452 l2cap_pi(sk)->expected_ack_seq = 0;
2453 l2cap_pi(sk)->unacked_frames = 0;
2454 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002455 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002456 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002457
2458 setup_timer(&l2cap_pi(sk)->retrans_timer,
2459 l2cap_retrans_timeout, (unsigned long) sk);
2460 setup_timer(&l2cap_pi(sk)->monitor_timer,
2461 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002462 setup_timer(&l2cap_pi(sk)->ack_timer,
2463 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002464
2465 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002466 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03002467 spin_lock_init(&l2cap_pi(sk)->send_lock);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002468
2469 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002470}
2471
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002472static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2473{
2474 switch (mode) {
2475 case L2CAP_MODE_STREAMING:
2476 case L2CAP_MODE_ERTM:
2477 if (l2cap_mode_supported(mode, remote_feat_mask))
2478 return mode;
2479 /* fall through */
2480 default:
2481 return L2CAP_MODE_BASIC;
2482 }
2483}
2484
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485static int l2cap_build_conf_req(struct sock *sk, void *data)
2486{
2487 struct l2cap_pinfo *pi = l2cap_pi(sk);
2488 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002489 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 void *ptr = req->data;
2491
2492 BT_DBG("sk %p", sk);
2493
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002494 if (pi->num_conf_req || pi->num_conf_rsp)
2495 goto done;
2496
2497 switch (pi->mode) {
2498 case L2CAP_MODE_STREAMING:
2499 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002500 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002501 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002502
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002503 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002504 default:
2505 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2506 break;
2507 }
2508
2509done:
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002510 switch (pi->mode) {
2511 case L2CAP_MODE_BASIC:
2512 if (pi->imtu != L2CAP_DEFAULT_MTU)
2513 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002514
2515 rfc.mode = L2CAP_MODE_BASIC;
2516 rfc.txwin_size = 0;
2517 rfc.max_transmit = 0;
2518 rfc.retrans_timeout = 0;
2519 rfc.monitor_timeout = 0;
2520 rfc.max_pdu_size = 0;
2521
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002522 break;
2523
2524 case L2CAP_MODE_ERTM:
2525 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002526 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002527 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002528 rfc.retrans_timeout = 0;
2529 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002530 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002531 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002532 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002533
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002534 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2535 break;
2536
2537 if (pi->fcs == L2CAP_FCS_NONE ||
2538 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2539 pi->fcs = L2CAP_FCS_NONE;
2540 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2541 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002542 break;
2543
2544 case L2CAP_MODE_STREAMING:
2545 rfc.mode = L2CAP_MODE_STREAMING;
2546 rfc.txwin_size = 0;
2547 rfc.max_transmit = 0;
2548 rfc.retrans_timeout = 0;
2549 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002550 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002551 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002552 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002553
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002554 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2555 break;
2556
2557 if (pi->fcs == L2CAP_FCS_NONE ||
2558 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2559 pi->fcs = L2CAP_FCS_NONE;
2560 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2561 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002562 break;
2563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002565 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2566 (unsigned long) &rfc);
2567
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 /* FIXME: Need actual value of the flush timeout */
2569 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2570 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2571
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002572 req->dcid = cpu_to_le16(pi->dcid);
2573 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
2575 return ptr - data;
2576}
2577
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002578static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579{
2580 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002581 struct l2cap_conf_rsp *rsp = data;
2582 void *ptr = rsp->data;
2583 void *req = pi->conf_req;
2584 int len = pi->conf_len;
2585 int type, hint, olen;
2586 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002587 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002588 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002589 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002591 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002592
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002593 while (len >= L2CAP_CONF_OPT_SIZE) {
2594 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002596 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002597 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002598
2599 switch (type) {
2600 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002601 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002602 break;
2603
2604 case L2CAP_CONF_FLUSH_TO:
2605 pi->flush_to = val;
2606 break;
2607
2608 case L2CAP_CONF_QOS:
2609 break;
2610
Marcel Holtmann6464f352007-10-20 13:39:51 +02002611 case L2CAP_CONF_RFC:
2612 if (olen == sizeof(rfc))
2613 memcpy(&rfc, (void *) val, olen);
2614 break;
2615
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002616 case L2CAP_CONF_FCS:
2617 if (val == L2CAP_FCS_NONE)
2618 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2619
2620 break;
2621
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002622 default:
2623 if (hint)
2624 break;
2625
2626 result = L2CAP_CONF_UNKNOWN;
2627 *((u8 *) ptr++) = type;
2628 break;
2629 }
2630 }
2631
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002632 if (pi->num_conf_rsp || pi->num_conf_req)
2633 goto done;
2634
2635 switch (pi->mode) {
2636 case L2CAP_MODE_STREAMING:
2637 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002638 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
2639 pi->mode = l2cap_select_mode(rfc.mode,
2640 pi->conn->feat_mask);
2641 break;
2642 }
2643
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002644 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002645 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002646
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002648 }
2649
2650done:
2651 if (pi->mode != rfc.mode) {
2652 result = L2CAP_CONF_UNACCEPT;
2653 rfc.mode = pi->mode;
2654
2655 if (pi->num_conf_rsp == 1)
2656 return -ECONNREFUSED;
2657
2658 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2659 sizeof(rfc), (unsigned long) &rfc);
2660 }
2661
2662
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002663 if (result == L2CAP_CONF_SUCCESS) {
2664 /* Configure output options and let the other side know
2665 * which ones we don't like. */
2666
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002667 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2668 result = L2CAP_CONF_UNACCEPT;
2669 else {
2670 pi->omtu = mtu;
2671 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2672 }
2673 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002674
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002675 switch (rfc.mode) {
2676 case L2CAP_MODE_BASIC:
2677 pi->fcs = L2CAP_FCS_NONE;
2678 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2679 break;
2680
2681 case L2CAP_MODE_ERTM:
2682 pi->remote_tx_win = rfc.txwin_size;
2683 pi->remote_max_tx = rfc.max_transmit;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002684 if (rfc.max_pdu_size > pi->conn->mtu - 10)
2685 rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
2686
2687 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002688
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002689 rfc.retrans_timeout =
2690 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2691 rfc.monitor_timeout =
2692 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002693
2694 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002695
2696 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2697 sizeof(rfc), (unsigned long) &rfc);
2698
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002699 break;
2700
2701 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002702 if (rfc.max_pdu_size > pi->conn->mtu - 10)
2703 rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
2704
2705 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002706
2707 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002708
2709 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2710 sizeof(rfc), (unsigned long) &rfc);
2711
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002712 break;
2713
2714 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002715 result = L2CAP_CONF_UNACCEPT;
2716
2717 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002718 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002719 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002720
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002721 if (result == L2CAP_CONF_SUCCESS)
2722 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2723 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002724 rsp->scid = cpu_to_le16(pi->dcid);
2725 rsp->result = cpu_to_le16(result);
2726 rsp->flags = cpu_to_le16(0x0000);
2727
2728 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729}
2730
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002731static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2732{
2733 struct l2cap_pinfo *pi = l2cap_pi(sk);
2734 struct l2cap_conf_req *req = data;
2735 void *ptr = req->data;
2736 int type, olen;
2737 unsigned long val;
2738 struct l2cap_conf_rfc rfc;
2739
2740 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2741
2742 while (len >= L2CAP_CONF_OPT_SIZE) {
2743 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2744
2745 switch (type) {
2746 case L2CAP_CONF_MTU:
2747 if (val < L2CAP_DEFAULT_MIN_MTU) {
2748 *result = L2CAP_CONF_UNACCEPT;
2749 pi->omtu = L2CAP_DEFAULT_MIN_MTU;
2750 } else
2751 pi->omtu = val;
2752 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
2753 break;
2754
2755 case L2CAP_CONF_FLUSH_TO:
2756 pi->flush_to = val;
2757 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2758 2, pi->flush_to);
2759 break;
2760
2761 case L2CAP_CONF_RFC:
2762 if (olen == sizeof(rfc))
2763 memcpy(&rfc, (void *)val, olen);
2764
2765 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2766 rfc.mode != pi->mode)
2767 return -ECONNREFUSED;
2768
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002769 pi->fcs = 0;
2770
2771 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2772 sizeof(rfc), (unsigned long) &rfc);
2773 break;
2774 }
2775 }
2776
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002777 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
2778 return -ECONNREFUSED;
2779
2780 pi->mode = rfc.mode;
2781
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002782 if (*result == L2CAP_CONF_SUCCESS) {
2783 switch (rfc.mode) {
2784 case L2CAP_MODE_ERTM:
2785 pi->remote_tx_win = rfc.txwin_size;
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002786 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2787 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002788 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002789 break;
2790 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002791 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002792 }
2793 }
2794
2795 req->dcid = cpu_to_le16(pi->dcid);
2796 req->flags = cpu_to_le16(0x0000);
2797
2798 return ptr - data;
2799}
2800
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002801static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802{
2803 struct l2cap_conf_rsp *rsp = data;
2804 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002806 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002808 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002809 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002810 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811
2812 return ptr - data;
2813}
2814
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002815static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2816{
2817 struct l2cap_pinfo *pi = l2cap_pi(sk);
2818 int type, olen;
2819 unsigned long val;
2820 struct l2cap_conf_rfc rfc;
2821
2822 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2823
2824 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2825 return;
2826
2827 while (len >= L2CAP_CONF_OPT_SIZE) {
2828 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2829
2830 switch (type) {
2831 case L2CAP_CONF_RFC:
2832 if (olen == sizeof(rfc))
2833 memcpy(&rfc, (void *)val, olen);
2834 goto done;
2835 }
2836 }
2837
2838done:
2839 switch (rfc.mode) {
2840 case L2CAP_MODE_ERTM:
2841 pi->remote_tx_win = rfc.txwin_size;
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002842 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2843 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002844 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2845 break;
2846 case L2CAP_MODE_STREAMING:
2847 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2848 }
2849}
2850
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002851static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2852{
2853 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2854
2855 if (rej->reason != 0x0000)
2856 return 0;
2857
2858 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2859 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002860 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002861
2862 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002863 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002864
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002865 l2cap_conn_start(conn);
2866 }
2867
2868 return 0;
2869}
2870
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2872{
2873 struct l2cap_chan_list *list = &conn->chan_list;
2874 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2875 struct l2cap_conn_rsp rsp;
2876 struct sock *sk, *parent;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002877 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878
2879 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002880 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
2882 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2883
2884 /* Check if we have socket listening on psm */
2885 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2886 if (!parent) {
2887 result = L2CAP_CR_BAD_PSM;
2888 goto sendresp;
2889 }
2890
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002891 /* Check if the ACL is secure enough (if not SDP) */
2892 if (psm != cpu_to_le16(0x0001) &&
2893 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002894 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002895 result = L2CAP_CR_SEC_BLOCK;
2896 goto response;
2897 }
2898
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 result = L2CAP_CR_NO_MEM;
2900
2901 /* Check for backlog size */
2902 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002903 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 goto response;
2905 }
2906
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002907 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 if (!sk)
2909 goto response;
2910
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002911 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912
2913 /* Check if we already have channel with that dcid */
2914 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002915 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 sock_set_flag(sk, SOCK_ZAPPED);
2917 l2cap_sock_kill(sk);
2918 goto response;
2919 }
2920
2921 hci_conn_hold(conn->hcon);
2922
2923 l2cap_sock_init(sk, parent);
2924 bacpy(&bt_sk(sk)->src, conn->src);
2925 bacpy(&bt_sk(sk)->dst, conn->dst);
2926 l2cap_pi(sk)->psm = psm;
2927 l2cap_pi(sk)->dcid = scid;
2928
2929 __l2cap_chan_add(conn, sk, parent);
2930 dcid = l2cap_pi(sk)->scid;
2931
2932 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2933
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 l2cap_pi(sk)->ident = cmd->ident;
2935
Marcel Holtmann984947d2009-02-06 23:35:19 +01002936 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002937 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002938 if (bt_sk(sk)->defer_setup) {
2939 sk->sk_state = BT_CONNECT2;
2940 result = L2CAP_CR_PEND;
2941 status = L2CAP_CS_AUTHOR_PEND;
2942 parent->sk_data_ready(parent, 0);
2943 } else {
2944 sk->sk_state = BT_CONFIG;
2945 result = L2CAP_CR_SUCCESS;
2946 status = L2CAP_CS_NO_INFO;
2947 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002948 } else {
2949 sk->sk_state = BT_CONNECT2;
2950 result = L2CAP_CR_PEND;
2951 status = L2CAP_CS_AUTHEN_PEND;
2952 }
2953 } else {
2954 sk->sk_state = BT_CONNECT2;
2955 result = L2CAP_CR_PEND;
2956 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 }
2958
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002959 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
2961response:
2962 bh_unlock_sock(parent);
2963
2964sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002965 rsp.scid = cpu_to_le16(scid);
2966 rsp.dcid = cpu_to_le16(dcid);
2967 rsp.result = cpu_to_le16(result);
2968 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002970
2971 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2972 struct l2cap_info_req info;
2973 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2974
2975 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2976 conn->info_ident = l2cap_get_ident(conn);
2977
2978 mod_timer(&conn->info_timer, jiffies +
2979 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2980
2981 l2cap_send_cmd(conn, conn->info_ident,
2982 L2CAP_INFO_REQ, sizeof(info), &info);
2983 }
2984
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 return 0;
2986}
2987
2988static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2989{
2990 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2991 u16 scid, dcid, result, status;
2992 struct sock *sk;
2993 u8 req[128];
2994
2995 scid = __le16_to_cpu(rsp->scid);
2996 dcid = __le16_to_cpu(rsp->dcid);
2997 result = __le16_to_cpu(rsp->result);
2998 status = __le16_to_cpu(rsp->status);
2999
3000 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
3001
3002 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003003 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3004 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 return 0;
3006 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003007 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
3008 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 return 0;
3010 }
3011
3012 switch (result) {
3013 case L2CAP_CR_SUCCESS:
3014 sk->sk_state = BT_CONFIG;
3015 l2cap_pi(sk)->ident = 0;
3016 l2cap_pi(sk)->dcid = dcid;
3017 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003018 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
3019
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3021 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003022 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 break;
3024
3025 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003026 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 break;
3028
3029 default:
3030 l2cap_chan_del(sk, ECONNREFUSED);
3031 break;
3032 }
3033
3034 bh_unlock_sock(sk);
3035 return 0;
3036}
3037
Al Viro88219a02007-07-29 00:17:25 -07003038static 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 -07003039{
3040 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3041 u16 dcid, flags;
3042 u8 rsp[64];
3043 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003044 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
3046 dcid = __le16_to_cpu(req->dcid);
3047 flags = __le16_to_cpu(req->flags);
3048
3049 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3050
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003051 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3052 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 return -ENOENT;
3054
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003055 if (sk->sk_state == BT_DISCONN)
3056 goto unlock;
3057
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003058 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003059 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003060 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
3061 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3062 l2cap_build_conf_rsp(sk, rsp,
3063 L2CAP_CONF_REJECT, flags), rsp);
3064 goto unlock;
3065 }
3066
3067 /* Store config. */
3068 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
3069 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
3071 if (flags & 0x0001) {
3072 /* Incomplete config. Send empty response. */
3073 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003074 l2cap_build_conf_rsp(sk, rsp,
3075 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 goto unlock;
3077 }
3078
3079 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003080 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003081 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003082 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003086 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003087 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003088
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003089 /* Reset config buffer. */
3090 l2cap_pi(sk)->conf_len = 0;
3091
Marcel Holtmann876d9482007-10-20 13:35:42 +02003092 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
3093 goto unlock;
3094
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Joe Perchesf64f9e72009-11-29 16:55:45 -08003096 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
3097 l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003098 l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
3099
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003101
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003102 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003103 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003104 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003105 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3106 l2cap_ertm_init(sk);
3107
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02003109 goto unlock;
3110 }
3111
3112 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003113 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003115 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003116 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 }
3118
3119unlock:
3120 bh_unlock_sock(sk);
3121 return 0;
3122}
3123
3124static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3125{
3126 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3127 u16 scid, flags, result;
3128 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003129 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
3131 scid = __le16_to_cpu(rsp->scid);
3132 flags = __le16_to_cpu(rsp->flags);
3133 result = __le16_to_cpu(rsp->result);
3134
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003135 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
3136 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003138 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3139 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 return 0;
3141
3142 switch (result) {
3143 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003144 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 break;
3146
3147 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003148 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003149 char req[64];
3150
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003151 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003152 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003153 goto done;
3154 }
3155
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003156 /* throw out any old stored conf requests */
3157 result = L2CAP_CONF_SUCCESS;
3158 len = l2cap_parse_conf_rsp(sk, rsp->data,
3159 len, req, &result);
3160 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003161 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003162 goto done;
3163 }
3164
3165 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3166 L2CAP_CONF_REQ, len, req);
3167 l2cap_pi(sk)->num_conf_req++;
3168 if (result != L2CAP_CONF_SUCCESS)
3169 goto done;
3170 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 }
3172
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003173 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003174 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003176 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 goto done;
3178 }
3179
3180 if (flags & 0x01)
3181 goto done;
3182
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3184
3185 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Joe Perchesf64f9e72009-11-29 16:55:45 -08003186 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
3187 l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003188 l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
3189
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003191 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003192 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003193 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003194 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3195 l2cap_ertm_init(sk);
3196
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 l2cap_chan_ready(sk);
3198 }
3199
3200done:
3201 bh_unlock_sock(sk);
3202 return 0;
3203}
3204
3205static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3206{
3207 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3208 struct l2cap_disconn_rsp rsp;
3209 u16 dcid, scid;
3210 struct sock *sk;
3211
3212 scid = __le16_to_cpu(req->scid);
3213 dcid = __le16_to_cpu(req->dcid);
3214
3215 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3216
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003217 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3218 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 return 0;
3220
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003221 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3222 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3224
3225 sk->sk_shutdown = SHUTDOWN_MASK;
3226
3227 l2cap_chan_del(sk, ECONNRESET);
3228 bh_unlock_sock(sk);
3229
3230 l2cap_sock_kill(sk);
3231 return 0;
3232}
3233
3234static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3235{
3236 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3237 u16 dcid, scid;
3238 struct sock *sk;
3239
3240 scid = __le16_to_cpu(rsp->scid);
3241 dcid = __le16_to_cpu(rsp->dcid);
3242
3243 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3244
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003245 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3246 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247 return 0;
3248
3249 l2cap_chan_del(sk, 0);
3250 bh_unlock_sock(sk);
3251
3252 l2cap_sock_kill(sk);
3253 return 0;
3254}
3255
3256static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3257{
3258 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 u16 type;
3260
3261 type = __le16_to_cpu(req->type);
3262
3263 BT_DBG("type 0x%4.4x", type);
3264
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003265 if (type == L2CAP_IT_FEAT_MASK) {
3266 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003267 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003268 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3269 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3270 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003271 if (enable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003272 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3273 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003274 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003275 l2cap_send_cmd(conn, cmd->ident,
3276 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003277 } else if (type == L2CAP_IT_FIXED_CHAN) {
3278 u8 buf[12];
3279 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3280 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3281 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3282 memcpy(buf + 4, l2cap_fixed_chan, 8);
3283 l2cap_send_cmd(conn, cmd->ident,
3284 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003285 } else {
3286 struct l2cap_info_rsp rsp;
3287 rsp.type = cpu_to_le16(type);
3288 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3289 l2cap_send_cmd(conn, cmd->ident,
3290 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292
3293 return 0;
3294}
3295
3296static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3297{
3298 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3299 u16 type, result;
3300
3301 type = __le16_to_cpu(rsp->type);
3302 result = __le16_to_cpu(rsp->result);
3303
3304 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3305
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003306 del_timer(&conn->info_timer);
3307
Marcel Holtmann984947d2009-02-06 23:35:19 +01003308 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003309 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003310
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003311 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003312 struct l2cap_info_req req;
3313 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3314
3315 conn->info_ident = l2cap_get_ident(conn);
3316
3317 l2cap_send_cmd(conn, conn->info_ident,
3318 L2CAP_INFO_REQ, sizeof(req), &req);
3319 } else {
3320 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3321 conn->info_ident = 0;
3322
3323 l2cap_conn_start(conn);
3324 }
3325 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003326 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003327 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003328
3329 l2cap_conn_start(conn);
3330 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003331
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 return 0;
3333}
3334
3335static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3336{
3337 u8 *data = skb->data;
3338 int len = skb->len;
3339 struct l2cap_cmd_hdr cmd;
3340 int err = 0;
3341
3342 l2cap_raw_recv(conn, skb);
3343
3344 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003345 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3347 data += L2CAP_CMD_HDR_SIZE;
3348 len -= L2CAP_CMD_HDR_SIZE;
3349
Al Viro88219a02007-07-29 00:17:25 -07003350 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351
Al Viro88219a02007-07-29 00:17:25 -07003352 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 -07003353
Al Viro88219a02007-07-29 00:17:25 -07003354 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 BT_DBG("corrupted command");
3356 break;
3357 }
3358
3359 switch (cmd.code) {
3360 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003361 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 break;
3363
3364 case L2CAP_CONN_REQ:
3365 err = l2cap_connect_req(conn, &cmd, data);
3366 break;
3367
3368 case L2CAP_CONN_RSP:
3369 err = l2cap_connect_rsp(conn, &cmd, data);
3370 break;
3371
3372 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003373 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 break;
3375
3376 case L2CAP_CONF_RSP:
3377 err = l2cap_config_rsp(conn, &cmd, data);
3378 break;
3379
3380 case L2CAP_DISCONN_REQ:
3381 err = l2cap_disconnect_req(conn, &cmd, data);
3382 break;
3383
3384 case L2CAP_DISCONN_RSP:
3385 err = l2cap_disconnect_rsp(conn, &cmd, data);
3386 break;
3387
3388 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003389 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 break;
3391
3392 case L2CAP_ECHO_RSP:
3393 break;
3394
3395 case L2CAP_INFO_REQ:
3396 err = l2cap_information_req(conn, &cmd, data);
3397 break;
3398
3399 case L2CAP_INFO_RSP:
3400 err = l2cap_information_rsp(conn, &cmd, data);
3401 break;
3402
3403 default:
3404 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3405 err = -EINVAL;
3406 break;
3407 }
3408
3409 if (err) {
3410 struct l2cap_cmd_rej rej;
3411 BT_DBG("error %d", err);
3412
3413 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003414 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3416 }
3417
Al Viro88219a02007-07-29 00:17:25 -07003418 data += cmd_len;
3419 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 }
3421
3422 kfree_skb(skb);
3423}
3424
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003425static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3426{
3427 u16 our_fcs, rcv_fcs;
3428 int hdr_size = L2CAP_HDR_SIZE + 2;
3429
3430 if (pi->fcs == L2CAP_FCS_CRC16) {
3431 skb_trim(skb, skb->len - 2);
3432 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3433 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3434
3435 if (our_fcs != rcv_fcs)
3436 return -EINVAL;
3437 }
3438 return 0;
3439}
3440
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003441static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3442{
3443 struct l2cap_pinfo *pi = l2cap_pi(sk);
3444 u16 control = 0;
3445
3446 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003447
3448 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3449
3450 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003451 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003452 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003453 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003454 }
3455
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003456 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3457 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003458
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003459 spin_lock_bh(&pi->send_lock);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003460 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003461 spin_unlock_bh(&pi->send_lock);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003462
3463 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3464 pi->frames_sent == 0) {
3465 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003466 l2cap_send_sframe(pi, control);
3467 }
3468}
3469
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003470static 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 -03003471{
3472 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003473 struct l2cap_pinfo *pi = l2cap_pi(sk);
3474 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003475
3476 bt_cb(skb)->tx_seq = tx_seq;
3477 bt_cb(skb)->sar = sar;
3478
3479 next_skb = skb_peek(SREJ_QUEUE(sk));
3480 if (!next_skb) {
3481 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003482 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003483 }
3484
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003485 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3486 if (tx_seq_offset < 0)
3487 tx_seq_offset += 64;
3488
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003490 if (bt_cb(next_skb)->tx_seq == tx_seq)
3491 return -EINVAL;
3492
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003493 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3494 pi->buffer_seq) % 64;
3495 if (next_tx_seq_offset < 0)
3496 next_tx_seq_offset += 64;
3497
3498 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003499 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003500 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003501 }
3502
3503 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3504 break;
3505
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003506 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003507
3508 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003509
3510 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003511}
3512
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003513static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3514{
3515 struct l2cap_pinfo *pi = l2cap_pi(sk);
3516 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003517 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003518
3519 switch (control & L2CAP_CTRL_SAR) {
3520 case L2CAP_SDU_UNSEGMENTED:
3521 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3522 goto drop;
3523
3524 err = sock_queue_rcv_skb(sk, skb);
3525 if (!err)
3526 return err;
3527
3528 break;
3529
3530 case L2CAP_SDU_START:
3531 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3532 goto drop;
3533
3534 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003535
3536 if (pi->sdu_len > pi->imtu)
3537 goto disconnect;
3538
3539 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003540 if (!pi->sdu)
3541 return -ENOMEM;
3542
3543 /* pull sdu_len bytes only after alloc, because of Local Busy
3544 * condition we have to be sure that this will be executed
3545 * only once, i.e., when alloc does not fail */
3546 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003547
3548 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3549
3550 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3551 pi->partial_sdu_len = skb->len;
3552 break;
3553
3554 case L2CAP_SDU_CONTINUE:
3555 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3556 goto disconnect;
3557
3558 if (!pi->sdu)
3559 goto disconnect;
3560
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003561 pi->partial_sdu_len += skb->len;
3562 if (pi->partial_sdu_len > pi->sdu_len)
3563 goto drop;
3564
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003565 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3566
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003567 break;
3568
3569 case L2CAP_SDU_END:
3570 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3571 goto disconnect;
3572
3573 if (!pi->sdu)
3574 goto disconnect;
3575
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003576 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003577 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003578
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003579 if (pi->partial_sdu_len > pi->imtu)
3580 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003581
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003582 if (pi->partial_sdu_len != pi->sdu_len)
3583 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003584
3585 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003586 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003587
3588 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003589 if (!_skb) {
3590 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3591 return -ENOMEM;
3592 }
3593
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003594 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003595 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003596 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003597 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3598 return err;
3599 }
3600
3601 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3602 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003603
3604 kfree_skb(pi->sdu);
3605 break;
3606 }
3607
3608 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003609 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003610
3611drop:
3612 kfree_skb(pi->sdu);
3613 pi->sdu = NULL;
3614
3615disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003616 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003617 kfree_skb(skb);
3618 return 0;
3619}
3620
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003621static void l2cap_busy_work(struct work_struct *work)
3622{
3623 DECLARE_WAITQUEUE(wait, current);
3624 struct l2cap_pinfo *pi =
3625 container_of(work, struct l2cap_pinfo, busy_work);
3626 struct sock *sk = (struct sock *)pi;
3627 int n_tries = 0, timeo = HZ/5, err;
3628 struct sk_buff *skb;
3629 u16 control;
3630
3631 lock_sock(sk);
3632
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003633 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003634 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3635 set_current_state(TASK_INTERRUPTIBLE);
3636
3637 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3638 err = -EBUSY;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003639 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003640 goto done;
3641 }
3642
3643 if (!timeo)
3644 timeo = HZ/5;
3645
3646 if (signal_pending(current)) {
3647 err = sock_intr_errno(timeo);
3648 goto done;
3649 }
3650
3651 release_sock(sk);
3652 timeo = schedule_timeout(timeo);
3653 lock_sock(sk);
3654
3655 err = sock_error(sk);
3656 if (err)
3657 goto done;
3658
3659 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3660 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3661 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3662 if (err < 0) {
3663 skb_queue_head(BUSY_QUEUE(sk), skb);
3664 break;
3665 }
3666
3667 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3668 }
3669
3670 if (!skb)
3671 break;
3672 }
3673
3674 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3675 goto done;
3676
3677 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3678 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3679 l2cap_send_sframe(pi, control);
3680 l2cap_pi(sk)->retry_count = 1;
3681
3682 del_timer(&pi->retrans_timer);
3683 __mod_monitor_timer();
3684
3685 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3686
3687done:
3688 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3689 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3690
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003691 BT_DBG("sk %p, Exit local busy", sk);
3692
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003693 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003694 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003695
3696 release_sock(sk);
3697}
3698
3699static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3700{
3701 struct l2cap_pinfo *pi = l2cap_pi(sk);
3702 int sctrl, err;
3703
3704 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3705 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3706 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3707 return -EBUSY;
3708 }
3709
3710 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3711 if (err >= 0) {
3712 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3713 return err;
3714 }
3715
3716 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003717 BT_DBG("sk %p, Enter local busy", sk);
3718
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003719 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3720 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3721 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3722
3723 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3724 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3725 l2cap_send_sframe(pi, sctrl);
3726
3727 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3728
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003729 del_timer(&pi->ack_timer);
3730
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003731 queue_work(_busy_wq, &pi->busy_work);
3732
3733 return err;
3734}
3735
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003736static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003737{
3738 struct l2cap_pinfo *pi = l2cap_pi(sk);
3739 struct sk_buff *_skb;
3740 int err = -EINVAL;
3741
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003742 /*
3743 * TODO: We have to notify the userland if some data is lost with the
3744 * Streaming Mode.
3745 */
3746
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003747 switch (control & L2CAP_CTRL_SAR) {
3748 case L2CAP_SDU_UNSEGMENTED:
3749 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3750 kfree_skb(pi->sdu);
3751 break;
3752 }
3753
3754 err = sock_queue_rcv_skb(sk, skb);
3755 if (!err)
3756 return 0;
3757
3758 break;
3759
3760 case L2CAP_SDU_START:
3761 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3762 kfree_skb(pi->sdu);
3763 break;
3764 }
3765
3766 pi->sdu_len = get_unaligned_le16(skb->data);
3767 skb_pull(skb, 2);
3768
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003769 if (pi->sdu_len > pi->imtu) {
3770 err = -EMSGSIZE;
3771 break;
3772 }
3773
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003774 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3775 if (!pi->sdu) {
3776 err = -ENOMEM;
3777 break;
3778 }
3779
3780 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3781
3782 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3783 pi->partial_sdu_len = skb->len;
3784 err = 0;
3785 break;
3786
3787 case L2CAP_SDU_CONTINUE:
3788 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3789 break;
3790
3791 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3792
3793 pi->partial_sdu_len += skb->len;
3794 if (pi->partial_sdu_len > pi->sdu_len)
3795 kfree_skb(pi->sdu);
3796 else
3797 err = 0;
3798
3799 break;
3800
3801 case L2CAP_SDU_END:
3802 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3803 break;
3804
3805 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3806
3807 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3808 pi->partial_sdu_len += skb->len;
3809
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003810 if (pi->partial_sdu_len > pi->imtu)
3811 goto drop;
3812
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003813 if (pi->partial_sdu_len == pi->sdu_len) {
3814 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3815 err = sock_queue_rcv_skb(sk, _skb);
3816 if (err < 0)
3817 kfree_skb(_skb);
3818 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003819 err = 0;
3820
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003821drop:
3822 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003823 break;
3824 }
3825
3826 kfree_skb(skb);
3827 return err;
3828}
3829
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003830static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3831{
3832 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003833 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003834
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003835 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003836 if (bt_cb(skb)->tx_seq != tx_seq)
3837 break;
3838
3839 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003840 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003841 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003842 l2cap_pi(sk)->buffer_seq_srej =
3843 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003844 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003845 }
3846}
3847
3848static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3849{
3850 struct l2cap_pinfo *pi = l2cap_pi(sk);
3851 struct srej_list *l, *tmp;
3852 u16 control;
3853
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003854 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003855 if (l->tx_seq == tx_seq) {
3856 list_del(&l->list);
3857 kfree(l);
3858 return;
3859 }
3860 control = L2CAP_SUPER_SELECT_REJECT;
3861 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3862 l2cap_send_sframe(pi, control);
3863 list_del(&l->list);
3864 list_add_tail(&l->list, SREJ_LIST(sk));
3865 }
3866}
3867
3868static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3869{
3870 struct l2cap_pinfo *pi = l2cap_pi(sk);
3871 struct srej_list *new;
3872 u16 control;
3873
3874 while (tx_seq != pi->expected_tx_seq) {
3875 control = L2CAP_SUPER_SELECT_REJECT;
3876 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3877 l2cap_send_sframe(pi, control);
3878
3879 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003880 new->tx_seq = pi->expected_tx_seq;
3881 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003882 list_add_tail(&new->list, SREJ_LIST(sk));
3883 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003884 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003885}
3886
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003887static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3888{
3889 struct l2cap_pinfo *pi = l2cap_pi(sk);
3890 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003891 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003892 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003893 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003894 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003895 int err = 0;
3896
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003897 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3898 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003899
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003900 if (L2CAP_CTRL_FINAL & rx_control &&
3901 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003902 del_timer(&pi->monitor_timer);
3903 if (pi->unacked_frames > 0)
3904 __mod_retrans_timer();
3905 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3906 }
3907
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003908 pi->expected_ack_seq = req_seq;
3909 l2cap_drop_acked_frames(sk);
3910
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003911 if (tx_seq == pi->expected_tx_seq)
3912 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003913
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003914 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3915 if (tx_seq_offset < 0)
3916 tx_seq_offset += 64;
3917
3918 /* invalid tx_seq */
3919 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003920 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003921 goto drop;
3922 }
3923
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003924 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3925 goto drop;
3926
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003927 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3928 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003929
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003930 first = list_first_entry(SREJ_LIST(sk),
3931 struct srej_list, list);
3932 if (tx_seq == first->tx_seq) {
3933 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3934 l2cap_check_srej_gap(sk, tx_seq);
3935
3936 list_del(&first->list);
3937 kfree(first);
3938
3939 if (list_empty(SREJ_LIST(sk))) {
3940 pi->buffer_seq = pi->buffer_seq_srej;
3941 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003942 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003943 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003944 }
3945 } else {
3946 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003947
3948 /* duplicated tx_seq */
3949 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3950 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003951
3952 list_for_each_entry(l, SREJ_LIST(sk), list) {
3953 if (l->tx_seq == tx_seq) {
3954 l2cap_resend_srejframe(sk, tx_seq);
3955 return 0;
3956 }
3957 }
3958 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003959 }
3960 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003961 expected_tx_seq_offset =
3962 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3963 if (expected_tx_seq_offset < 0)
3964 expected_tx_seq_offset += 64;
3965
3966 /* duplicated tx_seq */
3967 if (tx_seq_offset < expected_tx_seq_offset)
3968 goto drop;
3969
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003970 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003971
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003972 BT_DBG("sk %p, Enter SREJ", sk);
3973
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003974 INIT_LIST_HEAD(SREJ_LIST(sk));
3975 pi->buffer_seq_srej = pi->buffer_seq;
3976
3977 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003978 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003979 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3980
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003981 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3982
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003983 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003984
3985 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003987 return 0;
3988
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003989expected:
3990 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3991
3992 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003993 bt_cb(skb)->tx_seq = tx_seq;
3994 bt_cb(skb)->sar = sar;
3995 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003996 return 0;
3997 }
3998
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003999 err = l2cap_push_rx_skb(sk, skb, rx_control);
4000 if (err < 0)
4001 return 0;
4002
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004003 if (rx_control & L2CAP_CTRL_FINAL) {
4004 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4005 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004006 else
4007 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004008 }
4009
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004010 __mod_ack_timer();
4011
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03004012 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
4013 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004014 l2cap_send_ack(pi);
4015
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004016 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004017
4018drop:
4019 kfree_skb(skb);
4020 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004021}
4022
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004023static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004024{
4025 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004026
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004027 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
4028 rx_control);
4029
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004030 pi->expected_ack_seq = __get_reqseq(rx_control);
4031 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004032
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004033 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004034 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004035 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4036 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4037 (pi->unacked_frames > 0))
4038 __mod_retrans_timer();
4039
4040 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4041 l2cap_send_srejtail(sk);
4042 } else {
4043 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004044 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004045
4046 } else if (rx_control & L2CAP_CTRL_FINAL) {
4047 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004048
4049 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4050 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004051 else
4052 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004053
4054 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004055 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4056 (pi->unacked_frames > 0))
4057 __mod_retrans_timer();
4058
4059 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004060 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004061 l2cap_send_ack(pi);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004062 } else {
4063 spin_lock_bh(&pi->send_lock);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004064 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004065 spin_unlock_bh(&pi->send_lock);
4066 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004067 }
4068}
4069
4070static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
4071{
4072 struct l2cap_pinfo *pi = l2cap_pi(sk);
4073 u8 tx_seq = __get_reqseq(rx_control);
4074
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004075 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4076
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004077 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4078
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03004079 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004080 l2cap_drop_acked_frames(sk);
4081
4082 if (rx_control & L2CAP_CTRL_FINAL) {
4083 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4084 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004085 else
4086 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004087 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004088 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004089
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03004090 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004091 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004092 }
4093}
4094static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
4095{
4096 struct l2cap_pinfo *pi = l2cap_pi(sk);
4097 u8 tx_seq = __get_reqseq(rx_control);
4098
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004099 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4100
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004101 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4102
4103 if (rx_control & L2CAP_CTRL_POLL) {
4104 pi->expected_ack_seq = tx_seq;
4105 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004106
4107 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004108 l2cap_retransmit_one_frame(sk, tx_seq);
4109
4110 spin_lock_bh(&pi->send_lock);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004111 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004112 spin_unlock_bh(&pi->send_lock);
4113
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 } else if (rx_control & L2CAP_CTRL_FINAL) {
4119 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
4120 pi->srej_save_reqseq == tx_seq)
4121 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
4122 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004123 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004124 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004125 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004126 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4127 pi->srej_save_reqseq = tx_seq;
4128 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4129 }
4130 }
4131}
4132
4133static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
4134{
4135 struct l2cap_pinfo *pi = l2cap_pi(sk);
4136 u8 tx_seq = __get_reqseq(rx_control);
4137
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004138 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4139
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004140 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
4141 pi->expected_ack_seq = tx_seq;
4142 l2cap_drop_acked_frames(sk);
4143
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004144 if (rx_control & L2CAP_CTRL_POLL)
4145 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
4146
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004147 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
4148 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03004149 if (rx_control & L2CAP_CTRL_POLL)
4150 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004151 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004152 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004153
4154 if (rx_control & L2CAP_CTRL_POLL)
4155 l2cap_send_srejtail(sk);
4156 else
4157 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004158}
4159
4160static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
4161{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004162 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
4163
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03004164 if (L2CAP_CTRL_FINAL & rx_control &&
4165 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004166 del_timer(&l2cap_pi(sk)->monitor_timer);
4167 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004168 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004169 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004170 }
4171
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004172 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
4173 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004174 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004175 break;
4176
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004177 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004178 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004179 break;
4180
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004181 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004182 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004183 break;
4184
4185 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004186 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004187 break;
4188 }
4189
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004190 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004191 return 0;
4192}
4193
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4195{
4196 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004197 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004198 u16 control;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03004199 u8 tx_seq, req_seq;
Nathan Holstein51893f82010-06-09 15:46:25 -04004200 int len, next_tx_seq_offset, req_seq_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
4202 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4203 if (!sk) {
4204 BT_DBG("unknown cid 0x%4.4x", cid);
4205 goto drop;
4206 }
4207
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004208 pi = l2cap_pi(sk);
4209
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 BT_DBG("sk %p, len %d", sk, skb->len);
4211
4212 if (sk->sk_state != BT_CONNECTED)
4213 goto drop;
4214
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004215 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004216 case L2CAP_MODE_BASIC:
4217 /* If socket recv buffers overflows we drop data here
4218 * which is *bad* because L2CAP has to be reliable.
4219 * But we don't have any other choice. L2CAP doesn't
4220 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004222 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004223 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004225 if (!sock_queue_rcv_skb(sk, skb))
4226 goto done;
4227 break;
4228
4229 case L2CAP_MODE_ERTM:
4230 control = get_unaligned_le16(skb->data);
4231 skb_pull(skb, 2);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03004232 len = skb->len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004233
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004234 /*
4235 * We can just drop the corrupted I-frame here.
4236 * Receiver will miss it and start proper recovery
4237 * procedures and ask retransmission.
4238 */
4239 if (l2cap_check_fcs(pi, skb))
4240 goto drop;
4241
Gustavo F. Padovanbc1b1f82010-05-11 22:14:00 -03004242 if (__is_sar_start(control) && __is_iframe(control))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03004243 len -= 2;
4244
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004245 if (pi->fcs == L2CAP_FCS_CRC16)
4246 len -= 2;
4247
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004248 if (len > pi->mps) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03004249 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004250 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004251 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004252
João Paulo Rechi Vita01760bd2010-05-01 16:15:43 -03004253 req_seq = __get_reqseq(control);
4254 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4255 if (req_seq_offset < 0)
4256 req_seq_offset += 64;
4257
4258 next_tx_seq_offset =
4259 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4260 if (next_tx_seq_offset < 0)
4261 next_tx_seq_offset += 64;
4262
4263 /* check for invalid req-seq */
4264 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03004265 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita01760bd2010-05-01 16:15:43 -03004266 goto drop;
4267 }
4268
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004269 if (__is_iframe(control)) {
Nathan Holstein51893f82010-06-09 15:46:25 -04004270 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03004271 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004272 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004273 }
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004274
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004275 l2cap_data_channel_iframe(sk, control, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004276 } else {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004277 if (len != 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03004278 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004279 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004280 }
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004281
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004282 l2cap_data_channel_sframe(sk, control, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004283 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004284
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004285 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004286
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004287 case L2CAP_MODE_STREAMING:
4288 control = get_unaligned_le16(skb->data);
4289 skb_pull(skb, 2);
4290 len = skb->len;
4291
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004292 if (l2cap_check_fcs(pi, skb))
4293 goto drop;
4294
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004295 if (__is_sar_start(control))
4296 len -= 2;
4297
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004298 if (pi->fcs == L2CAP_FCS_CRC16)
4299 len -= 2;
4300
Nathan Holstein51893f82010-06-09 15:46:25 -04004301 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004302 goto drop;
4303
4304 tx_seq = __get_txseq(control);
4305
4306 if (pi->expected_tx_seq == tx_seq)
4307 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4308 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004309 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004310
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004311 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004312
4313 goto done;
4314
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004315 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004316 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004317 break;
4318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
4320drop:
4321 kfree_skb(skb);
4322
4323done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004324 if (sk)
4325 bh_unlock_sock(sk);
4326
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 return 0;
4328}
4329
Al Viro8e036fc2007-07-29 00:16:36 -07004330static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331{
4332 struct sock *sk;
4333
4334 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4335 if (!sk)
4336 goto drop;
4337
4338 BT_DBG("sk %p, len %d", sk, skb->len);
4339
4340 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4341 goto drop;
4342
4343 if (l2cap_pi(sk)->imtu < skb->len)
4344 goto drop;
4345
4346 if (!sock_queue_rcv_skb(sk, skb))
4347 goto done;
4348
4349drop:
4350 kfree_skb(skb);
4351
4352done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004353 if (sk)
4354 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355 return 0;
4356}
4357
4358static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4359{
4360 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004361 u16 cid, len;
4362 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
4364 skb_pull(skb, L2CAP_HDR_SIZE);
4365 cid = __le16_to_cpu(lh->cid);
4366 len = __le16_to_cpu(lh->len);
4367
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004368 if (len != skb->len) {
4369 kfree_skb(skb);
4370 return;
4371 }
4372
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4374
4375 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004376 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 l2cap_sig_channel(conn, skb);
4378 break;
4379
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004380 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004381 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 skb_pull(skb, 2);
4383 l2cap_conless_channel(conn, psm, skb);
4384 break;
4385
4386 default:
4387 l2cap_data_channel(conn, cid, skb);
4388 break;
4389 }
4390}
4391
4392/* ---- L2CAP interface with lower layer (HCI) ---- */
4393
4394static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4395{
4396 int exact = 0, lm1 = 0, lm2 = 0;
4397 register struct sock *sk;
4398 struct hlist_node *node;
4399
4400 if (type != ACL_LINK)
4401 return 0;
4402
4403 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4404
4405 /* Find listening sockets and check their link_mode */
4406 read_lock(&l2cap_sk_list.lock);
4407 sk_for_each(sk, node, &l2cap_sk_list.head) {
4408 if (sk->sk_state != BT_LISTEN)
4409 continue;
4410
4411 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004412 lm1 |= HCI_LM_ACCEPT;
4413 if (l2cap_pi(sk)->role_switch)
4414 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004416 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4417 lm2 |= HCI_LM_ACCEPT;
4418 if (l2cap_pi(sk)->role_switch)
4419 lm2 |= HCI_LM_MASTER;
4420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 }
4422 read_unlock(&l2cap_sk_list.lock);
4423
4424 return exact ? lm1 : lm2;
4425}
4426
4427static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4428{
Marcel Holtmann01394182006-07-03 10:02:46 +02004429 struct l2cap_conn *conn;
4430
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4432
4433 if (hcon->type != ACL_LINK)
4434 return 0;
4435
4436 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 conn = l2cap_conn_add(hcon, status);
4438 if (conn)
4439 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004440 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441 l2cap_conn_del(hcon, bt_err(status));
4442
4443 return 0;
4444}
4445
Marcel Holtmann2950f212009-02-12 14:02:50 +01004446static int l2cap_disconn_ind(struct hci_conn *hcon)
4447{
4448 struct l2cap_conn *conn = hcon->l2cap_data;
4449
4450 BT_DBG("hcon %p", hcon);
4451
4452 if (hcon->type != ACL_LINK || !conn)
4453 return 0x13;
4454
4455 return conn->disc_reason;
4456}
4457
4458static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459{
4460 BT_DBG("hcon %p reason %d", hcon, reason);
4461
4462 if (hcon->type != ACL_LINK)
4463 return 0;
4464
4465 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004466
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 return 0;
4468}
4469
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004470static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4471{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004472 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004473 return;
4474
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004475 if (encrypt == 0x00) {
4476 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4477 l2cap_sock_clear_timer(sk);
4478 l2cap_sock_set_timer(sk, HZ * 5);
4479 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4480 __l2cap_sock_close(sk, ECONNREFUSED);
4481 } else {
4482 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4483 l2cap_sock_clear_timer(sk);
4484 }
4485}
4486
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004487static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488{
4489 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004490 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492
Marcel Holtmann01394182006-07-03 10:02:46 +02004493 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004495
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 l = &conn->chan_list;
4497
4498 BT_DBG("conn %p", conn);
4499
4500 read_lock(&l->lock);
4501
4502 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4503 bh_lock_sock(sk);
4504
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004505 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4506 bh_unlock_sock(sk);
4507 continue;
4508 }
4509
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004510 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004511 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004512 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004513 bh_unlock_sock(sk);
4514 continue;
4515 }
4516
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004517 if (sk->sk_state == BT_CONNECT) {
4518 if (!status) {
4519 struct l2cap_conn_req req;
4520 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4521 req.psm = l2cap_pi(sk)->psm;
4522
4523 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004524 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004525
4526 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4527 L2CAP_CONN_REQ, sizeof(req), &req);
4528 } else {
4529 l2cap_sock_clear_timer(sk);
4530 l2cap_sock_set_timer(sk, HZ / 10);
4531 }
4532 } else if (sk->sk_state == BT_CONNECT2) {
4533 struct l2cap_conn_rsp rsp;
4534 __u16 result;
4535
4536 if (!status) {
4537 sk->sk_state = BT_CONFIG;
4538 result = L2CAP_CR_SUCCESS;
4539 } else {
4540 sk->sk_state = BT_DISCONN;
4541 l2cap_sock_set_timer(sk, HZ / 10);
4542 result = L2CAP_CR_SEC_BLOCK;
4543 }
4544
4545 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4546 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4547 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004548 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004549 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4550 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 }
4552
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553 bh_unlock_sock(sk);
4554 }
4555
4556 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004557
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 return 0;
4559}
4560
4561static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4562{
4563 struct l2cap_conn *conn = hcon->l2cap_data;
4564
4565 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
4566 goto drop;
4567
4568 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4569
4570 if (flags & ACL_START) {
4571 struct l2cap_hdr *hdr;
4572 int len;
4573
4574 if (conn->rx_len) {
4575 BT_ERR("Unexpected start frame (len %d)", skb->len);
4576 kfree_skb(conn->rx_skb);
4577 conn->rx_skb = NULL;
4578 conn->rx_len = 0;
4579 l2cap_conn_unreliable(conn, ECOMM);
4580 }
4581
4582 if (skb->len < 2) {
4583 BT_ERR("Frame is too short (len %d)", skb->len);
4584 l2cap_conn_unreliable(conn, ECOMM);
4585 goto drop;
4586 }
4587
4588 hdr = (struct l2cap_hdr *) skb->data;
4589 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
4590
4591 if (len == skb->len) {
4592 /* Complete frame received */
4593 l2cap_recv_frame(conn, skb);
4594 return 0;
4595 }
4596
4597 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4598
4599 if (skb->len > len) {
4600 BT_ERR("Frame is too long (len %d, expected len %d)",
4601 skb->len, len);
4602 l2cap_conn_unreliable(conn, ECOMM);
4603 goto drop;
4604 }
4605
4606 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004607 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4608 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 goto drop;
4610
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004611 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004612 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 conn->rx_len = len - skb->len;
4614 } else {
4615 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4616
4617 if (!conn->rx_len) {
4618 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4619 l2cap_conn_unreliable(conn, ECOMM);
4620 goto drop;
4621 }
4622
4623 if (skb->len > conn->rx_len) {
4624 BT_ERR("Fragment is too long (len %d, expected %d)",
4625 skb->len, conn->rx_len);
4626 kfree_skb(conn->rx_skb);
4627 conn->rx_skb = NULL;
4628 conn->rx_len = 0;
4629 l2cap_conn_unreliable(conn, ECOMM);
4630 goto drop;
4631 }
4632
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004633 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004634 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635 conn->rx_len -= skb->len;
4636
4637 if (!conn->rx_len) {
4638 /* Complete frame received */
4639 l2cap_recv_frame(conn, conn->rx_skb);
4640 conn->rx_skb = NULL;
4641 }
4642 }
4643
4644drop:
4645 kfree_skb(skb);
4646 return 0;
4647}
4648
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004649static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650{
4651 struct sock *sk;
4652 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
4654 read_lock_bh(&l2cap_sk_list.lock);
4655
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004656 sk_for_each(sk, node, &l2cap_sk_list.head) {
4657 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004659 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4660 batostr(&bt_sk(sk)->src),
4661 batostr(&bt_sk(sk)->dst),
4662 sk->sk_state, __le16_to_cpu(pi->psm),
4663 pi->scid, pi->dcid,
4664 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004668
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004669 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670}
4671
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004672static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4673{
4674 return single_open(file, l2cap_debugfs_show, inode->i_private);
4675}
4676
4677static const struct file_operations l2cap_debugfs_fops = {
4678 .open = l2cap_debugfs_open,
4679 .read = seq_read,
4680 .llseek = seq_lseek,
4681 .release = single_release,
4682};
4683
4684static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004686static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687 .family = PF_BLUETOOTH,
4688 .owner = THIS_MODULE,
4689 .release = l2cap_sock_release,
4690 .bind = l2cap_sock_bind,
4691 .connect = l2cap_sock_connect,
4692 .listen = l2cap_sock_listen,
4693 .accept = l2cap_sock_accept,
4694 .getname = l2cap_sock_getname,
4695 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004696 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004698 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 .mmap = sock_no_mmap,
4700 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701 .shutdown = l2cap_sock_shutdown,
4702 .setsockopt = l2cap_sock_setsockopt,
4703 .getsockopt = l2cap_sock_getsockopt
4704};
4705
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004706static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707 .family = PF_BLUETOOTH,
4708 .owner = THIS_MODULE,
4709 .create = l2cap_sock_create,
4710};
4711
4712static struct hci_proto l2cap_hci_proto = {
4713 .name = "L2CAP",
4714 .id = HCI_PROTO_L2CAP,
4715 .connect_ind = l2cap_connect_ind,
4716 .connect_cfm = l2cap_connect_cfm,
4717 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004718 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004719 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720 .recv_acldata = l2cap_recv_acldata
4721};
4722
4723static int __init l2cap_init(void)
4724{
4725 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004726
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 err = proto_register(&l2cap_proto, 0);
4728 if (err < 0)
4729 return err;
4730
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004731 _busy_wq = create_singlethread_workqueue("l2cap");
4732 if (!_busy_wq)
4733 goto error;
4734
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4736 if (err < 0) {
4737 BT_ERR("L2CAP socket registration failed");
4738 goto error;
4739 }
4740
4741 err = hci_register_proto(&l2cap_hci_proto);
4742 if (err < 0) {
4743 BT_ERR("L2CAP protocol registration failed");
4744 bt_sock_unregister(BTPROTO_L2CAP);
4745 goto error;
4746 }
4747
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004748 if (bt_debugfs) {
4749 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4750 bt_debugfs, NULL, &l2cap_debugfs_fops);
4751 if (!l2cap_debugfs)
4752 BT_ERR("Failed to create L2CAP debug file");
4753 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754
4755 BT_INFO("L2CAP ver %s", VERSION);
4756 BT_INFO("L2CAP socket layer initialized");
4757
4758 return 0;
4759
4760error:
4761 proto_unregister(&l2cap_proto);
4762 return err;
4763}
4764
4765static void __exit l2cap_exit(void)
4766{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004767 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004769 flush_workqueue(_busy_wq);
4770 destroy_workqueue(_busy_wq);
4771
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4773 BT_ERR("L2CAP socket unregistration failed");
4774
4775 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4776 BT_ERR("L2CAP protocol unregistration failed");
4777
4778 proto_unregister(&l2cap_proto);
4779}
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
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004792module_param(enable_ertm, bool, 0644);
4793MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
4794
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");