blob: 7550abb0c96a36d60869009daecd20a601eb7263 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
27/* Bluetooth L2CAP core and sockets. */
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovandd135242010-07-13 11:57:12 -030058#define VERSION "2.15"
Marcel Holtmann44dd46d2009-05-02 19:09:01 -070059
Andrei Emeltchenko894718a2010-12-01 16:58:24 +020060static int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010063static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Eric Dumazet90ddc4f2005-12-22 12:49:22 -080065static const struct proto_ops l2cap_sock_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030067static struct workqueue_struct *_busy_wq;
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069static struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070070 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071};
72
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030073static void l2cap_busy_work(struct work_struct *work);
74
Linus Torvalds1da177e2005-04-16 15:20:36 -070075static void __l2cap_sock_close(struct sock *sk, int reason);
76static void l2cap_sock_close(struct sock *sk);
77static void l2cap_sock_kill(struct sock *sk);
78
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -030079static int l2cap_build_conf_req(struct sock *sk, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
81 u8 code, u8 ident, u16 dlen, void *data);
82
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030083static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085/* ---- L2CAP timers ---- */
Andrei Emeltchenko940a9ee2010-11-03 12:32:45 +020086static void l2cap_sock_set_timer(struct sock *sk, long timeout)
87{
88 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
89 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
90}
91
92static void l2cap_sock_clear_timer(struct sock *sk)
93{
94 BT_DBG("sock %p state %d", sk, sk->sk_state);
95 sk_stop_timer(sk, &sk->sk_timer);
96}
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098static void l2cap_sock_timeout(unsigned long arg)
99{
100 struct sock *sk = (struct sock *) arg;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200101 int reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103 BT_DBG("sock %p state %d", sk, sk->sk_state);
104
105 bh_lock_sock(sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200106
Andrei Emeltchenko940a9ee2010-11-03 12:32:45 +0200107 if (sock_owned_by_user(sk)) {
108 /* sk is owned by user. Try again later */
109 l2cap_sock_set_timer(sk, HZ / 5);
110 bh_unlock_sock(sk);
111 sock_put(sk);
112 return;
113 }
114
Marcel Holtmannf62e4322009-01-15 21:58:44 +0100115 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
116 reason = ECONNREFUSED;
117 else if (sk->sk_state == BT_CONNECT &&
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100118 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200119 reason = ECONNREFUSED;
120 else
121 reason = ETIMEDOUT;
122
123 __l2cap_sock_close(sk, reason);
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 bh_unlock_sock(sk);
126
127 l2cap_sock_kill(sk);
128 sock_put(sk);
129}
130
Marcel Holtmann01394182006-07-03 10:02:46 +0200131/* ---- L2CAP channels ---- */
132static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
133{
134 struct sock *s;
135 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
136 if (l2cap_pi(s)->dcid == cid)
137 break;
138 }
139 return s;
140}
141
142static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
143{
144 struct sock *s;
145 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
146 if (l2cap_pi(s)->scid == cid)
147 break;
148 }
149 return s;
150}
151
152/* Find channel with given SCID.
153 * Returns locked socket */
154static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
155{
156 struct sock *s;
157 read_lock(&l->lock);
158 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300159 if (s)
160 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200161 read_unlock(&l->lock);
162 return s;
163}
164
165static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
166{
167 struct sock *s;
168 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
169 if (l2cap_pi(s)->ident == ident)
170 break;
171 }
172 return s;
173}
174
175static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
176{
177 struct sock *s;
178 read_lock(&l->lock);
179 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300180 if (s)
181 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200182 read_unlock(&l->lock);
183 return s;
184}
185
186static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
187{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300188 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200189
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300190 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300191 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200192 return cid;
193 }
194
195 return 0;
196}
197
198static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
199{
200 sock_hold(sk);
201
202 if (l->head)
203 l2cap_pi(l->head)->prev_c = sk;
204
205 l2cap_pi(sk)->next_c = l->head;
206 l2cap_pi(sk)->prev_c = NULL;
207 l->head = sk;
208}
209
210static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
211{
212 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
213
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200214 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215 if (sk == l->head)
216 l->head = next;
217
218 if (next)
219 l2cap_pi(next)->prev_c = prev;
220 if (prev)
221 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200222 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200223
224 __sock_put(sk);
225}
226
227static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
228{
229 struct l2cap_chan_list *l = &conn->chan_list;
230
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300231 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
232 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200233
Marcel Holtmann2950f212009-02-12 14:02:50 +0100234 conn->disc_reason = 0x13;
235
Marcel Holtmann01394182006-07-03 10:02:46 +0200236 l2cap_pi(sk)->conn = conn;
237
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300238 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200239 /* Alloc CID for connection-oriented socket */
240 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
241 } else if (sk->sk_type == SOCK_DGRAM) {
242 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300243 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
244 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200245 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
246 } else {
247 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300248 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
249 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200250 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
251 }
252
253 __l2cap_chan_link(l, sk);
254
255 if (parent)
256 bt_accept_enqueue(parent, sk);
257}
258
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900259/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200260 * Must be called on the locked socket. */
261static void l2cap_chan_del(struct sock *sk, int err)
262{
263 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
264 struct sock *parent = bt_sk(sk)->parent;
265
266 l2cap_sock_clear_timer(sk);
267
268 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
269
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900270 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200271 /* Unlink from channel list */
272 l2cap_chan_unlink(&conn->chan_list, sk);
273 l2cap_pi(sk)->conn = NULL;
274 hci_conn_put(conn->hcon);
275 }
276
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200277 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200278 sock_set_flag(sk, SOCK_ZAPPED);
279
280 if (err)
281 sk->sk_err = err;
282
283 if (parent) {
284 bt_accept_unlink(sk);
285 parent->sk_data_ready(parent, 0);
286 } else
287 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300288
289 skb_queue_purge(TX_QUEUE(sk));
290
291 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
292 struct srej_list *l, *tmp;
293
294 del_timer(&l2cap_pi(sk)->retrans_timer);
295 del_timer(&l2cap_pi(sk)->monitor_timer);
296 del_timer(&l2cap_pi(sk)->ack_timer);
297
298 skb_queue_purge(SREJ_QUEUE(sk));
299 skb_queue_purge(BUSY_QUEUE(sk));
300
301 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
302 list_del(&l->list);
303 kfree(l);
304 }
305 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200306}
307
Johan Hedberg8556edd32011-01-19 12:06:50 +0530308static inline u8 l2cap_get_auth_type(struct sock *sk)
309{
310 if (sk->sk_type == SOCK_RAW) {
311 switch (l2cap_pi(sk)->sec_level) {
312 case BT_SECURITY_HIGH:
313 return HCI_AT_DEDICATED_BONDING_MITM;
314 case BT_SECURITY_MEDIUM:
315 return HCI_AT_DEDICATED_BONDING;
316 default:
317 return HCI_AT_NO_BONDING;
318 }
319 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
320 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
321 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
322
323 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
324 return HCI_AT_NO_BONDING_MITM;
325 else
326 return HCI_AT_NO_BONDING;
327 } else {
328 switch (l2cap_pi(sk)->sec_level) {
329 case BT_SECURITY_HIGH:
330 return HCI_AT_GENERAL_BONDING_MITM;
331 case BT_SECURITY_MEDIUM:
332 return HCI_AT_GENERAL_BONDING;
333 default:
334 return HCI_AT_NO_BONDING;
335 }
336 }
337}
338
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200339/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100340static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200341{
342 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100343 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200344
Johan Hedberg8556edd32011-01-19 12:06:50 +0530345 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100346
347 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
348 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200349}
350
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200351static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
352{
353 u8 id;
354
355 /* Get next available identificator.
356 * 1 - 128 are used by kernel.
357 * 129 - 199 are reserved.
358 * 200 - 254 are used by utilities like l2ping, etc.
359 */
360
361 spin_lock_bh(&conn->lock);
362
363 if (++conn->tx_ident > 128)
364 conn->tx_ident = 1;
365
366 id = conn->tx_ident;
367
368 spin_unlock_bh(&conn->lock);
369
370 return id;
371}
372
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300373static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200374{
375 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
376
377 BT_DBG("code 0x%2.2x", code);
378
379 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300380 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200381
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300382 hci_send_acl(conn->hcon, skb, 0);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200383}
384
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300385static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300386{
387 struct sk_buff *skb;
388 struct l2cap_hdr *lh;
389 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300390 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300391 int count, hlen = L2CAP_HDR_SIZE + 2;
392
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300393 if (sk->sk_state != BT_CONNECTED)
394 return;
395
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300396 if (pi->fcs == L2CAP_FCS_CRC16)
397 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300398
399 BT_DBG("pi %p, control 0x%2.2x", pi, control);
400
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300401 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300402 control |= L2CAP_CTRL_FRAME_TYPE;
403
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300404 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
405 control |= L2CAP_CTRL_FINAL;
406 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
407 }
408
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300409 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
410 control |= L2CAP_CTRL_POLL;
411 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
412 }
413
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300414 skb = bt_skb_alloc(count, GFP_ATOMIC);
415 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300416 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300417
418 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300419 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300420 lh->cid = cpu_to_le16(pi->dcid);
421 put_unaligned_le16(control, skb_put(skb, 2));
422
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300423 if (pi->fcs == L2CAP_FCS_CRC16) {
424 u16 fcs = crc16(0, (u8 *)lh, count - 2);
425 put_unaligned_le16(fcs, skb_put(skb, 2));
426 }
427
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300428 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300429}
430
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300431static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300432{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300433 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300434 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300435 pi->conn_state |= L2CAP_CONN_RNR_SENT;
436 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300437 control |= L2CAP_SUPER_RCV_READY;
438
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300439 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
440
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300441 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300442}
443
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300444static inline int __l2cap_no_conn_pending(struct sock *sk)
445{
446 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
447}
448
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200449static void l2cap_do_start(struct sock *sk)
450{
451 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
452
453 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100454 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
455 return;
456
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300457 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200458 struct l2cap_conn_req req;
459 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
460 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200461
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200462 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300463 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200464
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200465 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200466 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200467 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200468 } else {
469 struct l2cap_info_req req;
470 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
471
472 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
473 conn->info_ident = l2cap_get_ident(conn);
474
475 mod_timer(&conn->info_timer, jiffies +
476 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
477
478 l2cap_send_cmd(conn, conn->info_ident,
479 L2CAP_INFO_REQ, sizeof(req), &req);
480 }
481}
482
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300483static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
484{
485 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300486 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300487 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
488
489 switch (mode) {
490 case L2CAP_MODE_ERTM:
491 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
492 case L2CAP_MODE_STREAMING:
493 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
494 default:
495 return 0x00;
496 }
497}
498
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300499static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300500{
501 struct l2cap_disconn_req req;
502
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300503 if (!conn)
504 return;
505
506 skb_queue_purge(TX_QUEUE(sk));
507
508 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
509 del_timer(&l2cap_pi(sk)->retrans_timer);
510 del_timer(&l2cap_pi(sk)->monitor_timer);
511 del_timer(&l2cap_pi(sk)->ack_timer);
512 }
513
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300514 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
515 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
516 l2cap_send_cmd(conn, l2cap_get_ident(conn),
517 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300518
519 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300520 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300521}
522
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200524static void l2cap_conn_start(struct l2cap_conn *conn)
525{
526 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300527 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200528 struct sock *sk;
529
530 BT_DBG("conn %p", conn);
531
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300532 INIT_LIST_HEAD(&del.list);
533
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200534 read_lock(&l->lock);
535
536 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
537 bh_lock_sock(sk);
538
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300539 if (sk->sk_type != SOCK_SEQPACKET &&
540 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200541 bh_unlock_sock(sk);
542 continue;
543 }
544
545 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300546 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300547
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300548 if (!l2cap_check_security(sk) ||
549 !__l2cap_no_conn_pending(sk)) {
550 bh_unlock_sock(sk);
551 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200552 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300553
554 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
555 conn->feat_mask)
556 && l2cap_pi(sk)->conf_state &
557 L2CAP_CONF_STATE2_DEVICE) {
558 tmp1 = kzalloc(sizeof(struct sock_del_list),
559 GFP_ATOMIC);
560 tmp1->sk = sk;
561 list_add_tail(&tmp1->list, &del.list);
562 bh_unlock_sock(sk);
563 continue;
564 }
565
566 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
567 req.psm = l2cap_pi(sk)->psm;
568
569 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
570 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
571
572 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
573 L2CAP_CONN_REQ, sizeof(req), &req);
574
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200575 } else if (sk->sk_state == BT_CONNECT2) {
576 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300577 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200578 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
579 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
580
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100581 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100582 if (bt_sk(sk)->defer_setup) {
583 struct sock *parent = bt_sk(sk)->parent;
584 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
585 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
586 parent->sk_data_ready(parent, 0);
587
588 } else {
589 sk->sk_state = BT_CONFIG;
590 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
591 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
592 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200593 } else {
594 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
595 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
596 }
597
598 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
599 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300600
601 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
602 rsp.result != L2CAP_CR_SUCCESS) {
603 bh_unlock_sock(sk);
604 continue;
605 }
606
607 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
608 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
609 l2cap_build_conf_req(sk, buf), buf);
610 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200611 }
612
613 bh_unlock_sock(sk);
614 }
615
616 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300617
618 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
619 bh_lock_sock(tmp1->sk);
620 __l2cap_sock_close(tmp1->sk, ECONNRESET);
621 bh_unlock_sock(tmp1->sk);
622 list_del(&tmp1->list);
623 kfree(tmp1);
624 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200625}
626
627static void l2cap_conn_ready(struct l2cap_conn *conn)
628{
629 struct l2cap_chan_list *l = &conn->chan_list;
630 struct sock *sk;
631
632 BT_DBG("conn %p", conn);
633
634 read_lock(&l->lock);
635
636 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
637 bh_lock_sock(sk);
638
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300639 if (sk->sk_type != SOCK_SEQPACKET &&
640 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200641 l2cap_sock_clear_timer(sk);
642 sk->sk_state = BT_CONNECTED;
643 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200644 } else if (sk->sk_state == BT_CONNECT)
645 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200646
647 bh_unlock_sock(sk);
648 }
649
650 read_unlock(&l->lock);
651}
652
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200653/* Notify sockets that we cannot guaranty reliability anymore */
654static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
655{
656 struct l2cap_chan_list *l = &conn->chan_list;
657 struct sock *sk;
658
659 BT_DBG("conn %p", conn);
660
661 read_lock(&l->lock);
662
663 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100664 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200665 sk->sk_err = err;
666 }
667
668 read_unlock(&l->lock);
669}
670
671static void l2cap_info_timeout(unsigned long arg)
672{
673 struct l2cap_conn *conn = (void *) arg;
674
Marcel Holtmann984947d2009-02-06 23:35:19 +0100675 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100676 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100677
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200678 l2cap_conn_start(conn);
679}
680
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
682{
Marcel Holtmann01394182006-07-03 10:02:46 +0200683 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Marcel Holtmann01394182006-07-03 10:02:46 +0200685 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 return conn;
687
Marcel Holtmann01394182006-07-03 10:02:46 +0200688 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
689 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 hcon->l2cap_data = conn;
693 conn->hcon = hcon;
694
Marcel Holtmann01394182006-07-03 10:02:46 +0200695 BT_DBG("hcon %p conn %p", hcon, conn);
696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 conn->mtu = hcon->hdev->acl_mtu;
698 conn->src = &hcon->hdev->bdaddr;
699 conn->dst = &hcon->dst;
700
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200701 conn->feat_mask = 0;
702
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 spin_lock_init(&conn->lock);
704 rwlock_init(&conn->chan_list.lock);
705
Dave Young45054dc2009-10-18 20:28:30 +0000706 setup_timer(&conn->info_timer, l2cap_info_timeout,
707 (unsigned long) conn);
708
Marcel Holtmann2950f212009-02-12 14:02:50 +0100709 conn->disc_reason = 0x13;
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 return conn;
712}
713
Marcel Holtmann01394182006-07-03 10:02:46 +0200714static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Marcel Holtmann01394182006-07-03 10:02:46 +0200716 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 struct sock *sk;
718
Marcel Holtmann01394182006-07-03 10:02:46 +0200719 if (!conn)
720 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
723
Wei Yongjun7585b972009-02-25 18:29:52 +0800724 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 /* Kill channels */
727 while ((sk = conn->chan_list.head)) {
728 bh_lock_sock(sk);
729 l2cap_chan_del(sk, err);
730 bh_unlock_sock(sk);
731 l2cap_sock_kill(sk);
732 }
733
Dave Young8e8440f2008-03-03 12:18:55 -0800734 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
735 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 hcon->l2cap_data = NULL;
738 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739}
740
741static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
742{
743 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200744 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200746 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747}
748
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749/* ---- Socket interface ---- */
Al Viro8e036fc2007-07-29 00:16:36 -0700750static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751{
752 struct sock *sk;
753 struct hlist_node *node;
754 sk_for_each(sk, node, &l2cap_sk_list.head)
755 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
756 goto found;
757 sk = NULL;
758found:
759 return sk;
760}
761
762/* Find socket with psm and source bdaddr.
763 * Returns closest match.
764 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000765static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
767 struct sock *sk = NULL, *sk1 = NULL;
768 struct hlist_node *node;
769
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000770 read_lock(&l2cap_sk_list.lock);
771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 sk_for_each(sk, node, &l2cap_sk_list.head) {
773 if (state && sk->sk_state != state)
774 continue;
775
776 if (l2cap_pi(sk)->psm == psm) {
777 /* Exact match. */
778 if (!bacmp(&bt_sk(sk)->src, src))
779 break;
780
781 /* Closest match */
782 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
783 sk1 = sk;
784 }
785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000788
789 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790}
791
792static void l2cap_sock_destruct(struct sock *sk)
793{
794 BT_DBG("sk %p", sk);
795
796 skb_queue_purge(&sk->sk_receive_queue);
797 skb_queue_purge(&sk->sk_write_queue);
798}
799
800static void l2cap_sock_cleanup_listen(struct sock *parent)
801{
802 struct sock *sk;
803
804 BT_DBG("parent %p", parent);
805
806 /* Close not yet accepted channels */
807 while ((sk = bt_accept_dequeue(parent, NULL)))
808 l2cap_sock_close(sk);
809
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200810 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 sock_set_flag(parent, SOCK_ZAPPED);
812}
813
814/* Kill socket (only if zapped and orphan)
815 * Must be called on unlocked socket.
816 */
817static void l2cap_sock_kill(struct sock *sk)
818{
819 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
820 return;
821
822 BT_DBG("sk %p state %d", sk, sk->sk_state);
823
824 /* Kill poor orphan */
825 bt_sock_unlink(&l2cap_sk_list, sk);
826 sock_set_flag(sk, SOCK_DEAD);
827 sock_put(sk);
828}
829
830static void __l2cap_sock_close(struct sock *sk, int reason)
831{
832 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
833
834 switch (sk->sk_state) {
835 case BT_LISTEN:
836 l2cap_sock_cleanup_listen(sk);
837 break;
838
839 case BT_CONNECTED:
840 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300841 if (sk->sk_type == SOCK_SEQPACKET ||
842 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300846 l2cap_send_disconn_req(conn, sk, reason);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200847 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 break;
850
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100851 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300852 if (sk->sk_type == SOCK_SEQPACKET ||
853 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100854 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
855 struct l2cap_conn_rsp rsp;
856 __u16 result;
857
858 if (bt_sk(sk)->defer_setup)
859 result = L2CAP_CR_SEC_BLOCK;
860 else
861 result = L2CAP_CR_BAD_PSM;
862
863 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
864 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
865 rsp.result = cpu_to_le16(result);
866 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
867 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
868 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
869 } else
870 l2cap_chan_del(sk, reason);
871 break;
872
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 case BT_CONNECT:
874 case BT_DISCONN:
875 l2cap_chan_del(sk, reason);
876 break;
877
878 default:
879 sock_set_flag(sk, SOCK_ZAPPED);
880 break;
881 }
882}
883
884/* Must be called on unlocked socket. */
885static void l2cap_sock_close(struct sock *sk)
886{
887 l2cap_sock_clear_timer(sk);
888 lock_sock(sk);
889 __l2cap_sock_close(sk, ECONNRESET);
890 release_sock(sk);
891 l2cap_sock_kill(sk);
892}
893
894static void l2cap_sock_init(struct sock *sk, struct sock *parent)
895{
896 struct l2cap_pinfo *pi = l2cap_pi(sk);
897
898 BT_DBG("sk %p", sk);
899
900 if (parent) {
901 sk->sk_type = parent->sk_type;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100902 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 pi->imtu = l2cap_pi(parent)->imtu;
905 pi->omtu = l2cap_pi(parent)->omtu;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300906 pi->conf_state = l2cap_pi(parent)->conf_state;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700907 pi->mode = l2cap_pi(parent)->mode;
908 pi->fcs = l2cap_pi(parent)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -0300909 pi->max_tx = l2cap_pi(parent)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -0300910 pi->tx_win = l2cap_pi(parent)->tx_win;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100911 pi->sec_level = l2cap_pi(parent)->sec_level;
912 pi->role_switch = l2cap_pi(parent)->role_switch;
913 pi->force_reliable = l2cap_pi(parent)->force_reliable;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 } else {
915 pi->imtu = L2CAP_DEFAULT_MTU;
916 pi->omtu = 0;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300917 if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300918 pi->mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300919 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
920 } else {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300921 pi->mode = L2CAP_MODE_BASIC;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300922 }
Gustavo F. Padovanfd059b92010-05-10 14:22:56 -0300923 pi->max_tx = L2CAP_DEFAULT_MAX_TX;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700924 pi->fcs = L2CAP_FCS_CRC16;
Gustavo F. Padovanfd059b92010-05-10 14:22:56 -0300925 pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100926 pi->sec_level = BT_SECURITY_LOW;
927 pi->role_switch = 0;
928 pi->force_reliable = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 }
930
931 /* Default config options */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +0200932 pi->conf_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Dave Young45054dc2009-10-18 20:28:30 +0000934 skb_queue_head_init(TX_QUEUE(sk));
935 skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300936 skb_queue_head_init(BUSY_QUEUE(sk));
Dave Young45054dc2009-10-18 20:28:30 +0000937 INIT_LIST_HEAD(SREJ_LIST(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938}
939
940static struct proto l2cap_proto = {
941 .name = "L2CAP",
942 .owner = THIS_MODULE,
943 .obj_size = sizeof(struct l2cap_pinfo)
944};
945
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700946static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947{
948 struct sock *sk;
949
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700950 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (!sk)
952 return NULL;
953
954 sock_init_data(sock, sk);
955 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
956
957 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200958 sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960 sock_reset_flag(sk, SOCK_ZAPPED);
961
962 sk->sk_protocol = proto;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200963 sk->sk_state = BT_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200965 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966
967 bt_sock_link(&l2cap_sk_list, sk);
968 return sk;
969}
970
Eric Paris3f378b62009-11-05 22:18:14 -0800971static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
972 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973{
974 struct sock *sk;
975
976 BT_DBG("sock %p", sock);
977
978 sock->state = SS_UNCONNECTED;
979
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300980 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
982 return -ESOCKTNOSUPPORT;
983
Eric Parisc84b3262009-11-05 20:45:52 -0800984 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 return -EPERM;
986
987 sock->ops = &l2cap_sock_ops;
988
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700989 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 if (!sk)
991 return -ENOMEM;
992
993 l2cap_sock_init(sk, NULL);
994 return 0;
995}
996
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100997static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001000 struct sockaddr_l2 la;
1001 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001003 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
1005 if (!addr || addr->sa_family != AF_BLUETOOTH)
1006 return -EINVAL;
1007
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001008 memset(&la, 0, sizeof(la));
1009 len = min_t(unsigned int, sizeof(la), alen);
1010 memcpy(&la, addr, len);
1011
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001012 if (la.l2_cid)
1013 return -EINVAL;
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 lock_sock(sk);
1016
1017 if (sk->sk_state != BT_OPEN) {
1018 err = -EBADFD;
1019 goto done;
1020 }
1021
Mat Martineau0fba2552010-09-08 10:05:26 -07001022 if (la.l2_psm) {
1023 __u16 psm = __le16_to_cpu(la.l2_psm);
1024
1025 /* PSM must be odd and lsb of upper byte must be 0 */
1026 if ((psm & 0x0101) != 0x0001) {
1027 err = -EINVAL;
1028 goto done;
1029 }
1030
1031 /* Restrict usage of well-known PSMs */
1032 if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
1033 err = -EACCES;
1034 goto done;
1035 }
Marcel Holtmann847641d2007-01-22 22:00:45 +01001036 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 write_lock_bh(&l2cap_sk_list.lock);
1039
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001040 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 err = -EADDRINUSE;
1042 } else {
1043 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001044 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
1045 l2cap_pi(sk)->psm = la.l2_psm;
1046 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001048
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001049 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
1050 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001051 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 }
1053
1054 write_unlock_bh(&l2cap_sk_list.lock);
1055
1056done:
1057 release_sock(sk);
1058 return err;
1059}
1060
1061static int l2cap_do_connect(struct sock *sk)
1062{
1063 bdaddr_t *src = &bt_sk(sk)->src;
1064 bdaddr_t *dst = &bt_sk(sk)->dst;
1065 struct l2cap_conn *conn;
1066 struct hci_conn *hcon;
1067 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001068 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001069 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001071 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
1072 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001074 hdev = hci_get_route(dst, src);
1075 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 return -EHOSTUNREACH;
1077
1078 hci_dev_lock_bh(hdev);
1079
1080 err = -ENOMEM;
1081
Johan Hedberg8556edd32011-01-19 12:06:50 +05301082 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001083
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001084 hcon = hci_connect(hdev, ACL_LINK, dst,
1085 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (!hcon)
1087 goto done;
1088
1089 conn = l2cap_conn_add(hcon, 0);
1090 if (!conn) {
1091 hci_conn_put(hcon);
1092 goto done;
1093 }
1094
1095 err = 0;
1096
1097 /* Update source addr of the socket */
1098 bacpy(src, conn->src);
1099
1100 l2cap_chan_add(conn, sk, NULL);
1101
1102 sk->sk_state = BT_CONNECT;
1103 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1104
1105 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001106 if (sk->sk_type != SOCK_SEQPACKET &&
1107 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +05301109 if (l2cap_check_security(sk))
1110 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001111 } else
1112 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
1114
1115done:
1116 hci_dev_unlock_bh(hdev);
1117 hci_dev_put(hdev);
1118 return err;
1119}
1120
1121static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
1122{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001124 struct sockaddr_l2 la;
1125 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 BT_DBG("sk %p", sk);
1128
Changli Gao6503d962010-03-31 22:58:26 +00001129 if (!addr || alen < sizeof(addr->sa_family) ||
1130 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001131 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001133 memset(&la, 0, sizeof(la));
1134 len = min_t(unsigned int, sizeof(la), alen);
1135 memcpy(&la, addr, len);
1136
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001137 if (la.l2_cid)
1138 return -EINVAL;
1139
1140 lock_sock(sk);
1141
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001142 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
1143 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 err = -EINVAL;
1145 goto done;
1146 }
1147
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001148 switch (l2cap_pi(sk)->mode) {
1149 case L2CAP_MODE_BASIC:
1150 break;
1151 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001152 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001153 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001154 break;
1155 /* fall through */
1156 default:
1157 err = -ENOTSUPP;
1158 goto done;
1159 }
1160
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001161 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 case BT_CONNECT:
1163 case BT_CONNECT2:
1164 case BT_CONFIG:
1165 /* Already connecting */
1166 goto wait;
1167
1168 case BT_CONNECTED:
1169 /* Already connected */
João Paulo Rechi Vita8b0dc6d2010-06-22 13:56:22 -03001170 err = -EISCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 goto done;
1172
1173 case BT_OPEN:
1174 case BT_BOUND:
1175 /* Can connect */
1176 break;
1177
1178 default:
1179 err = -EBADFD;
1180 goto done;
1181 }
1182
Mat Martineau0fba2552010-09-08 10:05:26 -07001183 /* PSM must be odd and lsb of upper byte must be 0 */
1184 if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
1185 sk->sk_type != SOCK_RAW) {
1186 err = -EINVAL;
1187 goto done;
1188 }
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001191 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1192 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001194 err = l2cap_do_connect(sk);
1195 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 goto done;
1197
1198wait:
1199 err = bt_sock_wait_state(sk, BT_CONNECTED,
1200 sock_sndtimeo(sk, flags & O_NONBLOCK));
1201done:
1202 release_sock(sk);
1203 return err;
1204}
1205
1206static int l2cap_sock_listen(struct socket *sock, int backlog)
1207{
1208 struct sock *sk = sock->sk;
1209 int err = 0;
1210
1211 BT_DBG("sk %p backlog %d", sk, backlog);
1212
1213 lock_sock(sk);
1214
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001215 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1216 || sk->sk_state != BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 err = -EBADFD;
1218 goto done;
1219 }
1220
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001221 switch (l2cap_pi(sk)->mode) {
1222 case L2CAP_MODE_BASIC:
1223 break;
1224 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001225 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001226 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001227 break;
1228 /* fall through */
1229 default:
1230 err = -ENOTSUPP;
1231 goto done;
1232 }
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 if (!l2cap_pi(sk)->psm) {
1235 bdaddr_t *src = &bt_sk(sk)->src;
1236 u16 psm;
1237
1238 err = -EINVAL;
1239
1240 write_lock_bh(&l2cap_sk_list.lock);
1241
1242 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001243 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1244 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1245 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 err = 0;
1247 break;
1248 }
1249
1250 write_unlock_bh(&l2cap_sk_list.lock);
1251
1252 if (err < 0)
1253 goto done;
1254 }
1255
1256 sk->sk_max_ack_backlog = backlog;
1257 sk->sk_ack_backlog = 0;
1258 sk->sk_state = BT_LISTEN;
1259
1260done:
1261 release_sock(sk);
1262 return err;
1263}
1264
1265static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
1266{
1267 DECLARE_WAITQUEUE(wait, current);
1268 struct sock *sk = sock->sk, *nsk;
1269 long timeo;
1270 int err = 0;
1271
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001272 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 if (sk->sk_state != BT_LISTEN) {
1275 err = -EBADFD;
1276 goto done;
1277 }
1278
1279 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1280
1281 BT_DBG("sk %p timeo %ld", sk, timeo);
1282
1283 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001284 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1286 set_current_state(TASK_INTERRUPTIBLE);
1287 if (!timeo) {
1288 err = -EAGAIN;
1289 break;
1290 }
1291
1292 release_sock(sk);
1293 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001294 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296 if (sk->sk_state != BT_LISTEN) {
1297 err = -EBADFD;
1298 break;
1299 }
1300
1301 if (signal_pending(current)) {
1302 err = sock_intr_errno(timeo);
1303 break;
1304 }
1305 }
1306 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001307 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
1309 if (err)
1310 goto done;
1311
1312 newsock->state = SS_CONNECTED;
1313
1314 BT_DBG("new socket %p", nsk);
1315
1316done:
1317 release_sock(sk);
1318 return err;
1319}
1320
1321static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
1322{
1323 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1324 struct sock *sk = sock->sk;
1325
1326 BT_DBG("sock %p, sk %p", sock, sk);
1327
1328 addr->sa_family = AF_BLUETOOTH;
1329 *len = sizeof(struct sockaddr_l2);
1330
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001331 if (peer) {
1332 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001334 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001335 } else {
1336 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001338 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return 0;
1342}
1343
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001344static int __l2cap_wait_ack(struct sock *sk)
1345{
1346 DECLARE_WAITQUEUE(wait, current);
1347 int err = 0;
1348 int timeo = HZ/5;
1349
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001350 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001351 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
1352 set_current_state(TASK_INTERRUPTIBLE);
1353
1354 if (!timeo)
1355 timeo = HZ/5;
1356
1357 if (signal_pending(current)) {
1358 err = sock_intr_errno(timeo);
1359 break;
1360 }
1361
1362 release_sock(sk);
1363 timeo = schedule_timeout(timeo);
1364 lock_sock(sk);
1365
1366 err = sock_error(sk);
1367 if (err)
1368 break;
1369 }
1370 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001371 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001372 return err;
1373}
1374
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001375static void l2cap_monitor_timeout(unsigned long arg)
1376{
1377 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001378
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001379 BT_DBG("sk %p", sk);
1380
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001381 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001382 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001383 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001384 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001385 return;
1386 }
1387
1388 l2cap_pi(sk)->retry_count++;
1389 __mod_monitor_timer();
1390
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001391 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001392 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001393}
1394
1395static void l2cap_retrans_timeout(unsigned long arg)
1396{
1397 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001398
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001399 BT_DBG("sk %p", sk);
1400
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001401 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001402 l2cap_pi(sk)->retry_count = 1;
1403 __mod_monitor_timer();
1404
1405 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1406
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001407 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001408 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001409}
1410
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001411static void l2cap_drop_acked_frames(struct sock *sk)
1412{
1413 struct sk_buff *skb;
1414
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001415 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1416 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001417 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1418 break;
1419
1420 skb = skb_dequeue(TX_QUEUE(sk));
1421 kfree_skb(skb);
1422
1423 l2cap_pi(sk)->unacked_frames--;
1424 }
1425
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001426 if (!l2cap_pi(sk)->unacked_frames)
1427 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428}
1429
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001430static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001431{
1432 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433
1434 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1435
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001436 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437}
1438
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001439static void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001440{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001441 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001442 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001443 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001444
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001445 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1446 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001447 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001448 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001449
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001450 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001451 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1452 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001453 }
1454
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001455 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001456
1457 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001458 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001459}
1460
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001461static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001462{
1463 struct l2cap_pinfo *pi = l2cap_pi(sk);
1464 struct sk_buff *skb, *tx_skb;
1465 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001466
1467 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001468 if (!skb)
1469 return;
1470
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001471 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001472 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001473 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001474
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001475 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1476 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001477
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001478 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001479
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001480 if (pi->remote_max_tx &&
1481 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001482 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001483 return;
1484 }
1485
1486 tx_skb = skb_clone(skb, GFP_ATOMIC);
1487 bt_cb(skb)->retries++;
1488 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001489
1490 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1491 control |= L2CAP_CTRL_FINAL;
1492 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1493 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001494
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001495 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1496 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001497
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001498 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1499
1500 if (pi->fcs == L2CAP_FCS_CRC16) {
1501 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1502 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1503 }
1504
1505 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001506}
1507
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001508static int l2cap_ertm_send(struct sock *sk)
1509{
1510 struct sk_buff *skb, *tx_skb;
1511 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001512 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001513 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001514
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001515 if (sk->sk_state != BT_CONNECTED)
1516 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001517
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001518 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001519
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001520 if (pi->remote_max_tx &&
1521 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001522 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001523 break;
1524 }
1525
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001526 tx_skb = skb_clone(skb, GFP_ATOMIC);
1527
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001528 bt_cb(skb)->retries++;
1529
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001531 control &= L2CAP_CTRL_SAR;
1532
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001533 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1534 control |= L2CAP_CTRL_FINAL;
1535 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1536 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001537 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001538 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1539 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1540
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001541
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001542 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001543 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1544 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1545 }
1546
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001547 l2cap_do_send(sk, tx_skb);
1548
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001549 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550
1551 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1552 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1553
1554 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001555 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556
1557 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1558 sk->sk_send_head = NULL;
1559 else
1560 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001561
1562 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563 }
1564
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001565 return nsent;
1566}
1567
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001568static int l2cap_retransmit_frames(struct sock *sk)
1569{
1570 struct l2cap_pinfo *pi = l2cap_pi(sk);
1571 int ret;
1572
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001573 if (!skb_queue_empty(TX_QUEUE(sk)))
1574 sk->sk_send_head = TX_QUEUE(sk)->next;
1575
1576 pi->next_tx_seq = pi->expected_ack_seq;
1577 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001578 return ret;
1579}
1580
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001581static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001582{
1583 struct sock *sk = (struct sock *)pi;
1584 u16 control = 0;
1585
1586 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1587
1588 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1589 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001590 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001591 l2cap_send_sframe(pi, control);
1592 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001593 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001594
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001595 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001596 return;
1597
1598 control |= L2CAP_SUPER_RCV_READY;
1599 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001600}
1601
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001602static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001603{
1604 struct srej_list *tail;
1605 u16 control;
1606
1607 control = L2CAP_SUPER_SELECT_REJECT;
1608 control |= L2CAP_CTRL_FINAL;
1609
1610 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1611 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1612
1613 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001614}
1615
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001616static 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 -07001617{
1618 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001619 struct sk_buff **frag;
1620 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001622 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001623 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
1625 sent += count;
1626 len -= count;
1627
1628 /* Continuation fragments (no L2CAP header) */
1629 frag = &skb_shinfo(skb)->frag_list;
1630 while (len) {
1631 count = min_t(unsigned int, conn->mtu, len);
1632
1633 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1634 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001635 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001636 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1637 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
1639 sent += count;
1640 len -= count;
1641
1642 frag = &(*frag)->next;
1643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001646}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001648static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1649{
1650 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1651 struct sk_buff *skb;
1652 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1653 struct l2cap_hdr *lh;
1654
1655 BT_DBG("sk %p len %d", sk, (int)len);
1656
1657 count = min_t(unsigned int, (conn->mtu - hlen), len);
1658 skb = bt_skb_send_alloc(sk, count + hlen,
1659 msg->msg_flags & MSG_DONTWAIT, &err);
1660 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001661 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001662
1663 /* Create L2CAP header */
1664 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1665 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1666 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1667 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1668
1669 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1670 if (unlikely(err < 0)) {
1671 kfree_skb(skb);
1672 return ERR_PTR(err);
1673 }
1674 return skb;
1675}
1676
1677static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1678{
1679 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1680 struct sk_buff *skb;
1681 int err, count, hlen = L2CAP_HDR_SIZE;
1682 struct l2cap_hdr *lh;
1683
1684 BT_DBG("sk %p len %d", sk, (int)len);
1685
1686 count = min_t(unsigned int, (conn->mtu - hlen), len);
1687 skb = bt_skb_send_alloc(sk, count + hlen,
1688 msg->msg_flags & MSG_DONTWAIT, &err);
1689 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001690 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001691
1692 /* Create L2CAP header */
1693 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1694 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1695 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1696
1697 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1698 if (unlikely(err < 0)) {
1699 kfree_skb(skb);
1700 return ERR_PTR(err);
1701 }
1702 return skb;
1703}
1704
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001705static 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 -03001706{
1707 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1708 struct sk_buff *skb;
1709 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1710 struct l2cap_hdr *lh;
1711
1712 BT_DBG("sk %p len %d", sk, (int)len);
1713
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001714 if (!conn)
1715 return ERR_PTR(-ENOTCONN);
1716
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001717 if (sdulen)
1718 hlen += 2;
1719
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001720 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1721 hlen += 2;
1722
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001723 count = min_t(unsigned int, (conn->mtu - hlen), len);
1724 skb = bt_skb_send_alloc(sk, count + hlen,
1725 msg->msg_flags & MSG_DONTWAIT, &err);
1726 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001727 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001728
1729 /* Create L2CAP header */
1730 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1731 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1732 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1733 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001734 if (sdulen)
1735 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001736
1737 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1738 if (unlikely(err < 0)) {
1739 kfree_skb(skb);
1740 return ERR_PTR(err);
1741 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001742
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001743 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1744 put_unaligned_le16(0, skb_put(skb, 2));
1745
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001746 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001747 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748}
1749
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001750static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1751{
1752 struct l2cap_pinfo *pi = l2cap_pi(sk);
1753 struct sk_buff *skb;
1754 struct sk_buff_head sar_queue;
1755 u16 control;
1756 size_t size = 0;
1757
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001758 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001759 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001760 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001761 if (IS_ERR(skb))
1762 return PTR_ERR(skb);
1763
1764 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001765 len -= pi->remote_mps;
1766 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001767
1768 while (len > 0) {
1769 size_t buflen;
1770
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001771 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001772 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001773 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001774 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001775 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001776 buflen = len;
1777 }
1778
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001779 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001780 if (IS_ERR(skb)) {
1781 skb_queue_purge(&sar_queue);
1782 return PTR_ERR(skb);
1783 }
1784
1785 __skb_queue_tail(&sar_queue, skb);
1786 len -= buflen;
1787 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001788 }
1789 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1790 if (sk->sk_send_head == NULL)
1791 sk->sk_send_head = sar_queue.next;
1792
1793 return size;
1794}
1795
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
1797{
1798 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001799 struct l2cap_pinfo *pi = l2cap_pi(sk);
1800 struct sk_buff *skb;
1801 u16 control;
1802 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
1804 BT_DBG("sock %p, sk %p", sock, sk);
1805
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001806 err = sock_error(sk);
1807 if (err)
1808 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
1810 if (msg->msg_flags & MSG_OOB)
1811 return -EOPNOTSUPP;
1812
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 lock_sock(sk);
1814
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001815 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001817 goto done;
1818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001820 /* Connectionless channel */
1821 if (sk->sk_type == SOCK_DGRAM) {
1822 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001823 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001824 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001825 } else {
1826 l2cap_do_send(sk, skb);
1827 err = len;
1828 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001829 goto done;
1830 }
1831
1832 switch (pi->mode) {
1833 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001834 /* Check outgoing MTU */
1835 if (len > pi->omtu) {
João Paulo Rechi Vitaf9dd11b2010-06-22 13:56:24 -03001836 err = -EMSGSIZE;
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001837 goto done;
1838 }
1839
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001840 /* Create a basic PDU */
1841 skb = l2cap_create_basic_pdu(sk, msg, len);
1842 if (IS_ERR(skb)) {
1843 err = PTR_ERR(skb);
1844 goto done;
1845 }
1846
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001847 l2cap_do_send(sk, skb);
1848 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001849 break;
1850
1851 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001852 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001853 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001854 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001855 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001856 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001857 if (IS_ERR(skb)) {
1858 err = PTR_ERR(skb);
1859 goto done;
1860 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001861 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001862
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001863 if (sk->sk_send_head == NULL)
1864 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001865
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001866 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001867 /* Segment SDU into multiples PDUs */
1868 err = l2cap_sar_segment_sdu(sk, msg, len);
1869 if (err < 0)
1870 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001871 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001872
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001873 if (pi->mode == L2CAP_MODE_STREAMING) {
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001874 l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001875 } else {
David Sterba45719282011-01-14 14:59:44 +01001876 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1877 (pi->conn_state & L2CAP_CONN_WAIT_F)) {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001878 err = len;
1879 break;
1880 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001881 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001882 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001883
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001884 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001885 err = len;
1886 break;
1887
1888 default:
1889 BT_DBG("bad state %1.1x", pi->mode);
João Paulo Rechi Vitabc766db22010-06-22 13:56:25 -03001890 err = -EBADFD;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001891 }
1892
1893done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 release_sock(sk);
1895 return err;
1896}
1897
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001898static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1899{
1900 struct sock *sk = sock->sk;
1901
1902 lock_sock(sk);
1903
1904 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1905 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001906 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1907 u8 buf[128];
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001908
1909 sk->sk_state = BT_CONFIG;
1910
1911 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1912 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1913 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1914 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1915 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1916 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1917
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001918 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
1919 release_sock(sk);
1920 return 0;
1921 }
1922
1923 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1924 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1925 l2cap_build_conf_req(sk, buf), buf);
1926 l2cap_pi(sk)->num_conf_req++;
1927
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001928 release_sock(sk);
1929 return 0;
1930 }
1931
1932 release_sock(sk);
1933
Mat Martineau6fdf4822010-09-08 10:05:29 -07001934 if (sock->type == SOCK_STREAM)
1935 return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
1936
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001937 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1938}
1939
David S. Millerb7058842009-09-30 16:12:20 -07001940static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
1942 struct sock *sk = sock->sk;
1943 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001944 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 u32 opt;
1946
1947 BT_DBG("sk %p", sk);
1948
1949 lock_sock(sk);
1950
1951 switch (optname) {
1952 case L2CAP_OPTIONS:
Gustavo F. Padovaneaa71b32010-10-04 19:28:52 -03001953 if (sk->sk_state == BT_CONNECTED) {
1954 err = -EINVAL;
1955 break;
1956 }
1957
Marcel Holtmann0878b662007-05-05 00:35:59 +02001958 opts.imtu = l2cap_pi(sk)->imtu;
1959 opts.omtu = l2cap_pi(sk)->omtu;
1960 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001961 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001962 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001963 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001964 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001965
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 len = min_t(unsigned int, sizeof(opts), optlen);
1967 if (copy_from_user((char *) &opts, optval, len)) {
1968 err = -EFAULT;
1969 break;
1970 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001971
Gustavo F. Padovan45d65c42010-06-07 19:21:30 -03001972 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
1973 err = -EINVAL;
1974 break;
1975 }
1976
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001977 l2cap_pi(sk)->mode = opts.mode;
1978 switch (l2cap_pi(sk)->mode) {
1979 case L2CAP_MODE_BASIC:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001980 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001981 break;
1982 case L2CAP_MODE_ERTM:
1983 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001984 if (!disable_ertm)
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001985 break;
1986 /* fall through */
1987 default:
1988 err = -EINVAL;
1989 break;
1990 }
1991
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001992 l2cap_pi(sk)->imtu = opts.imtu;
1993 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001994 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001995 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001996 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 break;
1998
1999 case L2CAP_LM:
2000 if (get_user(opt, (u32 __user *) optval)) {
2001 err = -EFAULT;
2002 break;
2003 }
2004
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002005 if (opt & L2CAP_LM_AUTH)
2006 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
2007 if (opt & L2CAP_LM_ENCRYPT)
2008 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
2009 if (opt & L2CAP_LM_SECURE)
2010 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
2011
2012 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
2013 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 break;
2015
2016 default:
2017 err = -ENOPROTOOPT;
2018 break;
2019 }
2020
2021 release_sock(sk);
2022 return err;
2023}
2024
David S. Millerb7058842009-09-30 16:12:20 -07002025static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002026{
2027 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002028 struct bt_security sec;
2029 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002030 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002031
2032 BT_DBG("sk %p", sk);
2033
2034 if (level == SOL_L2CAP)
2035 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
2036
Marcel Holtmann0588d942009-01-16 10:06:13 +01002037 if (level != SOL_BLUETOOTH)
2038 return -ENOPROTOOPT;
2039
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002040 lock_sock(sk);
2041
2042 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002043 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002044 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2045 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002046 err = -EINVAL;
2047 break;
2048 }
2049
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002050 sec.level = BT_SECURITY_LOW;
2051
2052 len = min_t(unsigned int, sizeof(sec), optlen);
2053 if (copy_from_user((char *) &sec, optval, len)) {
2054 err = -EFAULT;
2055 break;
2056 }
2057
2058 if (sec.level < BT_SECURITY_LOW ||
2059 sec.level > BT_SECURITY_HIGH) {
2060 err = -EINVAL;
2061 break;
2062 }
2063
2064 l2cap_pi(sk)->sec_level = sec.level;
2065 break;
2066
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002067 case BT_DEFER_SETUP:
2068 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2069 err = -EINVAL;
2070 break;
2071 }
2072
2073 if (get_user(opt, (u32 __user *) optval)) {
2074 err = -EFAULT;
2075 break;
2076 }
2077
2078 bt_sk(sk)->defer_setup = opt;
2079 break;
2080
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002081 default:
2082 err = -ENOPROTOOPT;
2083 break;
2084 }
2085
2086 release_sock(sk);
2087 return err;
2088}
2089
2090static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091{
2092 struct sock *sk = sock->sk;
2093 struct l2cap_options opts;
2094 struct l2cap_conninfo cinfo;
2095 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002096 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
2098 BT_DBG("sk %p", sk);
2099
2100 if (get_user(len, optlen))
2101 return -EFAULT;
2102
2103 lock_sock(sk);
2104
2105 switch (optname) {
2106 case L2CAP_OPTIONS:
2107 opts.imtu = l2cap_pi(sk)->imtu;
2108 opts.omtu = l2cap_pi(sk)->omtu;
2109 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07002110 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002111 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002112 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002113 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
2115 len = min_t(unsigned int, len, sizeof(opts));
2116 if (copy_to_user(optval, (char *) &opts, len))
2117 err = -EFAULT;
2118
2119 break;
2120
2121 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002122 switch (l2cap_pi(sk)->sec_level) {
2123 case BT_SECURITY_LOW:
2124 opt = L2CAP_LM_AUTH;
2125 break;
2126 case BT_SECURITY_MEDIUM:
2127 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
2128 break;
2129 case BT_SECURITY_HIGH:
2130 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
2131 L2CAP_LM_SECURE;
2132 break;
2133 default:
2134 opt = 0;
2135 break;
2136 }
2137
2138 if (l2cap_pi(sk)->role_switch)
2139 opt |= L2CAP_LM_MASTER;
2140
2141 if (l2cap_pi(sk)->force_reliable)
2142 opt |= L2CAP_LM_RELIABLE;
2143
2144 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 err = -EFAULT;
2146 break;
2147
2148 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002149 if (sk->sk_state != BT_CONNECTED &&
2150 !(sk->sk_state == BT_CONNECT2 &&
2151 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 err = -ENOTCONN;
2153 break;
2154 }
2155
2156 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
2157 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
2158
2159 len = min_t(unsigned int, len, sizeof(cinfo));
2160 if (copy_to_user(optval, (char *) &cinfo, len))
2161 err = -EFAULT;
2162
2163 break;
2164
2165 default:
2166 err = -ENOPROTOOPT;
2167 break;
2168 }
2169
2170 release_sock(sk);
2171 return err;
2172}
2173
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002174static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
2175{
2176 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002177 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002178 int len, err = 0;
2179
2180 BT_DBG("sk %p", sk);
2181
2182 if (level == SOL_L2CAP)
2183 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
2184
Marcel Holtmann0588d942009-01-16 10:06:13 +01002185 if (level != SOL_BLUETOOTH)
2186 return -ENOPROTOOPT;
2187
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002188 if (get_user(len, optlen))
2189 return -EFAULT;
2190
2191 lock_sock(sk);
2192
2193 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002194 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002195 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2196 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002197 err = -EINVAL;
2198 break;
2199 }
2200
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002201 sec.level = l2cap_pi(sk)->sec_level;
2202
2203 len = min_t(unsigned int, len, sizeof(sec));
2204 if (copy_to_user(optval, (char *) &sec, len))
2205 err = -EFAULT;
2206
2207 break;
2208
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002209 case BT_DEFER_SETUP:
2210 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2211 err = -EINVAL;
2212 break;
2213 }
2214
2215 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
2216 err = -EFAULT;
2217
2218 break;
2219
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002220 default:
2221 err = -ENOPROTOOPT;
2222 break;
2223 }
2224
2225 release_sock(sk);
2226 return err;
2227}
2228
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229static int l2cap_sock_shutdown(struct socket *sock, int how)
2230{
2231 struct sock *sk = sock->sk;
2232 int err = 0;
2233
2234 BT_DBG("sock %p, sk %p", sock, sk);
2235
2236 if (!sk)
2237 return 0;
2238
2239 lock_sock(sk);
2240 if (!sk->sk_shutdown) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03002241 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2242 err = __l2cap_wait_ack(sk);
2243
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 sk->sk_shutdown = SHUTDOWN_MASK;
2245 l2cap_sock_clear_timer(sk);
2246 __l2cap_sock_close(sk, 0);
2247
2248 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002249 err = bt_sock_wait_state(sk, BT_CLOSED,
2250 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 }
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002252
2253 if (!err && sk->sk_err)
2254 err = -sk->sk_err;
2255
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 release_sock(sk);
2257 return err;
2258}
2259
2260static int l2cap_sock_release(struct socket *sock)
2261{
2262 struct sock *sk = sock->sk;
2263 int err;
2264
2265 BT_DBG("sock %p, sk %p", sock, sk);
2266
2267 if (!sk)
2268 return 0;
2269
2270 err = l2cap_sock_shutdown(sock, 2);
2271
2272 sock_orphan(sk);
2273 l2cap_sock_kill(sk);
2274 return err;
2275}
2276
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277static void l2cap_chan_ready(struct sock *sk)
2278{
2279 struct sock *parent = bt_sk(sk)->parent;
2280
2281 BT_DBG("sk %p, parent %p", sk, parent);
2282
2283 l2cap_pi(sk)->conf_state = 0;
2284 l2cap_sock_clear_timer(sk);
2285
2286 if (!parent) {
2287 /* Outgoing channel.
2288 * Wake up socket sleeping on connect.
2289 */
2290 sk->sk_state = BT_CONNECTED;
2291 sk->sk_state_change(sk);
2292 } else {
2293 /* Incoming channel.
2294 * Wake up socket sleeping on accept.
2295 */
2296 parent->sk_data_ready(parent, 0);
2297 }
2298}
2299
2300/* Copy frame to all raw sockets on that connection */
2301static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2302{
2303 struct l2cap_chan_list *l = &conn->chan_list;
2304 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002305 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
2307 BT_DBG("conn %p", conn);
2308
2309 read_lock(&l->lock);
2310 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2311 if (sk->sk_type != SOCK_RAW)
2312 continue;
2313
2314 /* Don't send frame to the socket it came from */
2315 if (skb->sk == sk)
2316 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002317 nskb = skb_clone(skb, GFP_ATOMIC);
2318 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 continue;
2320
2321 if (sock_queue_rcv_skb(sk, nskb))
2322 kfree_skb(nskb);
2323 }
2324 read_unlock(&l->lock);
2325}
2326
2327/* ---- L2CAP signalling commands ---- */
2328static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2329 u8 code, u8 ident, u16 dlen, void *data)
2330{
2331 struct sk_buff *skb, **frag;
2332 struct l2cap_cmd_hdr *cmd;
2333 struct l2cap_hdr *lh;
2334 int len, count;
2335
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002336 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2337 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
2339 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2340 count = min_t(unsigned int, conn->mtu, len);
2341
2342 skb = bt_skb_alloc(count, GFP_ATOMIC);
2343 if (!skb)
2344 return NULL;
2345
2346 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002347 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002348 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
2350 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2351 cmd->code = code;
2352 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002353 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354
2355 if (dlen) {
2356 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2357 memcpy(skb_put(skb, count), data, count);
2358 data += count;
2359 }
2360
2361 len -= skb->len;
2362
2363 /* Continuation fragments (no L2CAP header) */
2364 frag = &skb_shinfo(skb)->frag_list;
2365 while (len) {
2366 count = min_t(unsigned int, conn->mtu, len);
2367
2368 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2369 if (!*frag)
2370 goto fail;
2371
2372 memcpy(skb_put(*frag, count), data, count);
2373
2374 len -= count;
2375 data += count;
2376
2377 frag = &(*frag)->next;
2378 }
2379
2380 return skb;
2381
2382fail:
2383 kfree_skb(skb);
2384 return NULL;
2385}
2386
2387static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2388{
2389 struct l2cap_conf_opt *opt = *ptr;
2390 int len;
2391
2392 len = L2CAP_CONF_OPT_SIZE + opt->len;
2393 *ptr += len;
2394
2395 *type = opt->type;
2396 *olen = opt->len;
2397
2398 switch (opt->len) {
2399 case 1:
2400 *val = *((u8 *) opt->val);
2401 break;
2402
2403 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002404 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 break;
2406
2407 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002408 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 break;
2410
2411 default:
2412 *val = (unsigned long) opt->val;
2413 break;
2414 }
2415
2416 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2417 return len;
2418}
2419
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2421{
2422 struct l2cap_conf_opt *opt = *ptr;
2423
2424 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2425
2426 opt->type = type;
2427 opt->len = len;
2428
2429 switch (len) {
2430 case 1:
2431 *((u8 *) opt->val) = val;
2432 break;
2433
2434 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002435 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 break;
2437
2438 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002439 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 break;
2441
2442 default:
2443 memcpy(opt->val, (void *) val, len);
2444 break;
2445 }
2446
2447 *ptr += L2CAP_CONF_OPT_SIZE + len;
2448}
2449
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002450static void l2cap_ack_timeout(unsigned long arg)
2451{
2452 struct sock *sk = (void *) arg;
2453
2454 bh_lock_sock(sk);
2455 l2cap_send_ack(l2cap_pi(sk));
2456 bh_unlock_sock(sk);
2457}
2458
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002459static inline void l2cap_ertm_init(struct sock *sk)
2460{
2461 l2cap_pi(sk)->expected_ack_seq = 0;
2462 l2cap_pi(sk)->unacked_frames = 0;
2463 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002464 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002465 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002466
2467 setup_timer(&l2cap_pi(sk)->retrans_timer,
2468 l2cap_retrans_timeout, (unsigned long) sk);
2469 setup_timer(&l2cap_pi(sk)->monitor_timer,
2470 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002471 setup_timer(&l2cap_pi(sk)->ack_timer,
2472 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002473
2474 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002475 __skb_queue_head_init(BUSY_QUEUE(sk));
2476
2477 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03002478
2479 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002480}
2481
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002482static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2483{
2484 switch (mode) {
2485 case L2CAP_MODE_STREAMING:
2486 case L2CAP_MODE_ERTM:
2487 if (l2cap_mode_supported(mode, remote_feat_mask))
2488 return mode;
2489 /* fall through */
2490 default:
2491 return L2CAP_MODE_BASIC;
2492 }
2493}
2494
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495static int l2cap_build_conf_req(struct sock *sk, void *data)
2496{
2497 struct l2cap_pinfo *pi = l2cap_pi(sk);
2498 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002499 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 void *ptr = req->data;
2501
2502 BT_DBG("sk %p", sk);
2503
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002504 if (pi->num_conf_req || pi->num_conf_rsp)
2505 goto done;
2506
2507 switch (pi->mode) {
2508 case L2CAP_MODE_STREAMING:
2509 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002510 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002511 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002512
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002513 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002514 default:
2515 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2516 break;
2517 }
2518
2519done:
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002520 switch (pi->mode) {
2521 case L2CAP_MODE_BASIC:
2522 if (pi->imtu != L2CAP_DEFAULT_MTU)
2523 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002524
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002525 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2526 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
2527 break;
2528
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002529 rfc.mode = L2CAP_MODE_BASIC;
2530 rfc.txwin_size = 0;
2531 rfc.max_transmit = 0;
2532 rfc.retrans_timeout = 0;
2533 rfc.monitor_timeout = 0;
2534 rfc.max_pdu_size = 0;
2535
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002536 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2537 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002538 break;
2539
2540 case L2CAP_MODE_ERTM:
2541 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002542 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002543 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002544 rfc.retrans_timeout = 0;
2545 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002546 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002547 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002548 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002549
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002550 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2551 (unsigned long) &rfc);
2552
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002553 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2554 break;
2555
2556 if (pi->fcs == L2CAP_FCS_NONE ||
2557 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2558 pi->fcs = L2CAP_FCS_NONE;
2559 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2560 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002561 break;
2562
2563 case L2CAP_MODE_STREAMING:
2564 rfc.mode = L2CAP_MODE_STREAMING;
2565 rfc.txwin_size = 0;
2566 rfc.max_transmit = 0;
2567 rfc.retrans_timeout = 0;
2568 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002569 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002570 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002571 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002572
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002573 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2574 (unsigned long) &rfc);
2575
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002576 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2577 break;
2578
2579 if (pi->fcs == L2CAP_FCS_NONE ||
2580 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2581 pi->fcs = L2CAP_FCS_NONE;
2582 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2583 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002584 break;
2585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
2587 /* FIXME: Need actual value of the flush timeout */
2588 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2589 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2590
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002591 req->dcid = cpu_to_le16(pi->dcid);
2592 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
2594 return ptr - data;
2595}
2596
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002597static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598{
2599 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002600 struct l2cap_conf_rsp *rsp = data;
2601 void *ptr = rsp->data;
2602 void *req = pi->conf_req;
2603 int len = pi->conf_len;
2604 int type, hint, olen;
2605 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002606 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002607 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002608 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002610 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002611
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002612 while (len >= L2CAP_CONF_OPT_SIZE) {
2613 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002615 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002616 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002617
2618 switch (type) {
2619 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002620 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002621 break;
2622
2623 case L2CAP_CONF_FLUSH_TO:
2624 pi->flush_to = val;
2625 break;
2626
2627 case L2CAP_CONF_QOS:
2628 break;
2629
Marcel Holtmann6464f352007-10-20 13:39:51 +02002630 case L2CAP_CONF_RFC:
2631 if (olen == sizeof(rfc))
2632 memcpy(&rfc, (void *) val, olen);
2633 break;
2634
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002635 case L2CAP_CONF_FCS:
2636 if (val == L2CAP_FCS_NONE)
2637 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2638
2639 break;
2640
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002641 default:
2642 if (hint)
2643 break;
2644
2645 result = L2CAP_CONF_UNKNOWN;
2646 *((u8 *) ptr++) = type;
2647 break;
2648 }
2649 }
2650
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002651 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002652 goto done;
2653
2654 switch (pi->mode) {
2655 case L2CAP_MODE_STREAMING:
2656 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002657 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
2658 pi->mode = l2cap_select_mode(rfc.mode,
2659 pi->conn->feat_mask);
2660 break;
2661 }
2662
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002663 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002664 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002665
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002666 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002667 }
2668
2669done:
2670 if (pi->mode != rfc.mode) {
2671 result = L2CAP_CONF_UNACCEPT;
2672 rfc.mode = pi->mode;
2673
2674 if (pi->num_conf_rsp == 1)
2675 return -ECONNREFUSED;
2676
2677 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2678 sizeof(rfc), (unsigned long) &rfc);
2679 }
2680
2681
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002682 if (result == L2CAP_CONF_SUCCESS) {
2683 /* Configure output options and let the other side know
2684 * which ones we don't like. */
2685
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002686 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2687 result = L2CAP_CONF_UNACCEPT;
2688 else {
2689 pi->omtu = mtu;
2690 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2691 }
2692 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002693
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002694 switch (rfc.mode) {
2695 case L2CAP_MODE_BASIC:
2696 pi->fcs = L2CAP_FCS_NONE;
2697 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2698 break;
2699
2700 case L2CAP_MODE_ERTM:
2701 pi->remote_tx_win = rfc.txwin_size;
2702 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002703
2704 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2705 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002706
2707 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002708
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002709 rfc.retrans_timeout =
2710 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2711 rfc.monitor_timeout =
2712 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002713
2714 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002715
2716 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2717 sizeof(rfc), (unsigned long) &rfc);
2718
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002719 break;
2720
2721 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07002722 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2723 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002724
2725 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002726
2727 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002728
2729 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2730 sizeof(rfc), (unsigned long) &rfc);
2731
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002732 break;
2733
2734 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002735 result = L2CAP_CONF_UNACCEPT;
2736
2737 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002738 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002739 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002740
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002741 if (result == L2CAP_CONF_SUCCESS)
2742 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2743 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002744 rsp->scid = cpu_to_le16(pi->dcid);
2745 rsp->result = cpu_to_le16(result);
2746 rsp->flags = cpu_to_le16(0x0000);
2747
2748 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749}
2750
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002751static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2752{
2753 struct l2cap_pinfo *pi = l2cap_pi(sk);
2754 struct l2cap_conf_req *req = data;
2755 void *ptr = req->data;
2756 int type, olen;
2757 unsigned long val;
2758 struct l2cap_conf_rfc rfc;
2759
2760 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2761
2762 while (len >= L2CAP_CONF_OPT_SIZE) {
2763 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2764
2765 switch (type) {
2766 case L2CAP_CONF_MTU:
2767 if (val < L2CAP_DEFAULT_MIN_MTU) {
2768 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002769 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002770 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002771 pi->imtu = val;
2772 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002773 break;
2774
2775 case L2CAP_CONF_FLUSH_TO:
2776 pi->flush_to = val;
2777 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2778 2, pi->flush_to);
2779 break;
2780
2781 case L2CAP_CONF_RFC:
2782 if (olen == sizeof(rfc))
2783 memcpy(&rfc, (void *)val, olen);
2784
2785 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2786 rfc.mode != pi->mode)
2787 return -ECONNREFUSED;
2788
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002789 pi->fcs = 0;
2790
2791 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2792 sizeof(rfc), (unsigned long) &rfc);
2793 break;
2794 }
2795 }
2796
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002797 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
2798 return -ECONNREFUSED;
2799
2800 pi->mode = rfc.mode;
2801
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002802 if (*result == L2CAP_CONF_SUCCESS) {
2803 switch (rfc.mode) {
2804 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002805 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2806 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002807 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002808 break;
2809 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002810 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002811 }
2812 }
2813
2814 req->dcid = cpu_to_le16(pi->dcid);
2815 req->flags = cpu_to_le16(0x0000);
2816
2817 return ptr - data;
2818}
2819
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002820static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821{
2822 struct l2cap_conf_rsp *rsp = data;
2823 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002825 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002827 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002828 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002829 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
2831 return ptr - data;
2832}
2833
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002834static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2835{
2836 struct l2cap_pinfo *pi = l2cap_pi(sk);
2837 int type, olen;
2838 unsigned long val;
2839 struct l2cap_conf_rfc rfc;
2840
2841 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2842
2843 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2844 return;
2845
2846 while (len >= L2CAP_CONF_OPT_SIZE) {
2847 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2848
2849 switch (type) {
2850 case L2CAP_CONF_RFC:
2851 if (olen == sizeof(rfc))
2852 memcpy(&rfc, (void *)val, olen);
2853 goto done;
2854 }
2855 }
2856
2857done:
2858 switch (rfc.mode) {
2859 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002860 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2861 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002862 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2863 break;
2864 case L2CAP_MODE_STREAMING:
2865 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2866 }
2867}
2868
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002869static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2870{
2871 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2872
2873 if (rej->reason != 0x0000)
2874 return 0;
2875
2876 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2877 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002878 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002879
2880 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002881 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002882
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002883 l2cap_conn_start(conn);
2884 }
2885
2886 return 0;
2887}
2888
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2890{
2891 struct l2cap_chan_list *list = &conn->chan_list;
2892 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2893 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002894 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002895 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
2897 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002898 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899
2900 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2901
2902 /* Check if we have socket listening on psm */
2903 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2904 if (!parent) {
2905 result = L2CAP_CR_BAD_PSM;
2906 goto sendresp;
2907 }
2908
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002909 bh_lock_sock(parent);
2910
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002911 /* Check if the ACL is secure enough (if not SDP) */
2912 if (psm != cpu_to_le16(0x0001) &&
2913 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002914 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002915 result = L2CAP_CR_SEC_BLOCK;
2916 goto response;
2917 }
2918
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 result = L2CAP_CR_NO_MEM;
2920
2921 /* Check for backlog size */
2922 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002923 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 goto response;
2925 }
2926
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002927 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 if (!sk)
2929 goto response;
2930
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002931 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932
2933 /* Check if we already have channel with that dcid */
2934 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002935 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 sock_set_flag(sk, SOCK_ZAPPED);
2937 l2cap_sock_kill(sk);
2938 goto response;
2939 }
2940
2941 hci_conn_hold(conn->hcon);
2942
2943 l2cap_sock_init(sk, parent);
2944 bacpy(&bt_sk(sk)->src, conn->src);
2945 bacpy(&bt_sk(sk)->dst, conn->dst);
2946 l2cap_pi(sk)->psm = psm;
2947 l2cap_pi(sk)->dcid = scid;
2948
2949 __l2cap_chan_add(conn, sk, parent);
2950 dcid = l2cap_pi(sk)->scid;
2951
2952 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2953
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 l2cap_pi(sk)->ident = cmd->ident;
2955
Marcel Holtmann984947d2009-02-06 23:35:19 +01002956 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002957 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002958 if (bt_sk(sk)->defer_setup) {
2959 sk->sk_state = BT_CONNECT2;
2960 result = L2CAP_CR_PEND;
2961 status = L2CAP_CS_AUTHOR_PEND;
2962 parent->sk_data_ready(parent, 0);
2963 } else {
2964 sk->sk_state = BT_CONFIG;
2965 result = L2CAP_CR_SUCCESS;
2966 status = L2CAP_CS_NO_INFO;
2967 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002968 } else {
2969 sk->sk_state = BT_CONNECT2;
2970 result = L2CAP_CR_PEND;
2971 status = L2CAP_CS_AUTHEN_PEND;
2972 }
2973 } else {
2974 sk->sk_state = BT_CONNECT2;
2975 result = L2CAP_CR_PEND;
2976 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 }
2978
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002979 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
2981response:
2982 bh_unlock_sock(parent);
2983
2984sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002985 rsp.scid = cpu_to_le16(scid);
2986 rsp.dcid = cpu_to_le16(dcid);
2987 rsp.result = cpu_to_le16(result);
2988 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002990
2991 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2992 struct l2cap_info_req info;
2993 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2994
2995 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2996 conn->info_ident = l2cap_get_ident(conn);
2997
2998 mod_timer(&conn->info_timer, jiffies +
2999 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
3000
3001 l2cap_send_cmd(conn, conn->info_ident,
3002 L2CAP_INFO_REQ, sizeof(info), &info);
3003 }
3004
Nathan Holsteind793fe82010-10-15 11:54:02 -04003005 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003006 result == L2CAP_CR_SUCCESS) {
3007 u8 buf[128];
3008 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3009 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3010 l2cap_build_conf_req(sk, buf), buf);
3011 l2cap_pi(sk)->num_conf_req++;
3012 }
3013
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 return 0;
3015}
3016
3017static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3018{
3019 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3020 u16 scid, dcid, result, status;
3021 struct sock *sk;
3022 u8 req[128];
3023
3024 scid = __le16_to_cpu(rsp->scid);
3025 dcid = __le16_to_cpu(rsp->dcid);
3026 result = __le16_to_cpu(rsp->result);
3027 status = __le16_to_cpu(rsp->status);
3028
3029 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
3030
3031 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003032 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3033 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003034 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003036 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
3037 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003038 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 }
3040
3041 switch (result) {
3042 case L2CAP_CR_SUCCESS:
3043 sk->sk_state = BT_CONFIG;
3044 l2cap_pi(sk)->ident = 0;
3045 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003046 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
3047
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003048 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
3049 break;
3050
3051 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3052
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3054 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003055 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 break;
3057
3058 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003059 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 break;
3061
3062 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003063 /* don't delete l2cap channel if sk is owned by user */
3064 if (sock_owned_by_user(sk)) {
3065 sk->sk_state = BT_DISCONN;
3066 l2cap_sock_clear_timer(sk);
3067 l2cap_sock_set_timer(sk, HZ / 5);
3068 break;
3069 }
3070
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 l2cap_chan_del(sk, ECONNREFUSED);
3072 break;
3073 }
3074
3075 bh_unlock_sock(sk);
3076 return 0;
3077}
3078
Mat Martineau8c462b62010-08-24 15:35:42 -07003079static inline void set_default_fcs(struct l2cap_pinfo *pi)
3080{
3081 /* FCS is enabled only in ERTM or streaming mode, if one or both
3082 * sides request it.
3083 */
3084 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
3085 pi->fcs = L2CAP_FCS_NONE;
3086 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
3087 pi->fcs = L2CAP_FCS_CRC16;
3088}
3089
Al Viro88219a02007-07-29 00:17:25 -07003090static 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 -07003091{
3092 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3093 u16 dcid, flags;
3094 u8 rsp[64];
3095 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003096 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
3098 dcid = __le16_to_cpu(req->dcid);
3099 flags = __le16_to_cpu(req->flags);
3100
3101 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3102
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003103 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3104 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 return -ENOENT;
3106
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003107 if (sk->sk_state != BT_CONFIG) {
3108 struct l2cap_cmd_rej rej;
3109
3110 rej.reason = cpu_to_le16(0x0002);
3111 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3112 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003113 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003114 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003115
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003116 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003117 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003118 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
3119 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3120 l2cap_build_conf_rsp(sk, rsp,
3121 L2CAP_CONF_REJECT, flags), rsp);
3122 goto unlock;
3123 }
3124
3125 /* Store config. */
3126 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
3127 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
3129 if (flags & 0x0001) {
3130 /* Incomplete config. Send empty response. */
3131 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003132 l2cap_build_conf_rsp(sk, rsp,
3133 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 goto unlock;
3135 }
3136
3137 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003138 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003139 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003140 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003144 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003145 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003146
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003147 /* Reset config buffer. */
3148 l2cap_pi(sk)->conf_len = 0;
3149
Marcel Holtmann876d9482007-10-20 13:35:42 +02003150 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
3151 goto unlock;
3152
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003154 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003155
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003157
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003158 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003159 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003160 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003161 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3162 l2cap_ertm_init(sk);
3163
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02003165 goto unlock;
3166 }
3167
3168 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003169 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08003170 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003172 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003173 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 }
3175
3176unlock:
3177 bh_unlock_sock(sk);
3178 return 0;
3179}
3180
3181static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3182{
3183 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3184 u16 scid, flags, result;
3185 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003186 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
3188 scid = __le16_to_cpu(rsp->scid);
3189 flags = __le16_to_cpu(rsp->flags);
3190 result = __le16_to_cpu(rsp->result);
3191
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003192 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
3193 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003195 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3196 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 return 0;
3198
3199 switch (result) {
3200 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003201 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 break;
3203
3204 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003205 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003206 char req[64];
3207
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003208 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003209 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003210 goto done;
3211 }
3212
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003213 /* throw out any old stored conf requests */
3214 result = L2CAP_CONF_SUCCESS;
3215 len = l2cap_parse_conf_rsp(sk, rsp->data,
3216 len, req, &result);
3217 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003218 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003219 goto done;
3220 }
3221
3222 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3223 L2CAP_CONF_REQ, len, req);
3224 l2cap_pi(sk)->num_conf_req++;
3225 if (result != L2CAP_CONF_SUCCESS)
3226 goto done;
3227 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 }
3229
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003230 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003231 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003233 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 goto done;
3235 }
3236
3237 if (flags & 0x01)
3238 goto done;
3239
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3241
3242 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003243 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003244
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003246 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003248 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003249 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3250 l2cap_ertm_init(sk);
3251
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 l2cap_chan_ready(sk);
3253 }
3254
3255done:
3256 bh_unlock_sock(sk);
3257 return 0;
3258}
3259
3260static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3261{
3262 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3263 struct l2cap_disconn_rsp rsp;
3264 u16 dcid, scid;
3265 struct sock *sk;
3266
3267 scid = __le16_to_cpu(req->scid);
3268 dcid = __le16_to_cpu(req->dcid);
3269
3270 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3271
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003272 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3273 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 return 0;
3275
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003276 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3277 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3279
3280 sk->sk_shutdown = SHUTDOWN_MASK;
3281
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003282 /* don't delete l2cap channel if sk is owned by user */
3283 if (sock_owned_by_user(sk)) {
3284 sk->sk_state = BT_DISCONN;
3285 l2cap_sock_clear_timer(sk);
3286 l2cap_sock_set_timer(sk, HZ / 5);
3287 bh_unlock_sock(sk);
3288 return 0;
3289 }
3290
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291 l2cap_chan_del(sk, ECONNRESET);
3292 bh_unlock_sock(sk);
3293
3294 l2cap_sock_kill(sk);
3295 return 0;
3296}
3297
3298static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3299{
3300 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3301 u16 dcid, scid;
3302 struct sock *sk;
3303
3304 scid = __le16_to_cpu(rsp->scid);
3305 dcid = __le16_to_cpu(rsp->dcid);
3306
3307 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3308
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003309 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3310 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311 return 0;
3312
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003313 /* don't delete l2cap channel if sk is owned by user */
3314 if (sock_owned_by_user(sk)) {
3315 sk->sk_state = BT_DISCONN;
3316 l2cap_sock_clear_timer(sk);
3317 l2cap_sock_set_timer(sk, HZ / 5);
3318 bh_unlock_sock(sk);
3319 return 0;
3320 }
3321
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 l2cap_chan_del(sk, 0);
3323 bh_unlock_sock(sk);
3324
3325 l2cap_sock_kill(sk);
3326 return 0;
3327}
3328
3329static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3330{
3331 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 u16 type;
3333
3334 type = __le16_to_cpu(req->type);
3335
3336 BT_DBG("type 0x%4.4x", type);
3337
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003338 if (type == L2CAP_IT_FEAT_MASK) {
3339 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003340 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003341 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3342 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3343 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003344 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003345 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3346 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003347 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003348 l2cap_send_cmd(conn, cmd->ident,
3349 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003350 } else if (type == L2CAP_IT_FIXED_CHAN) {
3351 u8 buf[12];
3352 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3353 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3354 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3355 memcpy(buf + 4, l2cap_fixed_chan, 8);
3356 l2cap_send_cmd(conn, cmd->ident,
3357 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003358 } else {
3359 struct l2cap_info_rsp rsp;
3360 rsp.type = cpu_to_le16(type);
3361 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3362 l2cap_send_cmd(conn, cmd->ident,
3363 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
3366 return 0;
3367}
3368
3369static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3370{
3371 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3372 u16 type, result;
3373
3374 type = __le16_to_cpu(rsp->type);
3375 result = __le16_to_cpu(rsp->result);
3376
3377 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3378
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003379 del_timer(&conn->info_timer);
3380
Ville Tervoadb08ed2010-08-04 09:43:33 +03003381 if (result != L2CAP_IR_SUCCESS) {
3382 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3383 conn->info_ident = 0;
3384
3385 l2cap_conn_start(conn);
3386
3387 return 0;
3388 }
3389
Marcel Holtmann984947d2009-02-06 23:35:19 +01003390 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003391 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003392
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003393 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003394 struct l2cap_info_req req;
3395 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3396
3397 conn->info_ident = l2cap_get_ident(conn);
3398
3399 l2cap_send_cmd(conn, conn->info_ident,
3400 L2CAP_INFO_REQ, sizeof(req), &req);
3401 } else {
3402 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3403 conn->info_ident = 0;
3404
3405 l2cap_conn_start(conn);
3406 }
3407 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003408 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003409 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003410
3411 l2cap_conn_start(conn);
3412 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003413
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 return 0;
3415}
3416
3417static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3418{
3419 u8 *data = skb->data;
3420 int len = skb->len;
3421 struct l2cap_cmd_hdr cmd;
3422 int err = 0;
3423
3424 l2cap_raw_recv(conn, skb);
3425
3426 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003427 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3429 data += L2CAP_CMD_HDR_SIZE;
3430 len -= L2CAP_CMD_HDR_SIZE;
3431
Al Viro88219a02007-07-29 00:17:25 -07003432 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433
Al Viro88219a02007-07-29 00:17:25 -07003434 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 -07003435
Al Viro88219a02007-07-29 00:17:25 -07003436 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 BT_DBG("corrupted command");
3438 break;
3439 }
3440
3441 switch (cmd.code) {
3442 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003443 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 break;
3445
3446 case L2CAP_CONN_REQ:
3447 err = l2cap_connect_req(conn, &cmd, data);
3448 break;
3449
3450 case L2CAP_CONN_RSP:
3451 err = l2cap_connect_rsp(conn, &cmd, data);
3452 break;
3453
3454 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003455 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 break;
3457
3458 case L2CAP_CONF_RSP:
3459 err = l2cap_config_rsp(conn, &cmd, data);
3460 break;
3461
3462 case L2CAP_DISCONN_REQ:
3463 err = l2cap_disconnect_req(conn, &cmd, data);
3464 break;
3465
3466 case L2CAP_DISCONN_RSP:
3467 err = l2cap_disconnect_rsp(conn, &cmd, data);
3468 break;
3469
3470 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003471 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 break;
3473
3474 case L2CAP_ECHO_RSP:
3475 break;
3476
3477 case L2CAP_INFO_REQ:
3478 err = l2cap_information_req(conn, &cmd, data);
3479 break;
3480
3481 case L2CAP_INFO_RSP:
3482 err = l2cap_information_rsp(conn, &cmd, data);
3483 break;
3484
3485 default:
3486 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3487 err = -EINVAL;
3488 break;
3489 }
3490
3491 if (err) {
3492 struct l2cap_cmd_rej rej;
3493 BT_DBG("error %d", err);
3494
3495 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003496 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3498 }
3499
Al Viro88219a02007-07-29 00:17:25 -07003500 data += cmd_len;
3501 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 }
3503
3504 kfree_skb(skb);
3505}
3506
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003507static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3508{
3509 u16 our_fcs, rcv_fcs;
3510 int hdr_size = L2CAP_HDR_SIZE + 2;
3511
3512 if (pi->fcs == L2CAP_FCS_CRC16) {
3513 skb_trim(skb, skb->len - 2);
3514 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3515 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3516
3517 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003518 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003519 }
3520 return 0;
3521}
3522
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003523static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3524{
3525 struct l2cap_pinfo *pi = l2cap_pi(sk);
3526 u16 control = 0;
3527
3528 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003529
3530 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3531
3532 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003533 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003534 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003535 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003536 }
3537
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003538 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3539 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003540
3541 l2cap_ertm_send(sk);
3542
3543 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3544 pi->frames_sent == 0) {
3545 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003546 l2cap_send_sframe(pi, control);
3547 }
3548}
3549
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003550static 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 -03003551{
3552 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003553 struct l2cap_pinfo *pi = l2cap_pi(sk);
3554 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003555
3556 bt_cb(skb)->tx_seq = tx_seq;
3557 bt_cb(skb)->sar = sar;
3558
3559 next_skb = skb_peek(SREJ_QUEUE(sk));
3560 if (!next_skb) {
3561 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003562 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003563 }
3564
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003565 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3566 if (tx_seq_offset < 0)
3567 tx_seq_offset += 64;
3568
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003569 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003570 if (bt_cb(next_skb)->tx_seq == tx_seq)
3571 return -EINVAL;
3572
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003573 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3574 pi->buffer_seq) % 64;
3575 if (next_tx_seq_offset < 0)
3576 next_tx_seq_offset += 64;
3577
3578 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003579 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003580 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003581 }
3582
3583 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3584 break;
3585
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003586 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003587
3588 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003589
3590 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003591}
3592
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003593static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3594{
3595 struct l2cap_pinfo *pi = l2cap_pi(sk);
3596 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003597 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003598
3599 switch (control & L2CAP_CTRL_SAR) {
3600 case L2CAP_SDU_UNSEGMENTED:
3601 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3602 goto drop;
3603
3604 err = sock_queue_rcv_skb(sk, skb);
3605 if (!err)
3606 return err;
3607
3608 break;
3609
3610 case L2CAP_SDU_START:
3611 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3612 goto drop;
3613
3614 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003615
3616 if (pi->sdu_len > pi->imtu)
3617 goto disconnect;
3618
3619 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003620 if (!pi->sdu)
3621 return -ENOMEM;
3622
3623 /* pull sdu_len bytes only after alloc, because of Local Busy
3624 * condition we have to be sure that this will be executed
3625 * only once, i.e., when alloc does not fail */
3626 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003627
3628 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3629
3630 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3631 pi->partial_sdu_len = skb->len;
3632 break;
3633
3634 case L2CAP_SDU_CONTINUE:
3635 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3636 goto disconnect;
3637
3638 if (!pi->sdu)
3639 goto disconnect;
3640
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003641 pi->partial_sdu_len += skb->len;
3642 if (pi->partial_sdu_len > pi->sdu_len)
3643 goto drop;
3644
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003645 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3646
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003647 break;
3648
3649 case L2CAP_SDU_END:
3650 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3651 goto disconnect;
3652
3653 if (!pi->sdu)
3654 goto disconnect;
3655
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003656 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003657 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003658
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003659 if (pi->partial_sdu_len > pi->imtu)
3660 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003661
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003662 if (pi->partial_sdu_len != pi->sdu_len)
3663 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003664
3665 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003666 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003667
3668 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003669 if (!_skb) {
3670 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3671 return -ENOMEM;
3672 }
3673
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003674 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003675 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003676 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003677 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3678 return err;
3679 }
3680
3681 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3682 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003683
3684 kfree_skb(pi->sdu);
3685 break;
3686 }
3687
3688 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003689 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003690
3691drop:
3692 kfree_skb(pi->sdu);
3693 pi->sdu = NULL;
3694
3695disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003696 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003697 kfree_skb(skb);
3698 return 0;
3699}
3700
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003701static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003702{
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003703 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003704 struct sk_buff *skb;
3705 u16 control;
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003706 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003707
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003708 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3709 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3710 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3711 if (err < 0) {
3712 skb_queue_head(BUSY_QUEUE(sk), skb);
3713 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003714 }
3715
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003716 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003717 }
3718
3719 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3720 goto done;
3721
3722 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3723 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3724 l2cap_send_sframe(pi, control);
3725 l2cap_pi(sk)->retry_count = 1;
3726
3727 del_timer(&pi->retrans_timer);
3728 __mod_monitor_timer();
3729
3730 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3731
3732done:
3733 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3734 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3735
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003736 BT_DBG("sk %p, Exit local busy", sk);
3737
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003738 return 0;
3739}
3740
3741static void l2cap_busy_work(struct work_struct *work)
3742{
3743 DECLARE_WAITQUEUE(wait, current);
3744 struct l2cap_pinfo *pi =
3745 container_of(work, struct l2cap_pinfo, busy_work);
3746 struct sock *sk = (struct sock *)pi;
3747 int n_tries = 0, timeo = HZ/5, err;
3748 struct sk_buff *skb;
3749
3750 lock_sock(sk);
3751
3752 add_wait_queue(sk_sleep(sk), &wait);
3753 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3754 set_current_state(TASK_INTERRUPTIBLE);
3755
3756 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3757 err = -EBUSY;
3758 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3759 break;
3760 }
3761
3762 if (!timeo)
3763 timeo = HZ/5;
3764
3765 if (signal_pending(current)) {
3766 err = sock_intr_errno(timeo);
3767 break;
3768 }
3769
3770 release_sock(sk);
3771 timeo = schedule_timeout(timeo);
3772 lock_sock(sk);
3773
3774 err = sock_error(sk);
3775 if (err)
3776 break;
3777
3778 if (l2cap_try_push_rx_skb(sk) == 0)
3779 break;
3780 }
3781
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003782 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003783 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003784
3785 release_sock(sk);
3786}
3787
3788static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3789{
3790 struct l2cap_pinfo *pi = l2cap_pi(sk);
3791 int sctrl, err;
3792
3793 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3794 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3795 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003796 return l2cap_try_push_rx_skb(sk);
3797
3798
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003799 }
3800
3801 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3802 if (err >= 0) {
3803 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3804 return err;
3805 }
3806
3807 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003808 BT_DBG("sk %p, Enter local busy", sk);
3809
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003810 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3811 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3812 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3813
3814 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3815 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3816 l2cap_send_sframe(pi, sctrl);
3817
3818 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3819
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003820 del_timer(&pi->ack_timer);
3821
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003822 queue_work(_busy_wq, &pi->busy_work);
3823
3824 return err;
3825}
3826
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003827static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003828{
3829 struct l2cap_pinfo *pi = l2cap_pi(sk);
3830 struct sk_buff *_skb;
3831 int err = -EINVAL;
3832
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003833 /*
3834 * TODO: We have to notify the userland if some data is lost with the
3835 * Streaming Mode.
3836 */
3837
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003838 switch (control & L2CAP_CTRL_SAR) {
3839 case L2CAP_SDU_UNSEGMENTED:
3840 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3841 kfree_skb(pi->sdu);
3842 break;
3843 }
3844
3845 err = sock_queue_rcv_skb(sk, skb);
3846 if (!err)
3847 return 0;
3848
3849 break;
3850
3851 case L2CAP_SDU_START:
3852 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3853 kfree_skb(pi->sdu);
3854 break;
3855 }
3856
3857 pi->sdu_len = get_unaligned_le16(skb->data);
3858 skb_pull(skb, 2);
3859
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003860 if (pi->sdu_len > pi->imtu) {
3861 err = -EMSGSIZE;
3862 break;
3863 }
3864
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003865 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3866 if (!pi->sdu) {
3867 err = -ENOMEM;
3868 break;
3869 }
3870
3871 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3872
3873 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3874 pi->partial_sdu_len = skb->len;
3875 err = 0;
3876 break;
3877
3878 case L2CAP_SDU_CONTINUE:
3879 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3880 break;
3881
3882 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3883
3884 pi->partial_sdu_len += skb->len;
3885 if (pi->partial_sdu_len > pi->sdu_len)
3886 kfree_skb(pi->sdu);
3887 else
3888 err = 0;
3889
3890 break;
3891
3892 case L2CAP_SDU_END:
3893 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3894 break;
3895
3896 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3897
3898 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3899 pi->partial_sdu_len += skb->len;
3900
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003901 if (pi->partial_sdu_len > pi->imtu)
3902 goto drop;
3903
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003904 if (pi->partial_sdu_len == pi->sdu_len) {
3905 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3906 err = sock_queue_rcv_skb(sk, _skb);
3907 if (err < 0)
3908 kfree_skb(_skb);
3909 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003910 err = 0;
3911
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003912drop:
3913 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003914 break;
3915 }
3916
3917 kfree_skb(skb);
3918 return err;
3919}
3920
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003921static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3922{
3923 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003924 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003925
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003926 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003927 if (bt_cb(skb)->tx_seq != tx_seq)
3928 break;
3929
3930 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003931 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003932 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003933 l2cap_pi(sk)->buffer_seq_srej =
3934 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003935 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003936 }
3937}
3938
3939static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3940{
3941 struct l2cap_pinfo *pi = l2cap_pi(sk);
3942 struct srej_list *l, *tmp;
3943 u16 control;
3944
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003945 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003946 if (l->tx_seq == tx_seq) {
3947 list_del(&l->list);
3948 kfree(l);
3949 return;
3950 }
3951 control = L2CAP_SUPER_SELECT_REJECT;
3952 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3953 l2cap_send_sframe(pi, control);
3954 list_del(&l->list);
3955 list_add_tail(&l->list, SREJ_LIST(sk));
3956 }
3957}
3958
3959static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3960{
3961 struct l2cap_pinfo *pi = l2cap_pi(sk);
3962 struct srej_list *new;
3963 u16 control;
3964
3965 while (tx_seq != pi->expected_tx_seq) {
3966 control = L2CAP_SUPER_SELECT_REJECT;
3967 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3968 l2cap_send_sframe(pi, control);
3969
3970 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003971 new->tx_seq = pi->expected_tx_seq;
3972 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003973 list_add_tail(&new->list, SREJ_LIST(sk));
3974 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003975 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003976}
3977
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003978static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3979{
3980 struct l2cap_pinfo *pi = l2cap_pi(sk);
3981 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003982 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003983 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003984 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003985 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986 int err = 0;
3987
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003988 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3989 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003990
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003991 if (L2CAP_CTRL_FINAL & rx_control &&
3992 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003993 del_timer(&pi->monitor_timer);
3994 if (pi->unacked_frames > 0)
3995 __mod_retrans_timer();
3996 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3997 }
3998
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003999 pi->expected_ack_seq = req_seq;
4000 l2cap_drop_acked_frames(sk);
4001
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004002 if (tx_seq == pi->expected_tx_seq)
4003 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004004
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004005 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
4006 if (tx_seq_offset < 0)
4007 tx_seq_offset += 64;
4008
4009 /* invalid tx_seq */
4010 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03004011 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004012 goto drop;
4013 }
4014
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004015 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
4016 goto drop;
4017
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004018 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4019 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004020
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004021 first = list_first_entry(SREJ_LIST(sk),
4022 struct srej_list, list);
4023 if (tx_seq == first->tx_seq) {
4024 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
4025 l2cap_check_srej_gap(sk, tx_seq);
4026
4027 list_del(&first->list);
4028 kfree(first);
4029
4030 if (list_empty(SREJ_LIST(sk))) {
4031 pi->buffer_seq = pi->buffer_seq_srej;
4032 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03004033 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004034 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004035 }
4036 } else {
4037 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004038
4039 /* duplicated tx_seq */
4040 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
4041 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004042
4043 list_for_each_entry(l, SREJ_LIST(sk), list) {
4044 if (l->tx_seq == tx_seq) {
4045 l2cap_resend_srejframe(sk, tx_seq);
4046 return 0;
4047 }
4048 }
4049 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004050 }
4051 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004052 expected_tx_seq_offset =
4053 (pi->expected_tx_seq - pi->buffer_seq) % 64;
4054 if (expected_tx_seq_offset < 0)
4055 expected_tx_seq_offset += 64;
4056
4057 /* duplicated tx_seq */
4058 if (tx_seq_offset < expected_tx_seq_offset)
4059 goto drop;
4060
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004061 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004062
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004063 BT_DBG("sk %p, Enter SREJ", sk);
4064
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004065 INIT_LIST_HEAD(SREJ_LIST(sk));
4066 pi->buffer_seq_srej = pi->buffer_seq;
4067
4068 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004069 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004070 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
4071
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004072 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
4073
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004074 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03004075
4076 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004077 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004078 return 0;
4079
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004080expected:
4081 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4082
4083 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03004084 bt_cb(skb)->tx_seq = tx_seq;
4085 bt_cb(skb)->sar = sar;
4086 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004087 return 0;
4088 }
4089
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004090 err = l2cap_push_rx_skb(sk, skb, rx_control);
4091 if (err < 0)
4092 return 0;
4093
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004094 if (rx_control & L2CAP_CTRL_FINAL) {
4095 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4096 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004097 else
4098 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004099 }
4100
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004101 __mod_ack_timer();
4102
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03004103 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
4104 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004105 l2cap_send_ack(pi);
4106
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004107 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004108
4109drop:
4110 kfree_skb(skb);
4111 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004112}
4113
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004114static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004115{
4116 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004117
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004118 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
4119 rx_control);
4120
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004121 pi->expected_ack_seq = __get_reqseq(rx_control);
4122 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004123
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004124 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004125 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004126 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4127 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4128 (pi->unacked_frames > 0))
4129 __mod_retrans_timer();
4130
4131 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4132 l2cap_send_srejtail(sk);
4133 } else {
4134 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004135 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004136
4137 } else if (rx_control & L2CAP_CTRL_FINAL) {
4138 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004139
4140 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4141 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004142 else
4143 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004144
4145 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004146 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4147 (pi->unacked_frames > 0))
4148 __mod_retrans_timer();
4149
4150 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004151 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004152 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004153 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004154 l2cap_ertm_send(sk);
4155 }
4156}
4157
4158static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
4159{
4160 struct l2cap_pinfo *pi = l2cap_pi(sk);
4161 u8 tx_seq = __get_reqseq(rx_control);
4162
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004163 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4164
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004165 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4166
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03004167 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004168 l2cap_drop_acked_frames(sk);
4169
4170 if (rx_control & L2CAP_CTRL_FINAL) {
4171 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4172 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004173 else
4174 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004175 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004176 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004177
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03004178 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004179 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004180 }
4181}
4182static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
4183{
4184 struct l2cap_pinfo *pi = l2cap_pi(sk);
4185 u8 tx_seq = __get_reqseq(rx_control);
4186
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004187 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4188
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004189 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4190
4191 if (rx_control & L2CAP_CTRL_POLL) {
4192 pi->expected_ack_seq = tx_seq;
4193 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004194
4195 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004196 l2cap_retransmit_one_frame(sk, tx_seq);
4197
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004198 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004199
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004200 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4201 pi->srej_save_reqseq = tx_seq;
4202 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4203 }
4204 } else if (rx_control & L2CAP_CTRL_FINAL) {
4205 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
4206 pi->srej_save_reqseq == tx_seq)
4207 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
4208 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004209 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004210 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004211 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004212 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4213 pi->srej_save_reqseq = tx_seq;
4214 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4215 }
4216 }
4217}
4218
4219static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
4220{
4221 struct l2cap_pinfo *pi = l2cap_pi(sk);
4222 u8 tx_seq = __get_reqseq(rx_control);
4223
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004224 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4225
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004226 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
4227 pi->expected_ack_seq = tx_seq;
4228 l2cap_drop_acked_frames(sk);
4229
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004230 if (rx_control & L2CAP_CTRL_POLL)
4231 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
4232
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004233 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
4234 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03004235 if (rx_control & L2CAP_CTRL_POLL)
4236 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004237 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004238 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004239
4240 if (rx_control & L2CAP_CTRL_POLL)
4241 l2cap_send_srejtail(sk);
4242 else
4243 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004244}
4245
4246static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
4247{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004248 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
4249
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03004250 if (L2CAP_CTRL_FINAL & rx_control &&
4251 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004252 del_timer(&l2cap_pi(sk)->monitor_timer);
4253 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004254 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004255 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004256 }
4257
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004258 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
4259 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004260 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004261 break;
4262
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004263 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004264 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004265 break;
4266
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004267 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004268 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004269 break;
4270
4271 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004272 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004273 break;
4274 }
4275
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004276 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004277 return 0;
4278}
4279
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004280static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4281{
4282 struct l2cap_pinfo *pi = l2cap_pi(sk);
4283 u16 control;
4284 u8 req_seq;
4285 int len, next_tx_seq_offset, req_seq_offset;
4286
4287 control = get_unaligned_le16(skb->data);
4288 skb_pull(skb, 2);
4289 len = skb->len;
4290
4291 /*
4292 * We can just drop the corrupted I-frame here.
4293 * Receiver will miss it and start proper recovery
4294 * procedures and ask retransmission.
4295 */
4296 if (l2cap_check_fcs(pi, skb))
4297 goto drop;
4298
4299 if (__is_sar_start(control) && __is_iframe(control))
4300 len -= 2;
4301
4302 if (pi->fcs == L2CAP_FCS_CRC16)
4303 len -= 2;
4304
4305 if (len > pi->mps) {
4306 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4307 goto drop;
4308 }
4309
4310 req_seq = __get_reqseq(control);
4311 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4312 if (req_seq_offset < 0)
4313 req_seq_offset += 64;
4314
4315 next_tx_seq_offset =
4316 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4317 if (next_tx_seq_offset < 0)
4318 next_tx_seq_offset += 64;
4319
4320 /* check for invalid req-seq */
4321 if (req_seq_offset > next_tx_seq_offset) {
4322 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4323 goto drop;
4324 }
4325
4326 if (__is_iframe(control)) {
4327 if (len < 0) {
4328 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4329 goto drop;
4330 }
4331
4332 l2cap_data_channel_iframe(sk, control, skb);
4333 } else {
4334 if (len != 0) {
4335 BT_ERR("%d", len);
4336 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4337 goto drop;
4338 }
4339
4340 l2cap_data_channel_sframe(sk, control, skb);
4341 }
4342
4343 return 0;
4344
4345drop:
4346 kfree_skb(skb);
4347 return 0;
4348}
4349
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4351{
4352 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004353 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004354 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004355 u8 tx_seq;
4356 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357
4358 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4359 if (!sk) {
4360 BT_DBG("unknown cid 0x%4.4x", cid);
4361 goto drop;
4362 }
4363
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004364 pi = l2cap_pi(sk);
4365
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366 BT_DBG("sk %p, len %d", sk, skb->len);
4367
4368 if (sk->sk_state != BT_CONNECTED)
4369 goto drop;
4370
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004371 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004372 case L2CAP_MODE_BASIC:
4373 /* If socket recv buffers overflows we drop data here
4374 * which is *bad* because L2CAP has to be reliable.
4375 * But we don't have any other choice. L2CAP doesn't
4376 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004378 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004379 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004381 if (!sock_queue_rcv_skb(sk, skb))
4382 goto done;
4383 break;
4384
4385 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004386 if (!sock_owned_by_user(sk)) {
4387 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004388 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004389 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004390 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004391 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004392
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004393 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004394
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004395 case L2CAP_MODE_STREAMING:
4396 control = get_unaligned_le16(skb->data);
4397 skb_pull(skb, 2);
4398 len = skb->len;
4399
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004400 if (l2cap_check_fcs(pi, skb))
4401 goto drop;
4402
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004403 if (__is_sar_start(control))
4404 len -= 2;
4405
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004406 if (pi->fcs == L2CAP_FCS_CRC16)
4407 len -= 2;
4408
Nathan Holstein51893f82010-06-09 15:46:25 -04004409 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004410 goto drop;
4411
4412 tx_seq = __get_txseq(control);
4413
4414 if (pi->expected_tx_seq == tx_seq)
4415 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4416 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004417 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004418
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004419 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004420
4421 goto done;
4422
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004423 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004424 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004425 break;
4426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427
4428drop:
4429 kfree_skb(skb);
4430
4431done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004432 if (sk)
4433 bh_unlock_sock(sk);
4434
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 return 0;
4436}
4437
Al Viro8e036fc2007-07-29 00:16:36 -07004438static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439{
4440 struct sock *sk;
4441
4442 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4443 if (!sk)
4444 goto drop;
4445
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004446 bh_lock_sock(sk);
4447
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 BT_DBG("sk %p, len %d", sk, skb->len);
4449
4450 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4451 goto drop;
4452
4453 if (l2cap_pi(sk)->imtu < skb->len)
4454 goto drop;
4455
4456 if (!sock_queue_rcv_skb(sk, skb))
4457 goto done;
4458
4459drop:
4460 kfree_skb(skb);
4461
4462done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004463 if (sk)
4464 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465 return 0;
4466}
4467
4468static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4469{
4470 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004471 u16 cid, len;
4472 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473
4474 skb_pull(skb, L2CAP_HDR_SIZE);
4475 cid = __le16_to_cpu(lh->cid);
4476 len = __le16_to_cpu(lh->len);
4477
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004478 if (len != skb->len) {
4479 kfree_skb(skb);
4480 return;
4481 }
4482
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4484
4485 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004486 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 l2cap_sig_channel(conn, skb);
4488 break;
4489
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004490 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004491 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 skb_pull(skb, 2);
4493 l2cap_conless_channel(conn, psm, skb);
4494 break;
4495
4496 default:
4497 l2cap_data_channel(conn, cid, skb);
4498 break;
4499 }
4500}
4501
4502/* ---- L2CAP interface with lower layer (HCI) ---- */
4503
4504static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4505{
4506 int exact = 0, lm1 = 0, lm2 = 0;
4507 register struct sock *sk;
4508 struct hlist_node *node;
4509
4510 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004511 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512
4513 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4514
4515 /* Find listening sockets and check their link_mode */
4516 read_lock(&l2cap_sk_list.lock);
4517 sk_for_each(sk, node, &l2cap_sk_list.head) {
4518 if (sk->sk_state != BT_LISTEN)
4519 continue;
4520
4521 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004522 lm1 |= HCI_LM_ACCEPT;
4523 if (l2cap_pi(sk)->role_switch)
4524 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004526 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4527 lm2 |= HCI_LM_ACCEPT;
4528 if (l2cap_pi(sk)->role_switch)
4529 lm2 |= HCI_LM_MASTER;
4530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 }
4532 read_unlock(&l2cap_sk_list.lock);
4533
4534 return exact ? lm1 : lm2;
4535}
4536
4537static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4538{
Marcel Holtmann01394182006-07-03 10:02:46 +02004539 struct l2cap_conn *conn;
4540
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4542
4543 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004544 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545
4546 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 conn = l2cap_conn_add(hcon, status);
4548 if (conn)
4549 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004550 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 l2cap_conn_del(hcon, bt_err(status));
4552
4553 return 0;
4554}
4555
Marcel Holtmann2950f212009-02-12 14:02:50 +01004556static int l2cap_disconn_ind(struct hci_conn *hcon)
4557{
4558 struct l2cap_conn *conn = hcon->l2cap_data;
4559
4560 BT_DBG("hcon %p", hcon);
4561
4562 if (hcon->type != ACL_LINK || !conn)
4563 return 0x13;
4564
4565 return conn->disc_reason;
4566}
4567
4568static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569{
4570 BT_DBG("hcon %p reason %d", hcon, reason);
4571
4572 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004573 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574
4575 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004576
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 return 0;
4578}
4579
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004580static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4581{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004582 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004583 return;
4584
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004585 if (encrypt == 0x00) {
4586 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4587 l2cap_sock_clear_timer(sk);
4588 l2cap_sock_set_timer(sk, HZ * 5);
4589 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4590 __l2cap_sock_close(sk, ECONNREFUSED);
4591 } else {
4592 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4593 l2cap_sock_clear_timer(sk);
4594 }
4595}
4596
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004597static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598{
4599 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004600 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602
Marcel Holtmann01394182006-07-03 10:02:46 +02004603 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004605
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 l = &conn->chan_list;
4607
4608 BT_DBG("conn %p", conn);
4609
4610 read_lock(&l->lock);
4611
4612 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4613 bh_lock_sock(sk);
4614
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004615 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4616 bh_unlock_sock(sk);
4617 continue;
4618 }
4619
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004620 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004621 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004622 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004623 bh_unlock_sock(sk);
4624 continue;
4625 }
4626
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004627 if (sk->sk_state == BT_CONNECT) {
4628 if (!status) {
4629 struct l2cap_conn_req req;
4630 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4631 req.psm = l2cap_pi(sk)->psm;
4632
4633 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004634 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004635
4636 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4637 L2CAP_CONN_REQ, sizeof(req), &req);
4638 } else {
4639 l2cap_sock_clear_timer(sk);
4640 l2cap_sock_set_timer(sk, HZ / 10);
4641 }
4642 } else if (sk->sk_state == BT_CONNECT2) {
4643 struct l2cap_conn_rsp rsp;
4644 __u16 result;
4645
4646 if (!status) {
4647 sk->sk_state = BT_CONFIG;
4648 result = L2CAP_CR_SUCCESS;
4649 } else {
4650 sk->sk_state = BT_DISCONN;
4651 l2cap_sock_set_timer(sk, HZ / 10);
4652 result = L2CAP_CR_SEC_BLOCK;
4653 }
4654
4655 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4656 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4657 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004658 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004659 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4660 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004661 }
4662
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 bh_unlock_sock(sk);
4664 }
4665
4666 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004667
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668 return 0;
4669}
4670
4671static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4672{
4673 struct l2cap_conn *conn = hcon->l2cap_data;
4674
4675 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
4676 goto drop;
4677
4678 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4679
4680 if (flags & ACL_START) {
4681 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004682 struct sock *sk;
4683 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684 int len;
4685
4686 if (conn->rx_len) {
4687 BT_ERR("Unexpected start frame (len %d)", skb->len);
4688 kfree_skb(conn->rx_skb);
4689 conn->rx_skb = NULL;
4690 conn->rx_len = 0;
4691 l2cap_conn_unreliable(conn, ECOMM);
4692 }
4693
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004694 /* Start fragment always begin with Basic L2CAP header */
4695 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696 BT_ERR("Frame is too short (len %d)", skb->len);
4697 l2cap_conn_unreliable(conn, ECOMM);
4698 goto drop;
4699 }
4700
4701 hdr = (struct l2cap_hdr *) skb->data;
4702 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004703 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704
4705 if (len == skb->len) {
4706 /* Complete frame received */
4707 l2cap_recv_frame(conn, skb);
4708 return 0;
4709 }
4710
4711 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4712
4713 if (skb->len > len) {
4714 BT_ERR("Frame is too long (len %d, expected len %d)",
4715 skb->len, len);
4716 l2cap_conn_unreliable(conn, ECOMM);
4717 goto drop;
4718 }
4719
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004720 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4721
4722 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4723 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
4724 len, l2cap_pi(sk)->imtu);
4725 bh_unlock_sock(sk);
4726 l2cap_conn_unreliable(conn, ECOMM);
4727 goto drop;
4728 }
4729
4730 if (sk)
4731 bh_unlock_sock(sk);
4732
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004734 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4735 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736 goto drop;
4737
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004738 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004739 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740 conn->rx_len = len - skb->len;
4741 } else {
4742 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4743
4744 if (!conn->rx_len) {
4745 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4746 l2cap_conn_unreliable(conn, ECOMM);
4747 goto drop;
4748 }
4749
4750 if (skb->len > conn->rx_len) {
4751 BT_ERR("Fragment is too long (len %d, expected %d)",
4752 skb->len, conn->rx_len);
4753 kfree_skb(conn->rx_skb);
4754 conn->rx_skb = NULL;
4755 conn->rx_len = 0;
4756 l2cap_conn_unreliable(conn, ECOMM);
4757 goto drop;
4758 }
4759
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004760 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004761 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 conn->rx_len -= skb->len;
4763
4764 if (!conn->rx_len) {
4765 /* Complete frame received */
4766 l2cap_recv_frame(conn, conn->rx_skb);
4767 conn->rx_skb = NULL;
4768 }
4769 }
4770
4771drop:
4772 kfree_skb(skb);
4773 return 0;
4774}
4775
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004776static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777{
4778 struct sock *sk;
4779 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004780
4781 read_lock_bh(&l2cap_sk_list.lock);
4782
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004783 sk_for_each(sk, node, &l2cap_sk_list.head) {
4784 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004786 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4787 batostr(&bt_sk(sk)->src),
4788 batostr(&bt_sk(sk)->dst),
4789 sk->sk_state, __le16_to_cpu(pi->psm),
4790 pi->scid, pi->dcid,
4791 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004792 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004795
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004796 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797}
4798
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004799static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4800{
4801 return single_open(file, l2cap_debugfs_show, inode->i_private);
4802}
4803
4804static const struct file_operations l2cap_debugfs_fops = {
4805 .open = l2cap_debugfs_open,
4806 .read = seq_read,
4807 .llseek = seq_lseek,
4808 .release = single_release,
4809};
4810
4811static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004813static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814 .family = PF_BLUETOOTH,
4815 .owner = THIS_MODULE,
4816 .release = l2cap_sock_release,
4817 .bind = l2cap_sock_bind,
4818 .connect = l2cap_sock_connect,
4819 .listen = l2cap_sock_listen,
4820 .accept = l2cap_sock_accept,
4821 .getname = l2cap_sock_getname,
4822 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004823 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004825 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 .mmap = sock_no_mmap,
4827 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828 .shutdown = l2cap_sock_shutdown,
4829 .setsockopt = l2cap_sock_setsockopt,
4830 .getsockopt = l2cap_sock_getsockopt
4831};
4832
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004833static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834 .family = PF_BLUETOOTH,
4835 .owner = THIS_MODULE,
4836 .create = l2cap_sock_create,
4837};
4838
4839static struct hci_proto l2cap_hci_proto = {
4840 .name = "L2CAP",
4841 .id = HCI_PROTO_L2CAP,
4842 .connect_ind = l2cap_connect_ind,
4843 .connect_cfm = l2cap_connect_cfm,
4844 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004845 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004846 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847 .recv_acldata = l2cap_recv_acldata
4848};
4849
4850static int __init l2cap_init(void)
4851{
4852 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004853
Linus Torvalds1da177e2005-04-16 15:20:36 -07004854 err = proto_register(&l2cap_proto, 0);
4855 if (err < 0)
4856 return err;
4857
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004858 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004859 if (!_busy_wq) {
4860 proto_unregister(&l2cap_proto);
4861 return -ENOMEM;
4862 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004863
Linus Torvalds1da177e2005-04-16 15:20:36 -07004864 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4865 if (err < 0) {
4866 BT_ERR("L2CAP socket registration failed");
4867 goto error;
4868 }
4869
4870 err = hci_register_proto(&l2cap_hci_proto);
4871 if (err < 0) {
4872 BT_ERR("L2CAP protocol registration failed");
4873 bt_sock_unregister(BTPROTO_L2CAP);
4874 goto error;
4875 }
4876
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004877 if (bt_debugfs) {
4878 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4879 bt_debugfs, NULL, &l2cap_debugfs_fops);
4880 if (!l2cap_debugfs)
4881 BT_ERR("Failed to create L2CAP debug file");
4882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883
4884 BT_INFO("L2CAP ver %s", VERSION);
4885 BT_INFO("L2CAP socket layer initialized");
4886
4887 return 0;
4888
4889error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004890 destroy_workqueue(_busy_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891 proto_unregister(&l2cap_proto);
4892 return err;
4893}
4894
4895static void __exit l2cap_exit(void)
4896{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004897 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004899 flush_workqueue(_busy_wq);
4900 destroy_workqueue(_busy_wq);
4901
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4903 BT_ERR("L2CAP socket unregistration failed");
4904
4905 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4906 BT_ERR("L2CAP protocol unregistration failed");
4907
4908 proto_unregister(&l2cap_proto);
4909}
4910
4911void l2cap_load(void)
4912{
4913 /* Dummy function to trigger automatic L2CAP module loading by
4914 * other modules that use L2CAP sockets but don't use any other
4915 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916}
4917EXPORT_SYMBOL(l2cap_load);
4918
4919module_init(l2cap_init);
4920module_exit(l2cap_exit);
4921
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004922module_param(disable_ertm, bool, 0644);
4923MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004924
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004925MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4927MODULE_VERSION(VERSION);
4928MODULE_LICENSE("GPL");
4929MODULE_ALIAS("bt-proto-0");