blob: 0b54b7dd84010a52147a54155c4f8db2b61752a7 [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
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -030060static int disable_ertm = 0;
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 ---- */
86static void l2cap_sock_timeout(unsigned long arg)
87{
88 struct sock *sk = (struct sock *) arg;
Marcel Holtmannb1235d72008-07-14 20:13:54 +020089 int reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91 BT_DBG("sock %p state %d", sk, sk->sk_state);
92
93 bh_lock_sock(sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +020094
Marcel Holtmannf62e4322009-01-15 21:58:44 +010095 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
96 reason = ECONNREFUSED;
97 else if (sk->sk_state == BT_CONNECT &&
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +010098 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
Marcel Holtmannb1235d72008-07-14 20:13:54 +020099 reason = ECONNREFUSED;
100 else
101 reason = ETIMEDOUT;
102
103 __l2cap_sock_close(sk, reason);
104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 bh_unlock_sock(sk);
106
107 l2cap_sock_kill(sk);
108 sock_put(sk);
109}
110
111static void l2cap_sock_set_timer(struct sock *sk, long timeout)
112{
113 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
114 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
115}
116
117static void l2cap_sock_clear_timer(struct sock *sk)
118{
119 BT_DBG("sock %p state %d", sk, sk->sk_state);
120 sk_stop_timer(sk, &sk->sk_timer);
121}
122
Marcel Holtmann01394182006-07-03 10:02:46 +0200123/* ---- L2CAP channels ---- */
124static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
125{
126 struct sock *s;
127 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
128 if (l2cap_pi(s)->dcid == cid)
129 break;
130 }
131 return s;
132}
133
134static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
135{
136 struct sock *s;
137 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
138 if (l2cap_pi(s)->scid == cid)
139 break;
140 }
141 return s;
142}
143
144/* Find channel with given SCID.
145 * Returns locked socket */
146static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
147{
148 struct sock *s;
149 read_lock(&l->lock);
150 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300151 if (s)
152 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200153 read_unlock(&l->lock);
154 return s;
155}
156
157static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
158{
159 struct sock *s;
160 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
161 if (l2cap_pi(s)->ident == ident)
162 break;
163 }
164 return s;
165}
166
167static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
168{
169 struct sock *s;
170 read_lock(&l->lock);
171 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300172 if (s)
173 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 read_unlock(&l->lock);
175 return s;
176}
177
178static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
179{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300180 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200181
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300182 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300183 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200184 return cid;
185 }
186
187 return 0;
188}
189
190static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
191{
192 sock_hold(sk);
193
194 if (l->head)
195 l2cap_pi(l->head)->prev_c = sk;
196
197 l2cap_pi(sk)->next_c = l->head;
198 l2cap_pi(sk)->prev_c = NULL;
199 l->head = sk;
200}
201
202static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
203{
204 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
205
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200206 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200207 if (sk == l->head)
208 l->head = next;
209
210 if (next)
211 l2cap_pi(next)->prev_c = prev;
212 if (prev)
213 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200214 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
216 __sock_put(sk);
217}
218
219static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
220{
221 struct l2cap_chan_list *l = &conn->chan_list;
222
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300223 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
224 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200225
Marcel Holtmann2950f212009-02-12 14:02:50 +0100226 conn->disc_reason = 0x13;
227
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 l2cap_pi(sk)->conn = conn;
229
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300230 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200231 /* Alloc CID for connection-oriented socket */
232 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
233 } else if (sk->sk_type == SOCK_DGRAM) {
234 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300235 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
236 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200237 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
238 } else {
239 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300240 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
241 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200242 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
243 }
244
245 __l2cap_chan_link(l, sk);
246
247 if (parent)
248 bt_accept_enqueue(parent, sk);
249}
250
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900251/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200252 * Must be called on the locked socket. */
253static void l2cap_chan_del(struct sock *sk, int err)
254{
255 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
256 struct sock *parent = bt_sk(sk)->parent;
257
258 l2cap_sock_clear_timer(sk);
259
260 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
261
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900262 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200263 /* Unlink from channel list */
264 l2cap_chan_unlink(&conn->chan_list, sk);
265 l2cap_pi(sk)->conn = NULL;
266 hci_conn_put(conn->hcon);
267 }
268
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200269 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200270 sock_set_flag(sk, SOCK_ZAPPED);
271
272 if (err)
273 sk->sk_err = err;
274
275 if (parent) {
276 bt_accept_unlink(sk);
277 parent->sk_data_ready(parent, 0);
278 } else
279 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300280
281 skb_queue_purge(TX_QUEUE(sk));
282
283 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
284 struct srej_list *l, *tmp;
285
286 del_timer(&l2cap_pi(sk)->retrans_timer);
287 del_timer(&l2cap_pi(sk)->monitor_timer);
288 del_timer(&l2cap_pi(sk)->ack_timer);
289
290 skb_queue_purge(SREJ_QUEUE(sk));
291 skb_queue_purge(BUSY_QUEUE(sk));
292
293 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
294 list_del(&l->list);
295 kfree(l);
296 }
297 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200298}
299
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200300/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100301static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200302{
303 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100304 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200305
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100306 if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
307 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
308 auth_type = HCI_AT_NO_BONDING_MITM;
309 else
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300310 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100311
312 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
313 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
314 } else {
315 switch (l2cap_pi(sk)->sec_level) {
316 case BT_SECURITY_HIGH:
317 auth_type = HCI_AT_GENERAL_BONDING_MITM;
318 break;
319 case BT_SECURITY_MEDIUM:
320 auth_type = HCI_AT_GENERAL_BONDING;
321 break;
322 default:
323 auth_type = HCI_AT_NO_BONDING;
324 break;
325 }
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100326 }
327
328 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
329 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200330}
331
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200332static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
333{
334 u8 id;
335
336 /* Get next available identificator.
337 * 1 - 128 are used by kernel.
338 * 129 - 199 are reserved.
339 * 200 - 254 are used by utilities like l2ping, etc.
340 */
341
342 spin_lock_bh(&conn->lock);
343
344 if (++conn->tx_ident > 128)
345 conn->tx_ident = 1;
346
347 id = conn->tx_ident;
348
349 spin_unlock_bh(&conn->lock);
350
351 return id;
352}
353
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300354static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200355{
356 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
357
358 BT_DBG("code 0x%2.2x", code);
359
360 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300361 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200362
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300363 hci_send_acl(conn->hcon, skb, 0);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200364}
365
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300366static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367{
368 struct sk_buff *skb;
369 struct l2cap_hdr *lh;
370 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300371 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300372 int count, hlen = L2CAP_HDR_SIZE + 2;
373
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300374 if (sk->sk_state != BT_CONNECTED)
375 return;
376
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300377 if (pi->fcs == L2CAP_FCS_CRC16)
378 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379
380 BT_DBG("pi %p, control 0x%2.2x", pi, control);
381
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300382 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300383 control |= L2CAP_CTRL_FRAME_TYPE;
384
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300385 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
386 control |= L2CAP_CTRL_FINAL;
387 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
388 }
389
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300390 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
391 control |= L2CAP_CTRL_POLL;
392 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
393 }
394
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300395 skb = bt_skb_alloc(count, GFP_ATOMIC);
396 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300397 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300398
399 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300400 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300401 lh->cid = cpu_to_le16(pi->dcid);
402 put_unaligned_le16(control, skb_put(skb, 2));
403
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300404 if (pi->fcs == L2CAP_FCS_CRC16) {
405 u16 fcs = crc16(0, (u8 *)lh, count - 2);
406 put_unaligned_le16(fcs, skb_put(skb, 2));
407 }
408
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300409 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300410}
411
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300412static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300413{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300414 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300415 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300416 pi->conn_state |= L2CAP_CONN_RNR_SENT;
417 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300418 control |= L2CAP_SUPER_RCV_READY;
419
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300420 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
421
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300422 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300423}
424
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300425static inline int __l2cap_no_conn_pending(struct sock *sk)
426{
427 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
428}
429
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200430static void l2cap_do_start(struct sock *sk)
431{
432 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
433
434 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100435 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
436 return;
437
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300438 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200439 struct l2cap_conn_req req;
440 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
441 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200442
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200443 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300444 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200445
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200446 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200447 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200448 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200449 } else {
450 struct l2cap_info_req req;
451 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
452
453 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
454 conn->info_ident = l2cap_get_ident(conn);
455
456 mod_timer(&conn->info_timer, jiffies +
457 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
458
459 l2cap_send_cmd(conn, conn->info_ident,
460 L2CAP_INFO_REQ, sizeof(req), &req);
461 }
462}
463
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300464static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
465{
466 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300467 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300468 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
469
470 switch (mode) {
471 case L2CAP_MODE_ERTM:
472 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
473 case L2CAP_MODE_STREAMING:
474 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
475 default:
476 return 0x00;
477 }
478}
479
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300480static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300481{
482 struct l2cap_disconn_req req;
483
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300484 if (!conn)
485 return;
486
487 skb_queue_purge(TX_QUEUE(sk));
488
489 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
490 del_timer(&l2cap_pi(sk)->retrans_timer);
491 del_timer(&l2cap_pi(sk)->monitor_timer);
492 del_timer(&l2cap_pi(sk)->ack_timer);
493 }
494
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
496 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
497 l2cap_send_cmd(conn, l2cap_get_ident(conn),
498 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300499
500 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300501 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300502}
503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505static void l2cap_conn_start(struct l2cap_conn *conn)
506{
507 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300508 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 struct sock *sk;
510
511 BT_DBG("conn %p", conn);
512
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300513 INIT_LIST_HEAD(&del.list);
514
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200515 read_lock(&l->lock);
516
517 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
518 bh_lock_sock(sk);
519
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300520 if (sk->sk_type != SOCK_SEQPACKET &&
521 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200522 bh_unlock_sock(sk);
523 continue;
524 }
525
526 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300527 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300528
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300529 if (!l2cap_check_security(sk) ||
530 !__l2cap_no_conn_pending(sk)) {
531 bh_unlock_sock(sk);
532 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200533 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300534
535 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
536 conn->feat_mask)
537 && l2cap_pi(sk)->conf_state &
538 L2CAP_CONF_STATE2_DEVICE) {
539 tmp1 = kzalloc(sizeof(struct sock_del_list),
540 GFP_ATOMIC);
541 tmp1->sk = sk;
542 list_add_tail(&tmp1->list, &del.list);
543 bh_unlock_sock(sk);
544 continue;
545 }
546
547 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
548 req.psm = l2cap_pi(sk)->psm;
549
550 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
551 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
552
553 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
554 L2CAP_CONN_REQ, sizeof(req), &req);
555
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200556 } else if (sk->sk_state == BT_CONNECT2) {
557 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300558 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200559 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
560 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
561
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100562 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100563 if (bt_sk(sk)->defer_setup) {
564 struct sock *parent = bt_sk(sk)->parent;
565 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
566 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
567 parent->sk_data_ready(parent, 0);
568
569 } else {
570 sk->sk_state = BT_CONFIG;
571 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
572 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
573 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200574 } else {
575 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
576 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
577 }
578
579 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
580 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300581
582 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
583 rsp.result != L2CAP_CR_SUCCESS) {
584 bh_unlock_sock(sk);
585 continue;
586 }
587
588 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
589 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
590 l2cap_build_conf_req(sk, buf), buf);
591 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200592 }
593
594 bh_unlock_sock(sk);
595 }
596
597 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300598
599 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
600 bh_lock_sock(tmp1->sk);
601 __l2cap_sock_close(tmp1->sk, ECONNRESET);
602 bh_unlock_sock(tmp1->sk);
603 list_del(&tmp1->list);
604 kfree(tmp1);
605 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200606}
607
608static void l2cap_conn_ready(struct l2cap_conn *conn)
609{
610 struct l2cap_chan_list *l = &conn->chan_list;
611 struct sock *sk;
612
613 BT_DBG("conn %p", conn);
614
615 read_lock(&l->lock);
616
617 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
618 bh_lock_sock(sk);
619
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300620 if (sk->sk_type != SOCK_SEQPACKET &&
621 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200622 l2cap_sock_clear_timer(sk);
623 sk->sk_state = BT_CONNECTED;
624 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200625 } else if (sk->sk_state == BT_CONNECT)
626 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200627
628 bh_unlock_sock(sk);
629 }
630
631 read_unlock(&l->lock);
632}
633
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200634/* Notify sockets that we cannot guaranty reliability anymore */
635static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
636{
637 struct l2cap_chan_list *l = &conn->chan_list;
638 struct sock *sk;
639
640 BT_DBG("conn %p", conn);
641
642 read_lock(&l->lock);
643
644 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100645 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200646 sk->sk_err = err;
647 }
648
649 read_unlock(&l->lock);
650}
651
652static void l2cap_info_timeout(unsigned long arg)
653{
654 struct l2cap_conn *conn = (void *) arg;
655
Marcel Holtmann984947d2009-02-06 23:35:19 +0100656 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100657 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100658
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200659 l2cap_conn_start(conn);
660}
661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
663{
Marcel Holtmann01394182006-07-03 10:02:46 +0200664 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
Marcel Holtmann01394182006-07-03 10:02:46 +0200666 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 return conn;
668
Marcel Holtmann01394182006-07-03 10:02:46 +0200669 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
670 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
673 hcon->l2cap_data = conn;
674 conn->hcon = hcon;
675
Marcel Holtmann01394182006-07-03 10:02:46 +0200676 BT_DBG("hcon %p conn %p", hcon, conn);
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 conn->mtu = hcon->hdev->acl_mtu;
679 conn->src = &hcon->hdev->bdaddr;
680 conn->dst = &hcon->dst;
681
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200682 conn->feat_mask = 0;
683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 spin_lock_init(&conn->lock);
685 rwlock_init(&conn->chan_list.lock);
686
Dave Young45054dc2009-10-18 20:28:30 +0000687 setup_timer(&conn->info_timer, l2cap_info_timeout,
688 (unsigned long) conn);
689
Marcel Holtmann2950f212009-02-12 14:02:50 +0100690 conn->disc_reason = 0x13;
691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 return conn;
693}
694
Marcel Holtmann01394182006-07-03 10:02:46 +0200695static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Marcel Holtmann01394182006-07-03 10:02:46 +0200697 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 struct sock *sk;
699
Marcel Holtmann01394182006-07-03 10:02:46 +0200700 if (!conn)
701 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
703 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
704
Wei Yongjun7585b972009-02-25 18:29:52 +0800705 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 /* Kill channels */
708 while ((sk = conn->chan_list.head)) {
709 bh_lock_sock(sk);
710 l2cap_chan_del(sk, err);
711 bh_unlock_sock(sk);
712 l2cap_sock_kill(sk);
713 }
714
Dave Young8e8440f2008-03-03 12:18:55 -0800715 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
716 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 hcon->l2cap_data = NULL;
719 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
722static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
723{
724 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200725 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200727 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
729
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730/* ---- Socket interface ---- */
Al Viro8e036fc2007-07-29 00:16:36 -0700731static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
733 struct sock *sk;
734 struct hlist_node *node;
735 sk_for_each(sk, node, &l2cap_sk_list.head)
736 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
737 goto found;
738 sk = NULL;
739found:
740 return sk;
741}
742
743/* Find socket with psm and source bdaddr.
744 * Returns closest match.
745 */
Al Viro8e036fc2007-07-29 00:16:36 -0700746static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
748 struct sock *sk = NULL, *sk1 = NULL;
749 struct hlist_node *node;
750
751 sk_for_each(sk, node, &l2cap_sk_list.head) {
752 if (state && sk->sk_state != state)
753 continue;
754
755 if (l2cap_pi(sk)->psm == psm) {
756 /* Exact match. */
757 if (!bacmp(&bt_sk(sk)->src, src))
758 break;
759
760 /* Closest match */
761 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
762 sk1 = sk;
763 }
764 }
765 return node ? sk : sk1;
766}
767
768/* Find socket with given address (psm, src).
769 * Returns locked socket */
Al Viro8e036fc2007-07-29 00:16:36 -0700770static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771{
772 struct sock *s;
773 read_lock(&l2cap_sk_list.lock);
774 s = __l2cap_get_sock_by_psm(state, psm, src);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300775 if (s)
776 bh_lock_sock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 read_unlock(&l2cap_sk_list.lock);
778 return s;
779}
780
781static void l2cap_sock_destruct(struct sock *sk)
782{
783 BT_DBG("sk %p", sk);
784
785 skb_queue_purge(&sk->sk_receive_queue);
786 skb_queue_purge(&sk->sk_write_queue);
787}
788
789static void l2cap_sock_cleanup_listen(struct sock *parent)
790{
791 struct sock *sk;
792
793 BT_DBG("parent %p", parent);
794
795 /* Close not yet accepted channels */
796 while ((sk = bt_accept_dequeue(parent, NULL)))
797 l2cap_sock_close(sk);
798
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200799 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 sock_set_flag(parent, SOCK_ZAPPED);
801}
802
803/* Kill socket (only if zapped and orphan)
804 * Must be called on unlocked socket.
805 */
806static void l2cap_sock_kill(struct sock *sk)
807{
808 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
809 return;
810
811 BT_DBG("sk %p state %d", sk, sk->sk_state);
812
813 /* Kill poor orphan */
814 bt_sock_unlink(&l2cap_sk_list, sk);
815 sock_set_flag(sk, SOCK_DEAD);
816 sock_put(sk);
817}
818
819static void __l2cap_sock_close(struct sock *sk, int reason)
820{
821 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
822
823 switch (sk->sk_state) {
824 case BT_LISTEN:
825 l2cap_sock_cleanup_listen(sk);
826 break;
827
828 case BT_CONNECTED:
829 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300830 if (sk->sk_type == SOCK_SEQPACKET ||
831 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300835 l2cap_send_disconn_req(conn, sk, reason);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200836 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 break;
839
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100840 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300841 if (sk->sk_type == SOCK_SEQPACKET ||
842 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100843 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
844 struct l2cap_conn_rsp rsp;
845 __u16 result;
846
847 if (bt_sk(sk)->defer_setup)
848 result = L2CAP_CR_SEC_BLOCK;
849 else
850 result = L2CAP_CR_BAD_PSM;
851
852 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
853 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
854 rsp.result = cpu_to_le16(result);
855 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
856 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
857 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
858 } else
859 l2cap_chan_del(sk, reason);
860 break;
861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 case BT_CONNECT:
863 case BT_DISCONN:
864 l2cap_chan_del(sk, reason);
865 break;
866
867 default:
868 sock_set_flag(sk, SOCK_ZAPPED);
869 break;
870 }
871}
872
873/* Must be called on unlocked socket. */
874static void l2cap_sock_close(struct sock *sk)
875{
876 l2cap_sock_clear_timer(sk);
877 lock_sock(sk);
878 __l2cap_sock_close(sk, ECONNRESET);
879 release_sock(sk);
880 l2cap_sock_kill(sk);
881}
882
883static void l2cap_sock_init(struct sock *sk, struct sock *parent)
884{
885 struct l2cap_pinfo *pi = l2cap_pi(sk);
886
887 BT_DBG("sk %p", sk);
888
889 if (parent) {
890 sk->sk_type = parent->sk_type;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100891 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 pi->imtu = l2cap_pi(parent)->imtu;
894 pi->omtu = l2cap_pi(parent)->omtu;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300895 pi->conf_state = l2cap_pi(parent)->conf_state;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700896 pi->mode = l2cap_pi(parent)->mode;
897 pi->fcs = l2cap_pi(parent)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -0300898 pi->max_tx = l2cap_pi(parent)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -0300899 pi->tx_win = l2cap_pi(parent)->tx_win;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100900 pi->sec_level = l2cap_pi(parent)->sec_level;
901 pi->role_switch = l2cap_pi(parent)->role_switch;
902 pi->force_reliable = l2cap_pi(parent)->force_reliable;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 } else {
904 pi->imtu = L2CAP_DEFAULT_MTU;
905 pi->omtu = 0;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300906 if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300907 pi->mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300908 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
909 } else {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300910 pi->mode = L2CAP_MODE_BASIC;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -0300911 }
Gustavo F. Padovanfd059b92010-05-10 14:22:56 -0300912 pi->max_tx = L2CAP_DEFAULT_MAX_TX;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700913 pi->fcs = L2CAP_FCS_CRC16;
Gustavo F. Padovanfd059b92010-05-10 14:22:56 -0300914 pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100915 pi->sec_level = BT_SECURITY_LOW;
916 pi->role_switch = 0;
917 pi->force_reliable = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
920 /* Default config options */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +0200921 pi->conf_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Dave Young45054dc2009-10-18 20:28:30 +0000923 skb_queue_head_init(TX_QUEUE(sk));
924 skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300925 skb_queue_head_init(BUSY_QUEUE(sk));
Dave Young45054dc2009-10-18 20:28:30 +0000926 INIT_LIST_HEAD(SREJ_LIST(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927}
928
929static struct proto l2cap_proto = {
930 .name = "L2CAP",
931 .owner = THIS_MODULE,
932 .obj_size = sizeof(struct l2cap_pinfo)
933};
934
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700935static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
937 struct sock *sk;
938
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700939 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 if (!sk)
941 return NULL;
942
943 sock_init_data(sock, sk);
944 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
945
946 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947 sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 sock_reset_flag(sk, SOCK_ZAPPED);
950
951 sk->sk_protocol = proto;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200952 sk->sk_state = BT_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200954 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 bt_sock_link(&l2cap_sk_list, sk);
957 return sk;
958}
959
Eric Paris3f378b62009-11-05 22:18:14 -0800960static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
961 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962{
963 struct sock *sk;
964
965 BT_DBG("sock %p", sock);
966
967 sock->state = SS_UNCONNECTED;
968
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300969 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
971 return -ESOCKTNOSUPPORT;
972
Eric Parisc84b3262009-11-05 20:45:52 -0800973 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 return -EPERM;
975
976 sock->ops = &l2cap_sock_ops;
977
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700978 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 if (!sk)
980 return -ENOMEM;
981
982 l2cap_sock_init(sk, NULL);
983 return 0;
984}
985
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100986static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100989 struct sockaddr_l2 la;
990 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100992 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994 if (!addr || addr->sa_family != AF_BLUETOOTH)
995 return -EINVAL;
996
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100997 memset(&la, 0, sizeof(la));
998 len = min_t(unsigned int, sizeof(la), alen);
999 memcpy(&la, addr, len);
1000
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001001 if (la.l2_cid)
1002 return -EINVAL;
1003
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 lock_sock(sk);
1005
1006 if (sk->sk_state != BT_OPEN) {
1007 err = -EBADFD;
1008 goto done;
1009 }
1010
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001011 if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
Marcel Holtmann847641d2007-01-22 22:00:45 +01001012 !capable(CAP_NET_BIND_SERVICE)) {
1013 err = -EACCES;
1014 goto done;
1015 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001016
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 write_lock_bh(&l2cap_sk_list.lock);
1018
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001019 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 err = -EADDRINUSE;
1021 } else {
1022 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001023 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
1024 l2cap_pi(sk)->psm = la.l2_psm;
1025 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001027
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001028 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
1029 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001030 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032
1033 write_unlock_bh(&l2cap_sk_list.lock);
1034
1035done:
1036 release_sock(sk);
1037 return err;
1038}
1039
1040static int l2cap_do_connect(struct sock *sk)
1041{
1042 bdaddr_t *src = &bt_sk(sk)->src;
1043 bdaddr_t *dst = &bt_sk(sk)->dst;
1044 struct l2cap_conn *conn;
1045 struct hci_conn *hcon;
1046 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001047 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001048 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001050 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
1051 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001053 hdev = hci_get_route(dst, src);
1054 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return -EHOSTUNREACH;
1056
1057 hci_dev_lock_bh(hdev);
1058
1059 err = -ENOMEM;
1060
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001061 if (sk->sk_type == SOCK_RAW) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001062 switch (l2cap_pi(sk)->sec_level) {
1063 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001064 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001065 break;
1066 case BT_SECURITY_MEDIUM:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001067 auth_type = HCI_AT_DEDICATED_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001068 break;
1069 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001070 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001071 break;
1072 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001073 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001074 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001075 auth_type = HCI_AT_NO_BONDING_MITM;
1076 else
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001077 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann435fef22009-02-09 03:55:28 +01001078
1079 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
1080 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001081 } else {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001082 switch (l2cap_pi(sk)->sec_level) {
1083 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001084 auth_type = HCI_AT_GENERAL_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001085 break;
1086 case BT_SECURITY_MEDIUM:
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001087 auth_type = HCI_AT_GENERAL_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001088 break;
1089 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001090 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001091 break;
1092 }
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001093 }
1094
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001095 hcon = hci_connect(hdev, ACL_LINK, dst,
1096 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 if (!hcon)
1098 goto done;
1099
1100 conn = l2cap_conn_add(hcon, 0);
1101 if (!conn) {
1102 hci_conn_put(hcon);
1103 goto done;
1104 }
1105
1106 err = 0;
1107
1108 /* Update source addr of the socket */
1109 bacpy(src, conn->src);
1110
1111 l2cap_chan_add(conn, sk, NULL);
1112
1113 sk->sk_state = BT_CONNECT;
1114 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1115
1116 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001117 if (sk->sk_type != SOCK_SEQPACKET &&
1118 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 l2cap_sock_clear_timer(sk);
1120 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001121 } else
1122 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 }
1124
1125done:
1126 hci_dev_unlock_bh(hdev);
1127 hci_dev_put(hdev);
1128 return err;
1129}
1130
1131static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
1132{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001134 struct sockaddr_l2 la;
1135 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 BT_DBG("sk %p", sk);
1138
Changli Gao6503d962010-03-31 22:58:26 +00001139 if (!addr || alen < sizeof(addr->sa_family) ||
1140 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001141 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001143 memset(&la, 0, sizeof(la));
1144 len = min_t(unsigned int, sizeof(la), alen);
1145 memcpy(&la, addr, len);
1146
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001147 if (la.l2_cid)
1148 return -EINVAL;
1149
1150 lock_sock(sk);
1151
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001152 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
1153 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 err = -EINVAL;
1155 goto done;
1156 }
1157
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001158 switch (l2cap_pi(sk)->mode) {
1159 case L2CAP_MODE_BASIC:
1160 break;
1161 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001162 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001163 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001164 break;
1165 /* fall through */
1166 default:
1167 err = -ENOTSUPP;
1168 goto done;
1169 }
1170
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001171 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 case BT_CONNECT:
1173 case BT_CONNECT2:
1174 case BT_CONFIG:
1175 /* Already connecting */
1176 goto wait;
1177
1178 case BT_CONNECTED:
1179 /* Already connected */
João Paulo Rechi Vita8b0dc6d2010-06-22 13:56:22 -03001180 err = -EISCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 goto done;
1182
1183 case BT_OPEN:
1184 case BT_BOUND:
1185 /* Can connect */
1186 break;
1187
1188 default:
1189 err = -EBADFD;
1190 goto done;
1191 }
1192
1193 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001194 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1195 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001197 err = l2cap_do_connect(sk);
1198 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 goto done;
1200
1201wait:
1202 err = bt_sock_wait_state(sk, BT_CONNECTED,
1203 sock_sndtimeo(sk, flags & O_NONBLOCK));
1204done:
1205 release_sock(sk);
1206 return err;
1207}
1208
1209static int l2cap_sock_listen(struct socket *sock, int backlog)
1210{
1211 struct sock *sk = sock->sk;
1212 int err = 0;
1213
1214 BT_DBG("sk %p backlog %d", sk, backlog);
1215
1216 lock_sock(sk);
1217
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001218 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1219 || sk->sk_state != BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 err = -EBADFD;
1221 goto done;
1222 }
1223
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001224 switch (l2cap_pi(sk)->mode) {
1225 case L2CAP_MODE_BASIC:
1226 break;
1227 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001228 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001229 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001230 break;
1231 /* fall through */
1232 default:
1233 err = -ENOTSUPP;
1234 goto done;
1235 }
1236
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 if (!l2cap_pi(sk)->psm) {
1238 bdaddr_t *src = &bt_sk(sk)->src;
1239 u16 psm;
1240
1241 err = -EINVAL;
1242
1243 write_lock_bh(&l2cap_sk_list.lock);
1244
1245 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001246 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1247 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1248 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 err = 0;
1250 break;
1251 }
1252
1253 write_unlock_bh(&l2cap_sk_list.lock);
1254
1255 if (err < 0)
1256 goto done;
1257 }
1258
1259 sk->sk_max_ack_backlog = backlog;
1260 sk->sk_ack_backlog = 0;
1261 sk->sk_state = BT_LISTEN;
1262
1263done:
1264 release_sock(sk);
1265 return err;
1266}
1267
1268static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
1269{
1270 DECLARE_WAITQUEUE(wait, current);
1271 struct sock *sk = sock->sk, *nsk;
1272 long timeo;
1273 int err = 0;
1274
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001275 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 if (sk->sk_state != BT_LISTEN) {
1278 err = -EBADFD;
1279 goto done;
1280 }
1281
1282 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1283
1284 BT_DBG("sk %p timeo %ld", sk, timeo);
1285
1286 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001287 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1289 set_current_state(TASK_INTERRUPTIBLE);
1290 if (!timeo) {
1291 err = -EAGAIN;
1292 break;
1293 }
1294
1295 release_sock(sk);
1296 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001297 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
1299 if (sk->sk_state != BT_LISTEN) {
1300 err = -EBADFD;
1301 break;
1302 }
1303
1304 if (signal_pending(current)) {
1305 err = sock_intr_errno(timeo);
1306 break;
1307 }
1308 }
1309 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001310 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 if (err)
1313 goto done;
1314
1315 newsock->state = SS_CONNECTED;
1316
1317 BT_DBG("new socket %p", nsk);
1318
1319done:
1320 release_sock(sk);
1321 return err;
1322}
1323
1324static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
1325{
1326 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1327 struct sock *sk = sock->sk;
1328
1329 BT_DBG("sock %p, sk %p", sock, sk);
1330
1331 addr->sa_family = AF_BLUETOOTH;
1332 *len = sizeof(struct sockaddr_l2);
1333
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001334 if (peer) {
1335 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001337 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001338 } else {
1339 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001341 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001342 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 return 0;
1345}
1346
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001347static int __l2cap_wait_ack(struct sock *sk)
1348{
1349 DECLARE_WAITQUEUE(wait, current);
1350 int err = 0;
1351 int timeo = HZ/5;
1352
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001353 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001354 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
1355 set_current_state(TASK_INTERRUPTIBLE);
1356
1357 if (!timeo)
1358 timeo = HZ/5;
1359
1360 if (signal_pending(current)) {
1361 err = sock_intr_errno(timeo);
1362 break;
1363 }
1364
1365 release_sock(sk);
1366 timeo = schedule_timeout(timeo);
1367 lock_sock(sk);
1368
1369 err = sock_error(sk);
1370 if (err)
1371 break;
1372 }
1373 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001374 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001375 return err;
1376}
1377
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001378static void l2cap_monitor_timeout(unsigned long arg)
1379{
1380 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001381
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001382 BT_DBG("sk %p", sk);
1383
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001384 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001385 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001386 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001387 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001388 return;
1389 }
1390
1391 l2cap_pi(sk)->retry_count++;
1392 __mod_monitor_timer();
1393
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001394 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001395 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001396}
1397
1398static void l2cap_retrans_timeout(unsigned long arg)
1399{
1400 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001401
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001402 BT_DBG("sk %p", sk);
1403
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001404 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001405 l2cap_pi(sk)->retry_count = 1;
1406 __mod_monitor_timer();
1407
1408 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1409
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001410 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001411 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001412}
1413
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001414static void l2cap_drop_acked_frames(struct sock *sk)
1415{
1416 struct sk_buff *skb;
1417
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001418 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1419 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001420 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1421 break;
1422
1423 skb = skb_dequeue(TX_QUEUE(sk));
1424 kfree_skb(skb);
1425
1426 l2cap_pi(sk)->unacked_frames--;
1427 }
1428
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001429 if (!l2cap_pi(sk)->unacked_frames)
1430 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001431}
1432
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001433static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001434{
1435 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001436
1437 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1438
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001439 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001440}
1441
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001442static void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001443{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001444 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001445 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001446 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001447
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001448 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1449 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001450 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001451 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001452
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001453 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001454 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1455 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001456 }
1457
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001458 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001459
1460 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001461 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001462}
1463
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001464static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001465{
1466 struct l2cap_pinfo *pi = l2cap_pi(sk);
1467 struct sk_buff *skb, *tx_skb;
1468 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001469
1470 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001471 if (!skb)
1472 return;
1473
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001474 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001475 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001476 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001477
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001478 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1479 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001480
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001481 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001482
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001483 if (pi->remote_max_tx &&
1484 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001485 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001486 return;
1487 }
1488
1489 tx_skb = skb_clone(skb, GFP_ATOMIC);
1490 bt_cb(skb)->retries++;
1491 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001492
1493 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1494 control |= L2CAP_CTRL_FINAL;
1495 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1496 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001497
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001498 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1499 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001500
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001501 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1502
1503 if (pi->fcs == L2CAP_FCS_CRC16) {
1504 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1505 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1506 }
1507
1508 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001509}
1510
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001511static int l2cap_ertm_send(struct sock *sk)
1512{
1513 struct sk_buff *skb, *tx_skb;
1514 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001515 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001516 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001518 if (sk->sk_state != BT_CONNECTED)
1519 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001520
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001521 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001523 if (pi->remote_max_tx &&
1524 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001525 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001526 break;
1527 }
1528
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001529 tx_skb = skb_clone(skb, GFP_ATOMIC);
1530
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001531 bt_cb(skb)->retries++;
1532
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001533 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001534 control &= L2CAP_CTRL_SAR;
1535
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001536 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1537 control |= L2CAP_CTRL_FINAL;
1538 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1539 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001540 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1542 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1543
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001544
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001545 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001546 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1547 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1548 }
1549
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001550 l2cap_do_send(sk, tx_skb);
1551
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001552 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553
1554 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1555 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1556
1557 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001558 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559
1560 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1561 sk->sk_send_head = NULL;
1562 else
1563 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001564
1565 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001566 }
1567
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001568 return nsent;
1569}
1570
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001571static int l2cap_retransmit_frames(struct sock *sk)
1572{
1573 struct l2cap_pinfo *pi = l2cap_pi(sk);
1574 int ret;
1575
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001576 if (!skb_queue_empty(TX_QUEUE(sk)))
1577 sk->sk_send_head = TX_QUEUE(sk)->next;
1578
1579 pi->next_tx_seq = pi->expected_ack_seq;
1580 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001581 return ret;
1582}
1583
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001584static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001585{
1586 struct sock *sk = (struct sock *)pi;
1587 u16 control = 0;
1588
1589 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1590
1591 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1592 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001593 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001594 l2cap_send_sframe(pi, control);
1595 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001596 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001597
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001598 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001599 return;
1600
1601 control |= L2CAP_SUPER_RCV_READY;
1602 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001603}
1604
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001605static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001606{
1607 struct srej_list *tail;
1608 u16 control;
1609
1610 control = L2CAP_SUPER_SELECT_REJECT;
1611 control |= L2CAP_CTRL_FINAL;
1612
1613 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1614 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1615
1616 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001617}
1618
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001619static 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 -07001620{
1621 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001622 struct sk_buff **frag;
1623 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001625 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001626 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
1628 sent += count;
1629 len -= count;
1630
1631 /* Continuation fragments (no L2CAP header) */
1632 frag = &skb_shinfo(skb)->frag_list;
1633 while (len) {
1634 count = min_t(unsigned int, conn->mtu, len);
1635
1636 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1637 if (!*frag)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001638 return -EFAULT;
1639 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1640 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
1642 sent += count;
1643 len -= count;
1644
1645 frag = &(*frag)->next;
1646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
1648 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001649}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001651static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1652{
1653 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1654 struct sk_buff *skb;
1655 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1656 struct l2cap_hdr *lh;
1657
1658 BT_DBG("sk %p len %d", sk, (int)len);
1659
1660 count = min_t(unsigned int, (conn->mtu - hlen), len);
1661 skb = bt_skb_send_alloc(sk, count + hlen,
1662 msg->msg_flags & MSG_DONTWAIT, &err);
1663 if (!skb)
1664 return ERR_PTR(-ENOMEM);
1665
1666 /* Create L2CAP header */
1667 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1668 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1669 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1670 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1671
1672 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1673 if (unlikely(err < 0)) {
1674 kfree_skb(skb);
1675 return ERR_PTR(err);
1676 }
1677 return skb;
1678}
1679
1680static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1681{
1682 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1683 struct sk_buff *skb;
1684 int err, count, hlen = L2CAP_HDR_SIZE;
1685 struct l2cap_hdr *lh;
1686
1687 BT_DBG("sk %p len %d", sk, (int)len);
1688
1689 count = min_t(unsigned int, (conn->mtu - hlen), len);
1690 skb = bt_skb_send_alloc(sk, count + hlen,
1691 msg->msg_flags & MSG_DONTWAIT, &err);
1692 if (!skb)
1693 return ERR_PTR(-ENOMEM);
1694
1695 /* Create L2CAP header */
1696 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1697 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1698 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1699
1700 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1701 if (unlikely(err < 0)) {
1702 kfree_skb(skb);
1703 return ERR_PTR(err);
1704 }
1705 return skb;
1706}
1707
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001708static 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 -03001709{
1710 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1711 struct sk_buff *skb;
1712 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1713 struct l2cap_hdr *lh;
1714
1715 BT_DBG("sk %p len %d", sk, (int)len);
1716
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001717 if (!conn)
1718 return ERR_PTR(-ENOTCONN);
1719
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001720 if (sdulen)
1721 hlen += 2;
1722
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001723 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1724 hlen += 2;
1725
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001726 count = min_t(unsigned int, (conn->mtu - hlen), len);
1727 skb = bt_skb_send_alloc(sk, count + hlen,
1728 msg->msg_flags & MSG_DONTWAIT, &err);
1729 if (!skb)
1730 return ERR_PTR(-ENOMEM);
1731
1732 /* Create L2CAP header */
1733 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1734 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1735 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1736 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001737 if (sdulen)
1738 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001739
1740 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1741 if (unlikely(err < 0)) {
1742 kfree_skb(skb);
1743 return ERR_PTR(err);
1744 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001745
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001746 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1747 put_unaligned_le16(0, skb_put(skb, 2));
1748
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001749 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001750 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751}
1752
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001753static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1754{
1755 struct l2cap_pinfo *pi = l2cap_pi(sk);
1756 struct sk_buff *skb;
1757 struct sk_buff_head sar_queue;
1758 u16 control;
1759 size_t size = 0;
1760
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001761 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001762 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001763 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001764 if (IS_ERR(skb))
1765 return PTR_ERR(skb);
1766
1767 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001768 len -= pi->remote_mps;
1769 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001770
1771 while (len > 0) {
1772 size_t buflen;
1773
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001774 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001775 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001776 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001777 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001778 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001779 buflen = len;
1780 }
1781
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001782 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001783 if (IS_ERR(skb)) {
1784 skb_queue_purge(&sar_queue);
1785 return PTR_ERR(skb);
1786 }
1787
1788 __skb_queue_tail(&sar_queue, skb);
1789 len -= buflen;
1790 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001791 }
1792 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1793 if (sk->sk_send_head == NULL)
1794 sk->sk_send_head = sar_queue.next;
1795
1796 return size;
1797}
1798
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
1800{
1801 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001802 struct l2cap_pinfo *pi = l2cap_pi(sk);
1803 struct sk_buff *skb;
1804 u16 control;
1805 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
1807 BT_DBG("sock %p, sk %p", sock, sk);
1808
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001809 err = sock_error(sk);
1810 if (err)
1811 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 if (msg->msg_flags & MSG_OOB)
1814 return -EOPNOTSUPP;
1815
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 lock_sock(sk);
1817
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001818 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001820 goto done;
1821 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001823 /* Connectionless channel */
1824 if (sk->sk_type == SOCK_DGRAM) {
1825 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001826 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001827 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001828 } else {
1829 l2cap_do_send(sk, skb);
1830 err = len;
1831 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001832 goto done;
1833 }
1834
1835 switch (pi->mode) {
1836 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001837 /* Check outgoing MTU */
1838 if (len > pi->omtu) {
João Paulo Rechi Vitaf9dd11b2010-06-22 13:56:24 -03001839 err = -EMSGSIZE;
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001840 goto done;
1841 }
1842
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001843 /* Create a basic PDU */
1844 skb = l2cap_create_basic_pdu(sk, msg, len);
1845 if (IS_ERR(skb)) {
1846 err = PTR_ERR(skb);
1847 goto done;
1848 }
1849
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001850 l2cap_do_send(sk, skb);
1851 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001852 break;
1853
1854 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001855 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001856 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001857 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001858 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001859 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001860 if (IS_ERR(skb)) {
1861 err = PTR_ERR(skb);
1862 goto done;
1863 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001864 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001865
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001866 if (sk->sk_send_head == NULL)
1867 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001868
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001869 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001870 /* Segment SDU into multiples PDUs */
1871 err = l2cap_sar_segment_sdu(sk, msg, len);
1872 if (err < 0)
1873 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001874 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001875
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001876 if (pi->mode == L2CAP_MODE_STREAMING) {
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001877 l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001878 } else {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001879 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
1880 pi->conn_state && L2CAP_CONN_WAIT_F) {
1881 err = len;
1882 break;
1883 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001884 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001885 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001886
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001887 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001888 err = len;
1889 break;
1890
1891 default:
1892 BT_DBG("bad state %1.1x", pi->mode);
João Paulo Rechi Vitabc766db22010-06-22 13:56:25 -03001893 err = -EBADFD;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001894 }
1895
1896done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 release_sock(sk);
1898 return err;
1899}
1900
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001901static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1902{
1903 struct sock *sk = sock->sk;
1904
1905 lock_sock(sk);
1906
1907 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1908 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001909 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1910 u8 buf[128];
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001911
1912 sk->sk_state = BT_CONFIG;
1913
1914 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1915 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1916 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1917 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1918 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1919 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1920
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001921 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
1922 release_sock(sk);
1923 return 0;
1924 }
1925
1926 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1927 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1928 l2cap_build_conf_req(sk, buf), buf);
1929 l2cap_pi(sk)->num_conf_req++;
1930
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001931 release_sock(sk);
1932 return 0;
1933 }
1934
1935 release_sock(sk);
1936
1937 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:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002404 *val = __le16_to_cpu(*((__le16 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 break;
2406
2407 case 4:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002408 *val = __le32_to_cpu(*((__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:
Al Viro8e036fc2007-07-29 00:16:36 -07002435 *((__le16 *) opt->val) = cpu_to_le16(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 break;
2437
2438 case 4:
Al Viro8e036fc2007-07-29 00:16:36 -07002439 *((__le32 *) opt->val) = cpu_to_le32(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;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002894 struct sock *parent, *uninitialized_var(sk);
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
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002909 /* Check if the ACL is secure enough (if not SDP) */
2910 if (psm != cpu_to_le16(0x0001) &&
2911 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002912 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002913 result = L2CAP_CR_SEC_BLOCK;
2914 goto response;
2915 }
2916
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 result = L2CAP_CR_NO_MEM;
2918
2919 /* Check for backlog size */
2920 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002921 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 goto response;
2923 }
2924
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002925 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 if (!sk)
2927 goto response;
2928
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002929 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 /* Check if we already have channel with that dcid */
2932 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002933 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 sock_set_flag(sk, SOCK_ZAPPED);
2935 l2cap_sock_kill(sk);
2936 goto response;
2937 }
2938
2939 hci_conn_hold(conn->hcon);
2940
2941 l2cap_sock_init(sk, parent);
2942 bacpy(&bt_sk(sk)->src, conn->src);
2943 bacpy(&bt_sk(sk)->dst, conn->dst);
2944 l2cap_pi(sk)->psm = psm;
2945 l2cap_pi(sk)->dcid = scid;
2946
2947 __l2cap_chan_add(conn, sk, parent);
2948 dcid = l2cap_pi(sk)->scid;
2949
2950 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2951
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 l2cap_pi(sk)->ident = cmd->ident;
2953
Marcel Holtmann984947d2009-02-06 23:35:19 +01002954 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002955 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002956 if (bt_sk(sk)->defer_setup) {
2957 sk->sk_state = BT_CONNECT2;
2958 result = L2CAP_CR_PEND;
2959 status = L2CAP_CS_AUTHOR_PEND;
2960 parent->sk_data_ready(parent, 0);
2961 } else {
2962 sk->sk_state = BT_CONFIG;
2963 result = L2CAP_CR_SUCCESS;
2964 status = L2CAP_CS_NO_INFO;
2965 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002966 } else {
2967 sk->sk_state = BT_CONNECT2;
2968 result = L2CAP_CR_PEND;
2969 status = L2CAP_CS_AUTHEN_PEND;
2970 }
2971 } else {
2972 sk->sk_state = BT_CONNECT2;
2973 result = L2CAP_CR_PEND;
2974 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 }
2976
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002977 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978
2979response:
2980 bh_unlock_sock(parent);
2981
2982sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002983 rsp.scid = cpu_to_le16(scid);
2984 rsp.dcid = cpu_to_le16(dcid);
2985 rsp.result = cpu_to_le16(result);
2986 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002988
2989 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2990 struct l2cap_info_req info;
2991 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2992
2993 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2994 conn->info_ident = l2cap_get_ident(conn);
2995
2996 mod_timer(&conn->info_timer, jiffies +
2997 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2998
2999 l2cap_send_cmd(conn, conn->info_ident,
3000 L2CAP_INFO_REQ, sizeof(info), &info);
3001 }
3002
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003003 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
3004 result == L2CAP_CR_SUCCESS) {
3005 u8 buf[128];
3006 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3007 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3008 l2cap_build_conf_req(sk, buf), buf);
3009 l2cap_pi(sk)->num_conf_req++;
3010 }
3011
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 return 0;
3013}
3014
3015static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3016{
3017 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3018 u16 scid, dcid, result, status;
3019 struct sock *sk;
3020 u8 req[128];
3021
3022 scid = __le16_to_cpu(rsp->scid);
3023 dcid = __le16_to_cpu(rsp->dcid);
3024 result = __le16_to_cpu(rsp->result);
3025 status = __le16_to_cpu(rsp->status);
3026
3027 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
3028
3029 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003030 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3031 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003032 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003034 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
3035 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003036 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 }
3038
3039 switch (result) {
3040 case L2CAP_CR_SUCCESS:
3041 sk->sk_state = BT_CONFIG;
3042 l2cap_pi(sk)->ident = 0;
3043 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003044 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
3045
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003046 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
3047 break;
3048
3049 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3050
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3052 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003053 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 break;
3055
3056 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003057 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 break;
3059
3060 default:
3061 l2cap_chan_del(sk, ECONNREFUSED);
3062 break;
3063 }
3064
3065 bh_unlock_sock(sk);
3066 return 0;
3067}
3068
Mat Martineau8c462b62010-08-24 15:35:42 -07003069static inline void set_default_fcs(struct l2cap_pinfo *pi)
3070{
3071 /* FCS is enabled only in ERTM or streaming mode, if one or both
3072 * sides request it.
3073 */
3074 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
3075 pi->fcs = L2CAP_FCS_NONE;
3076 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
3077 pi->fcs = L2CAP_FCS_CRC16;
3078}
3079
Al Viro88219a02007-07-29 00:17:25 -07003080static 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 -07003081{
3082 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3083 u16 dcid, flags;
3084 u8 rsp[64];
3085 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003086 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
3088 dcid = __le16_to_cpu(req->dcid);
3089 flags = __le16_to_cpu(req->flags);
3090
3091 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3092
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003093 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3094 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 return -ENOENT;
3096
Gustavo F. Padovanb0239c82010-09-08 14:59:44 -03003097 if (sk->sk_state == BT_DISCONN)
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003098 goto unlock;
3099
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003100 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003101 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003102 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
3103 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3104 l2cap_build_conf_rsp(sk, rsp,
3105 L2CAP_CONF_REJECT, flags), rsp);
3106 goto unlock;
3107 }
3108
3109 /* Store config. */
3110 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
3111 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112
3113 if (flags & 0x0001) {
3114 /* Incomplete config. Send empty response. */
3115 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003116 l2cap_build_conf_rsp(sk, rsp,
3117 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 goto unlock;
3119 }
3120
3121 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003122 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003123 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003124 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003128 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003129 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003130
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003131 /* Reset config buffer. */
3132 l2cap_pi(sk)->conf_len = 0;
3133
Marcel Holtmann876d9482007-10-20 13:35:42 +02003134 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
3135 goto unlock;
3136
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003138 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003139
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003141
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003142 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003143 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003144 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003145 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3146 l2cap_ertm_init(sk);
3147
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02003149 goto unlock;
3150 }
3151
3152 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003153 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003155 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003156 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 }
3158
3159unlock:
3160 bh_unlock_sock(sk);
3161 return 0;
3162}
3163
3164static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3165{
3166 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3167 u16 scid, flags, result;
3168 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003169 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
3171 scid = __le16_to_cpu(rsp->scid);
3172 flags = __le16_to_cpu(rsp->flags);
3173 result = __le16_to_cpu(rsp->result);
3174
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003175 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
3176 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003178 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3179 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 return 0;
3181
3182 switch (result) {
3183 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003184 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 break;
3186
3187 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003188 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003189 char req[64];
3190
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003191 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003192 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003193 goto done;
3194 }
3195
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003196 /* throw out any old stored conf requests */
3197 result = L2CAP_CONF_SUCCESS;
3198 len = l2cap_parse_conf_rsp(sk, rsp->data,
3199 len, req, &result);
3200 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003201 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003202 goto done;
3203 }
3204
3205 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3206 L2CAP_CONF_REQ, len, req);
3207 l2cap_pi(sk)->num_conf_req++;
3208 if (result != L2CAP_CONF_SUCCESS)
3209 goto done;
3210 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 }
3212
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003213 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003214 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003216 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 goto done;
3218 }
3219
3220 if (flags & 0x01)
3221 goto done;
3222
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3224
3225 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003226 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003227
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003229 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003230 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003231 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003232 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3233 l2cap_ertm_init(sk);
3234
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 l2cap_chan_ready(sk);
3236 }
3237
3238done:
3239 bh_unlock_sock(sk);
3240 return 0;
3241}
3242
3243static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3244{
3245 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3246 struct l2cap_disconn_rsp rsp;
3247 u16 dcid, scid;
3248 struct sock *sk;
3249
3250 scid = __le16_to_cpu(req->scid);
3251 dcid = __le16_to_cpu(req->dcid);
3252
3253 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3254
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003255 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3256 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 return 0;
3258
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003259 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3260 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3262
3263 sk->sk_shutdown = SHUTDOWN_MASK;
3264
3265 l2cap_chan_del(sk, ECONNRESET);
3266 bh_unlock_sock(sk);
3267
3268 l2cap_sock_kill(sk);
3269 return 0;
3270}
3271
3272static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3273{
3274 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3275 u16 dcid, scid;
3276 struct sock *sk;
3277
3278 scid = __le16_to_cpu(rsp->scid);
3279 dcid = __le16_to_cpu(rsp->dcid);
3280
3281 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3282
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003283 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3284 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285 return 0;
3286
3287 l2cap_chan_del(sk, 0);
3288 bh_unlock_sock(sk);
3289
3290 l2cap_sock_kill(sk);
3291 return 0;
3292}
3293
3294static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3295{
3296 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297 u16 type;
3298
3299 type = __le16_to_cpu(req->type);
3300
3301 BT_DBG("type 0x%4.4x", type);
3302
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003303 if (type == L2CAP_IT_FEAT_MASK) {
3304 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003305 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003306 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3307 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3308 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003309 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003310 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3311 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003312 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003313 l2cap_send_cmd(conn, cmd->ident,
3314 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003315 } else if (type == L2CAP_IT_FIXED_CHAN) {
3316 u8 buf[12];
3317 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3318 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3319 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3320 memcpy(buf + 4, l2cap_fixed_chan, 8);
3321 l2cap_send_cmd(conn, cmd->ident,
3322 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003323 } else {
3324 struct l2cap_info_rsp rsp;
3325 rsp.type = cpu_to_le16(type);
3326 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3327 l2cap_send_cmd(conn, cmd->ident,
3328 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
3331 return 0;
3332}
3333
3334static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3335{
3336 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3337 u16 type, result;
3338
3339 type = __le16_to_cpu(rsp->type);
3340 result = __le16_to_cpu(rsp->result);
3341
3342 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3343
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003344 del_timer(&conn->info_timer);
3345
Ville Tervoadb08ed2010-08-04 09:43:33 +03003346 if (result != L2CAP_IR_SUCCESS) {
3347 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3348 conn->info_ident = 0;
3349
3350 l2cap_conn_start(conn);
3351
3352 return 0;
3353 }
3354
Marcel Holtmann984947d2009-02-06 23:35:19 +01003355 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003356 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003357
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003358 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003359 struct l2cap_info_req req;
3360 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3361
3362 conn->info_ident = l2cap_get_ident(conn);
3363
3364 l2cap_send_cmd(conn, conn->info_ident,
3365 L2CAP_INFO_REQ, sizeof(req), &req);
3366 } else {
3367 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3368 conn->info_ident = 0;
3369
3370 l2cap_conn_start(conn);
3371 }
3372 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003373 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003374 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003375
3376 l2cap_conn_start(conn);
3377 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003378
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 return 0;
3380}
3381
3382static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3383{
3384 u8 *data = skb->data;
3385 int len = skb->len;
3386 struct l2cap_cmd_hdr cmd;
3387 int err = 0;
3388
3389 l2cap_raw_recv(conn, skb);
3390
3391 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003392 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3394 data += L2CAP_CMD_HDR_SIZE;
3395 len -= L2CAP_CMD_HDR_SIZE;
3396
Al Viro88219a02007-07-29 00:17:25 -07003397 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398
Al Viro88219a02007-07-29 00:17:25 -07003399 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 -07003400
Al Viro88219a02007-07-29 00:17:25 -07003401 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402 BT_DBG("corrupted command");
3403 break;
3404 }
3405
3406 switch (cmd.code) {
3407 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003408 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 break;
3410
3411 case L2CAP_CONN_REQ:
3412 err = l2cap_connect_req(conn, &cmd, data);
3413 break;
3414
3415 case L2CAP_CONN_RSP:
3416 err = l2cap_connect_rsp(conn, &cmd, data);
3417 break;
3418
3419 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003420 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 break;
3422
3423 case L2CAP_CONF_RSP:
3424 err = l2cap_config_rsp(conn, &cmd, data);
3425 break;
3426
3427 case L2CAP_DISCONN_REQ:
3428 err = l2cap_disconnect_req(conn, &cmd, data);
3429 break;
3430
3431 case L2CAP_DISCONN_RSP:
3432 err = l2cap_disconnect_rsp(conn, &cmd, data);
3433 break;
3434
3435 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003436 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 break;
3438
3439 case L2CAP_ECHO_RSP:
3440 break;
3441
3442 case L2CAP_INFO_REQ:
3443 err = l2cap_information_req(conn, &cmd, data);
3444 break;
3445
3446 case L2CAP_INFO_RSP:
3447 err = l2cap_information_rsp(conn, &cmd, data);
3448 break;
3449
3450 default:
3451 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3452 err = -EINVAL;
3453 break;
3454 }
3455
3456 if (err) {
3457 struct l2cap_cmd_rej rej;
3458 BT_DBG("error %d", err);
3459
3460 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003461 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3463 }
3464
Al Viro88219a02007-07-29 00:17:25 -07003465 data += cmd_len;
3466 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 }
3468
3469 kfree_skb(skb);
3470}
3471
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003472static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3473{
3474 u16 our_fcs, rcv_fcs;
3475 int hdr_size = L2CAP_HDR_SIZE + 2;
3476
3477 if (pi->fcs == L2CAP_FCS_CRC16) {
3478 skb_trim(skb, skb->len - 2);
3479 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3480 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3481
3482 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003483 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003484 }
3485 return 0;
3486}
3487
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003488static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3489{
3490 struct l2cap_pinfo *pi = l2cap_pi(sk);
3491 u16 control = 0;
3492
3493 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003494
3495 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3496
3497 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003498 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003499 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003500 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003501 }
3502
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003503 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3504 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003505
3506 l2cap_ertm_send(sk);
3507
3508 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3509 pi->frames_sent == 0) {
3510 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003511 l2cap_send_sframe(pi, control);
3512 }
3513}
3514
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003515static 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 -03003516{
3517 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003518 struct l2cap_pinfo *pi = l2cap_pi(sk);
3519 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003520
3521 bt_cb(skb)->tx_seq = tx_seq;
3522 bt_cb(skb)->sar = sar;
3523
3524 next_skb = skb_peek(SREJ_QUEUE(sk));
3525 if (!next_skb) {
3526 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003527 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003528 }
3529
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003530 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3531 if (tx_seq_offset < 0)
3532 tx_seq_offset += 64;
3533
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003534 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003535 if (bt_cb(next_skb)->tx_seq == tx_seq)
3536 return -EINVAL;
3537
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003538 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3539 pi->buffer_seq) % 64;
3540 if (next_tx_seq_offset < 0)
3541 next_tx_seq_offset += 64;
3542
3543 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003544 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003545 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003546 }
3547
3548 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3549 break;
3550
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003551 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003552
3553 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003554
3555 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003556}
3557
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003558static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3559{
3560 struct l2cap_pinfo *pi = l2cap_pi(sk);
3561 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003562 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003563
3564 switch (control & L2CAP_CTRL_SAR) {
3565 case L2CAP_SDU_UNSEGMENTED:
3566 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3567 goto drop;
3568
3569 err = sock_queue_rcv_skb(sk, skb);
3570 if (!err)
3571 return err;
3572
3573 break;
3574
3575 case L2CAP_SDU_START:
3576 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3577 goto drop;
3578
3579 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003580
3581 if (pi->sdu_len > pi->imtu)
3582 goto disconnect;
3583
3584 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003585 if (!pi->sdu)
3586 return -ENOMEM;
3587
3588 /* pull sdu_len bytes only after alloc, because of Local Busy
3589 * condition we have to be sure that this will be executed
3590 * only once, i.e., when alloc does not fail */
3591 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003592
3593 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3594
3595 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3596 pi->partial_sdu_len = skb->len;
3597 break;
3598
3599 case L2CAP_SDU_CONTINUE:
3600 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3601 goto disconnect;
3602
3603 if (!pi->sdu)
3604 goto disconnect;
3605
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003606 pi->partial_sdu_len += skb->len;
3607 if (pi->partial_sdu_len > pi->sdu_len)
3608 goto drop;
3609
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003610 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3611
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003612 break;
3613
3614 case L2CAP_SDU_END:
3615 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3616 goto disconnect;
3617
3618 if (!pi->sdu)
3619 goto disconnect;
3620
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003621 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003622 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003623
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003624 if (pi->partial_sdu_len > pi->imtu)
3625 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003626
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003627 if (pi->partial_sdu_len != pi->sdu_len)
3628 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003629
3630 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003631 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003632
3633 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003634 if (!_skb) {
3635 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3636 return -ENOMEM;
3637 }
3638
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003639 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003640 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003641 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003642 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3643 return err;
3644 }
3645
3646 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3647 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003648
3649 kfree_skb(pi->sdu);
3650 break;
3651 }
3652
3653 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003654 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003655
3656drop:
3657 kfree_skb(pi->sdu);
3658 pi->sdu = NULL;
3659
3660disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003661 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003662 kfree_skb(skb);
3663 return 0;
3664}
3665
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003666static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003667{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003668 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003669 struct sk_buff *skb;
3670 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003671 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003672
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003673 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3674 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3675 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3676 if (err < 0) {
3677 skb_queue_head(BUSY_QUEUE(sk), skb);
3678 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003679 }
3680
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003681 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003682 }
3683
3684 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3685 goto done;
3686
3687 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3688 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3689 l2cap_send_sframe(pi, control);
3690 l2cap_pi(sk)->retry_count = 1;
3691
3692 del_timer(&pi->retrans_timer);
3693 __mod_monitor_timer();
3694
3695 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3696
3697done:
3698 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3699 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3700
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003701 BT_DBG("sk %p, Exit local busy", sk);
3702
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003703 return 0;
3704}
3705
3706static void l2cap_busy_work(struct work_struct *work)
3707{
3708 DECLARE_WAITQUEUE(wait, current);
3709 struct l2cap_pinfo *pi =
3710 container_of(work, struct l2cap_pinfo, busy_work);
3711 struct sock *sk = (struct sock *)pi;
3712 int n_tries = 0, timeo = HZ/5, err;
3713 struct sk_buff *skb;
3714
3715 lock_sock(sk);
3716
3717 add_wait_queue(sk_sleep(sk), &wait);
3718 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3719 set_current_state(TASK_INTERRUPTIBLE);
3720
3721 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3722 err = -EBUSY;
3723 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3724 break;
3725 }
3726
3727 if (!timeo)
3728 timeo = HZ/5;
3729
3730 if (signal_pending(current)) {
3731 err = sock_intr_errno(timeo);
3732 break;
3733 }
3734
3735 release_sock(sk);
3736 timeo = schedule_timeout(timeo);
3737 lock_sock(sk);
3738
3739 err = sock_error(sk);
3740 if (err)
3741 break;
3742
3743 if (l2cap_try_push_rx_skb(sk) == 0)
3744 break;
3745 }
3746
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003747 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003748 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003749
3750 release_sock(sk);
3751}
3752
3753static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3754{
3755 struct l2cap_pinfo *pi = l2cap_pi(sk);
3756 int sctrl, err;
3757
3758 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3759 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3760 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003761 return l2cap_try_push_rx_skb(sk);
3762
3763
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764 }
3765
3766 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3767 if (err >= 0) {
3768 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3769 return err;
3770 }
3771
3772 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003773 BT_DBG("sk %p, Enter local busy", sk);
3774
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003775 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3776 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3777 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3778
3779 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3780 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3781 l2cap_send_sframe(pi, sctrl);
3782
3783 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3784
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003785 del_timer(&pi->ack_timer);
3786
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003787 queue_work(_busy_wq, &pi->busy_work);
3788
3789 return err;
3790}
3791
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003792static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003793{
3794 struct l2cap_pinfo *pi = l2cap_pi(sk);
3795 struct sk_buff *_skb;
3796 int err = -EINVAL;
3797
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003798 /*
3799 * TODO: We have to notify the userland if some data is lost with the
3800 * Streaming Mode.
3801 */
3802
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003803 switch (control & L2CAP_CTRL_SAR) {
3804 case L2CAP_SDU_UNSEGMENTED:
3805 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3806 kfree_skb(pi->sdu);
3807 break;
3808 }
3809
3810 err = sock_queue_rcv_skb(sk, skb);
3811 if (!err)
3812 return 0;
3813
3814 break;
3815
3816 case L2CAP_SDU_START:
3817 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3818 kfree_skb(pi->sdu);
3819 break;
3820 }
3821
3822 pi->sdu_len = get_unaligned_le16(skb->data);
3823 skb_pull(skb, 2);
3824
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003825 if (pi->sdu_len > pi->imtu) {
3826 err = -EMSGSIZE;
3827 break;
3828 }
3829
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003830 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3831 if (!pi->sdu) {
3832 err = -ENOMEM;
3833 break;
3834 }
3835
3836 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3837
3838 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3839 pi->partial_sdu_len = skb->len;
3840 err = 0;
3841 break;
3842
3843 case L2CAP_SDU_CONTINUE:
3844 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3845 break;
3846
3847 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3848
3849 pi->partial_sdu_len += skb->len;
3850 if (pi->partial_sdu_len > pi->sdu_len)
3851 kfree_skb(pi->sdu);
3852 else
3853 err = 0;
3854
3855 break;
3856
3857 case L2CAP_SDU_END:
3858 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3859 break;
3860
3861 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3862
3863 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3864 pi->partial_sdu_len += skb->len;
3865
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003866 if (pi->partial_sdu_len > pi->imtu)
3867 goto drop;
3868
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003869 if (pi->partial_sdu_len == pi->sdu_len) {
3870 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3871 err = sock_queue_rcv_skb(sk, _skb);
3872 if (err < 0)
3873 kfree_skb(_skb);
3874 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003875 err = 0;
3876
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003877drop:
3878 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003879 break;
3880 }
3881
3882 kfree_skb(skb);
3883 return err;
3884}
3885
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003886static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3887{
3888 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003889 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003890
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003891 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003892 if (bt_cb(skb)->tx_seq != tx_seq)
3893 break;
3894
3895 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003896 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003897 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003898 l2cap_pi(sk)->buffer_seq_srej =
3899 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003900 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003901 }
3902}
3903
3904static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3905{
3906 struct l2cap_pinfo *pi = l2cap_pi(sk);
3907 struct srej_list *l, *tmp;
3908 u16 control;
3909
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003910 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003911 if (l->tx_seq == tx_seq) {
3912 list_del(&l->list);
3913 kfree(l);
3914 return;
3915 }
3916 control = L2CAP_SUPER_SELECT_REJECT;
3917 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3918 l2cap_send_sframe(pi, control);
3919 list_del(&l->list);
3920 list_add_tail(&l->list, SREJ_LIST(sk));
3921 }
3922}
3923
3924static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3925{
3926 struct l2cap_pinfo *pi = l2cap_pi(sk);
3927 struct srej_list *new;
3928 u16 control;
3929
3930 while (tx_seq != pi->expected_tx_seq) {
3931 control = L2CAP_SUPER_SELECT_REJECT;
3932 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3933 l2cap_send_sframe(pi, control);
3934
3935 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003936 new->tx_seq = pi->expected_tx_seq;
3937 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003938 list_add_tail(&new->list, SREJ_LIST(sk));
3939 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003940 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003941}
3942
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003943static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3944{
3945 struct l2cap_pinfo *pi = l2cap_pi(sk);
3946 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003947 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003948 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003949 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003950 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003951 int err = 0;
3952
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003953 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3954 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003955
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003956 if (L2CAP_CTRL_FINAL & rx_control &&
3957 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003958 del_timer(&pi->monitor_timer);
3959 if (pi->unacked_frames > 0)
3960 __mod_retrans_timer();
3961 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3962 }
3963
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003964 pi->expected_ack_seq = req_seq;
3965 l2cap_drop_acked_frames(sk);
3966
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003967 if (tx_seq == pi->expected_tx_seq)
3968 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003969
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003970 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3971 if (tx_seq_offset < 0)
3972 tx_seq_offset += 64;
3973
3974 /* invalid tx_seq */
3975 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003976 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003977 goto drop;
3978 }
3979
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003980 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3981 goto drop;
3982
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003983 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3984 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003985
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003986 first = list_first_entry(SREJ_LIST(sk),
3987 struct srej_list, list);
3988 if (tx_seq == first->tx_seq) {
3989 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3990 l2cap_check_srej_gap(sk, tx_seq);
3991
3992 list_del(&first->list);
3993 kfree(first);
3994
3995 if (list_empty(SREJ_LIST(sk))) {
3996 pi->buffer_seq = pi->buffer_seq_srej;
3997 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003998 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003999 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004000 }
4001 } else {
4002 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004003
4004 /* duplicated tx_seq */
4005 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
4006 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004007
4008 list_for_each_entry(l, SREJ_LIST(sk), list) {
4009 if (l->tx_seq == tx_seq) {
4010 l2cap_resend_srejframe(sk, tx_seq);
4011 return 0;
4012 }
4013 }
4014 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004015 }
4016 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004017 expected_tx_seq_offset =
4018 (pi->expected_tx_seq - pi->buffer_seq) % 64;
4019 if (expected_tx_seq_offset < 0)
4020 expected_tx_seq_offset += 64;
4021
4022 /* duplicated tx_seq */
4023 if (tx_seq_offset < expected_tx_seq_offset)
4024 goto drop;
4025
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004026 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004027
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004028 BT_DBG("sk %p, Enter SREJ", sk);
4029
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004030 INIT_LIST_HEAD(SREJ_LIST(sk));
4031 pi->buffer_seq_srej = pi->buffer_seq;
4032
4033 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004034 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004035 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
4036
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004037 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
4038
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004039 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03004040
4041 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004042 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004043 return 0;
4044
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004045expected:
4046 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4047
4048 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03004049 bt_cb(skb)->tx_seq = tx_seq;
4050 bt_cb(skb)->sar = sar;
4051 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004052 return 0;
4053 }
4054
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004055 err = l2cap_push_rx_skb(sk, skb, rx_control);
4056 if (err < 0)
4057 return 0;
4058
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004059 if (rx_control & L2CAP_CTRL_FINAL) {
4060 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4061 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004062 else
4063 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004064 }
4065
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004066 __mod_ack_timer();
4067
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03004068 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
4069 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004070 l2cap_send_ack(pi);
4071
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004072 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004073
4074drop:
4075 kfree_skb(skb);
4076 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004077}
4078
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004079static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004080{
4081 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004082
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004083 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
4084 rx_control);
4085
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004086 pi->expected_ack_seq = __get_reqseq(rx_control);
4087 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004088
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004089 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004090 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004091 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4092 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4093 (pi->unacked_frames > 0))
4094 __mod_retrans_timer();
4095
4096 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4097 l2cap_send_srejtail(sk);
4098 } else {
4099 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004100 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004101
4102 } else if (rx_control & L2CAP_CTRL_FINAL) {
4103 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004104
4105 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4106 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004107 else
4108 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004109
4110 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004111 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4112 (pi->unacked_frames > 0))
4113 __mod_retrans_timer();
4114
4115 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004116 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004117 l2cap_send_ack(pi);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004118 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004119 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004120 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004121 }
4122}
4123
4124static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
4125{
4126 struct l2cap_pinfo *pi = l2cap_pi(sk);
4127 u8 tx_seq = __get_reqseq(rx_control);
4128
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004129 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4130
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004131 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4132
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03004133 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004134 l2cap_drop_acked_frames(sk);
4135
4136 if (rx_control & L2CAP_CTRL_FINAL) {
4137 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4138 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004139 else
4140 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004141 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004142 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004143
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03004144 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004145 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004146 }
4147}
4148static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
4149{
4150 struct l2cap_pinfo *pi = l2cap_pi(sk);
4151 u8 tx_seq = __get_reqseq(rx_control);
4152
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004153 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4154
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004155 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4156
4157 if (rx_control & L2CAP_CTRL_POLL) {
4158 pi->expected_ack_seq = tx_seq;
4159 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004160
4161 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004162 l2cap_retransmit_one_frame(sk, tx_seq);
4163
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004164 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004165
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004166 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4167 pi->srej_save_reqseq = tx_seq;
4168 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4169 }
4170 } else if (rx_control & L2CAP_CTRL_FINAL) {
4171 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
4172 pi->srej_save_reqseq == tx_seq)
4173 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
4174 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004175 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004176 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004177 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004178 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4179 pi->srej_save_reqseq = tx_seq;
4180 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4181 }
4182 }
4183}
4184
4185static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
4186{
4187 struct l2cap_pinfo *pi = l2cap_pi(sk);
4188 u8 tx_seq = __get_reqseq(rx_control);
4189
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004190 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4191
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004192 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
4193 pi->expected_ack_seq = tx_seq;
4194 l2cap_drop_acked_frames(sk);
4195
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004196 if (rx_control & L2CAP_CTRL_POLL)
4197 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
4198
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004199 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
4200 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03004201 if (rx_control & L2CAP_CTRL_POLL)
4202 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004203 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004204 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004205
4206 if (rx_control & L2CAP_CTRL_POLL)
4207 l2cap_send_srejtail(sk);
4208 else
4209 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004210}
4211
4212static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
4213{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004214 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
4215
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03004216 if (L2CAP_CTRL_FINAL & rx_control &&
4217 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004218 del_timer(&l2cap_pi(sk)->monitor_timer);
4219 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004220 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004221 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004222 }
4223
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004224 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
4225 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004226 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004227 break;
4228
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004229 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004230 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004231 break;
4232
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004233 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004234 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004235 break;
4236
4237 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004238 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004239 break;
4240 }
4241
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004242 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004243 return 0;
4244}
4245
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004246static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4247{
4248 struct l2cap_pinfo *pi = l2cap_pi(sk);
4249 u16 control;
4250 u8 req_seq;
4251 int len, next_tx_seq_offset, req_seq_offset;
4252
4253 control = get_unaligned_le16(skb->data);
4254 skb_pull(skb, 2);
4255 len = skb->len;
4256
4257 /*
4258 * We can just drop the corrupted I-frame here.
4259 * Receiver will miss it and start proper recovery
4260 * procedures and ask retransmission.
4261 */
4262 if (l2cap_check_fcs(pi, skb))
4263 goto drop;
4264
4265 if (__is_sar_start(control) && __is_iframe(control))
4266 len -= 2;
4267
4268 if (pi->fcs == L2CAP_FCS_CRC16)
4269 len -= 2;
4270
4271 if (len > pi->mps) {
4272 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4273 goto drop;
4274 }
4275
4276 req_seq = __get_reqseq(control);
4277 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4278 if (req_seq_offset < 0)
4279 req_seq_offset += 64;
4280
4281 next_tx_seq_offset =
4282 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4283 if (next_tx_seq_offset < 0)
4284 next_tx_seq_offset += 64;
4285
4286 /* check for invalid req-seq */
4287 if (req_seq_offset > next_tx_seq_offset) {
4288 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4289 goto drop;
4290 }
4291
4292 if (__is_iframe(control)) {
4293 if (len < 0) {
4294 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4295 goto drop;
4296 }
4297
4298 l2cap_data_channel_iframe(sk, control, skb);
4299 } else {
4300 if (len != 0) {
4301 BT_ERR("%d", len);
4302 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4303 goto drop;
4304 }
4305
4306 l2cap_data_channel_sframe(sk, control, skb);
4307 }
4308
4309 return 0;
4310
4311drop:
4312 kfree_skb(skb);
4313 return 0;
4314}
4315
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4317{
4318 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004319 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004320 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004321 u8 tx_seq;
4322 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323
4324 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4325 if (!sk) {
4326 BT_DBG("unknown cid 0x%4.4x", cid);
4327 goto drop;
4328 }
4329
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004330 pi = l2cap_pi(sk);
4331
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 BT_DBG("sk %p, len %d", sk, skb->len);
4333
4334 if (sk->sk_state != BT_CONNECTED)
4335 goto drop;
4336
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004337 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004338 case L2CAP_MODE_BASIC:
4339 /* If socket recv buffers overflows we drop data here
4340 * which is *bad* because L2CAP has to be reliable.
4341 * But we don't have any other choice. L2CAP doesn't
4342 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004344 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004345 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004347 if (!sock_queue_rcv_skb(sk, skb))
4348 goto done;
4349 break;
4350
4351 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004352 if (!sock_owned_by_user(sk)) {
4353 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004354 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004355 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004356 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004357 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004358
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004359 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004360
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004361 case L2CAP_MODE_STREAMING:
4362 control = get_unaligned_le16(skb->data);
4363 skb_pull(skb, 2);
4364 len = skb->len;
4365
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004366 if (l2cap_check_fcs(pi, skb))
4367 goto drop;
4368
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004369 if (__is_sar_start(control))
4370 len -= 2;
4371
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004372 if (pi->fcs == L2CAP_FCS_CRC16)
4373 len -= 2;
4374
Nathan Holstein51893f82010-06-09 15:46:25 -04004375 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004376 goto drop;
4377
4378 tx_seq = __get_txseq(control);
4379
4380 if (pi->expected_tx_seq == tx_seq)
4381 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4382 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004383 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004384
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004385 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004386
4387 goto done;
4388
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004389 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004390 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004391 break;
4392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393
4394drop:
4395 kfree_skb(skb);
4396
4397done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004398 if (sk)
4399 bh_unlock_sock(sk);
4400
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 return 0;
4402}
4403
Al Viro8e036fc2007-07-29 00:16:36 -07004404static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405{
4406 struct sock *sk;
4407
4408 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4409 if (!sk)
4410 goto drop;
4411
4412 BT_DBG("sk %p, len %d", sk, skb->len);
4413
4414 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4415 goto drop;
4416
4417 if (l2cap_pi(sk)->imtu < skb->len)
4418 goto drop;
4419
4420 if (!sock_queue_rcv_skb(sk, skb))
4421 goto done;
4422
4423drop:
4424 kfree_skb(skb);
4425
4426done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004427 if (sk)
4428 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 return 0;
4430}
4431
4432static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4433{
4434 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004435 u16 cid, len;
4436 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
4438 skb_pull(skb, L2CAP_HDR_SIZE);
4439 cid = __le16_to_cpu(lh->cid);
4440 len = __le16_to_cpu(lh->len);
4441
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004442 if (len != skb->len) {
4443 kfree_skb(skb);
4444 return;
4445 }
4446
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4448
4449 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004450 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 l2cap_sig_channel(conn, skb);
4452 break;
4453
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004454 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004455 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 skb_pull(skb, 2);
4457 l2cap_conless_channel(conn, psm, skb);
4458 break;
4459
4460 default:
4461 l2cap_data_channel(conn, cid, skb);
4462 break;
4463 }
4464}
4465
4466/* ---- L2CAP interface with lower layer (HCI) ---- */
4467
4468static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4469{
4470 int exact = 0, lm1 = 0, lm2 = 0;
4471 register struct sock *sk;
4472 struct hlist_node *node;
4473
4474 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004475 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476
4477 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4478
4479 /* Find listening sockets and check their link_mode */
4480 read_lock(&l2cap_sk_list.lock);
4481 sk_for_each(sk, node, &l2cap_sk_list.head) {
4482 if (sk->sk_state != BT_LISTEN)
4483 continue;
4484
4485 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004486 lm1 |= HCI_LM_ACCEPT;
4487 if (l2cap_pi(sk)->role_switch)
4488 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004490 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4491 lm2 |= HCI_LM_ACCEPT;
4492 if (l2cap_pi(sk)->role_switch)
4493 lm2 |= HCI_LM_MASTER;
4494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 }
4496 read_unlock(&l2cap_sk_list.lock);
4497
4498 return exact ? lm1 : lm2;
4499}
4500
4501static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4502{
Marcel Holtmann01394182006-07-03 10:02:46 +02004503 struct l2cap_conn *conn;
4504
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4506
4507 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004508 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509
4510 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511 conn = l2cap_conn_add(hcon, status);
4512 if (conn)
4513 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004514 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 l2cap_conn_del(hcon, bt_err(status));
4516
4517 return 0;
4518}
4519
Marcel Holtmann2950f212009-02-12 14:02:50 +01004520static int l2cap_disconn_ind(struct hci_conn *hcon)
4521{
4522 struct l2cap_conn *conn = hcon->l2cap_data;
4523
4524 BT_DBG("hcon %p", hcon);
4525
4526 if (hcon->type != ACL_LINK || !conn)
4527 return 0x13;
4528
4529 return conn->disc_reason;
4530}
4531
4532static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533{
4534 BT_DBG("hcon %p reason %d", hcon, reason);
4535
4536 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004537 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538
4539 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004540
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 return 0;
4542}
4543
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004544static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4545{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004546 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004547 return;
4548
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004549 if (encrypt == 0x00) {
4550 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4551 l2cap_sock_clear_timer(sk);
4552 l2cap_sock_set_timer(sk, HZ * 5);
4553 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4554 __l2cap_sock_close(sk, ECONNREFUSED);
4555 } else {
4556 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4557 l2cap_sock_clear_timer(sk);
4558 }
4559}
4560
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004561static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562{
4563 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004564 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566
Marcel Holtmann01394182006-07-03 10:02:46 +02004567 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004569
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 l = &conn->chan_list;
4571
4572 BT_DBG("conn %p", conn);
4573
4574 read_lock(&l->lock);
4575
4576 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4577 bh_lock_sock(sk);
4578
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004579 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4580 bh_unlock_sock(sk);
4581 continue;
4582 }
4583
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004584 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004585 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004586 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004587 bh_unlock_sock(sk);
4588 continue;
4589 }
4590
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004591 if (sk->sk_state == BT_CONNECT) {
4592 if (!status) {
4593 struct l2cap_conn_req req;
4594 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4595 req.psm = l2cap_pi(sk)->psm;
4596
4597 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004598 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004599
4600 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4601 L2CAP_CONN_REQ, sizeof(req), &req);
4602 } else {
4603 l2cap_sock_clear_timer(sk);
4604 l2cap_sock_set_timer(sk, HZ / 10);
4605 }
4606 } else if (sk->sk_state == BT_CONNECT2) {
4607 struct l2cap_conn_rsp rsp;
4608 __u16 result;
4609
4610 if (!status) {
4611 sk->sk_state = BT_CONFIG;
4612 result = L2CAP_CR_SUCCESS;
4613 } else {
4614 sk->sk_state = BT_DISCONN;
4615 l2cap_sock_set_timer(sk, HZ / 10);
4616 result = L2CAP_CR_SEC_BLOCK;
4617 }
4618
4619 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4620 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4621 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004622 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004623 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4624 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 }
4626
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 bh_unlock_sock(sk);
4628 }
4629
4630 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004631
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 return 0;
4633}
4634
4635static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4636{
4637 struct l2cap_conn *conn = hcon->l2cap_data;
4638
4639 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
4640 goto drop;
4641
4642 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4643
4644 if (flags & ACL_START) {
4645 struct l2cap_hdr *hdr;
4646 int len;
4647
4648 if (conn->rx_len) {
4649 BT_ERR("Unexpected start frame (len %d)", skb->len);
4650 kfree_skb(conn->rx_skb);
4651 conn->rx_skb = NULL;
4652 conn->rx_len = 0;
4653 l2cap_conn_unreliable(conn, ECOMM);
4654 }
4655
4656 if (skb->len < 2) {
4657 BT_ERR("Frame is too short (len %d)", skb->len);
4658 l2cap_conn_unreliable(conn, ECOMM);
4659 goto drop;
4660 }
4661
4662 hdr = (struct l2cap_hdr *) skb->data;
4663 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
4664
4665 if (len == skb->len) {
4666 /* Complete frame received */
4667 l2cap_recv_frame(conn, skb);
4668 return 0;
4669 }
4670
4671 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4672
4673 if (skb->len > len) {
4674 BT_ERR("Frame is too long (len %d, expected len %d)",
4675 skb->len, len);
4676 l2cap_conn_unreliable(conn, ECOMM);
4677 goto drop;
4678 }
4679
4680 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004681 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4682 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683 goto drop;
4684
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004685 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004686 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687 conn->rx_len = len - skb->len;
4688 } else {
4689 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4690
4691 if (!conn->rx_len) {
4692 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4693 l2cap_conn_unreliable(conn, ECOMM);
4694 goto drop;
4695 }
4696
4697 if (skb->len > conn->rx_len) {
4698 BT_ERR("Fragment is too long (len %d, expected %d)",
4699 skb->len, conn->rx_len);
4700 kfree_skb(conn->rx_skb);
4701 conn->rx_skb = NULL;
4702 conn->rx_len = 0;
4703 l2cap_conn_unreliable(conn, ECOMM);
4704 goto drop;
4705 }
4706
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004707 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004708 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709 conn->rx_len -= skb->len;
4710
4711 if (!conn->rx_len) {
4712 /* Complete frame received */
4713 l2cap_recv_frame(conn, conn->rx_skb);
4714 conn->rx_skb = NULL;
4715 }
4716 }
4717
4718drop:
4719 kfree_skb(skb);
4720 return 0;
4721}
4722
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004723static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724{
4725 struct sock *sk;
4726 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727
4728 read_lock_bh(&l2cap_sk_list.lock);
4729
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004730 sk_for_each(sk, node, &l2cap_sk_list.head) {
4731 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004733 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4734 batostr(&bt_sk(sk)->src),
4735 batostr(&bt_sk(sk)->dst),
4736 sk->sk_state, __le16_to_cpu(pi->psm),
4737 pi->scid, pi->dcid,
4738 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004742
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004743 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744}
4745
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004746static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4747{
4748 return single_open(file, l2cap_debugfs_show, inode->i_private);
4749}
4750
4751static const struct file_operations l2cap_debugfs_fops = {
4752 .open = l2cap_debugfs_open,
4753 .read = seq_read,
4754 .llseek = seq_lseek,
4755 .release = single_release,
4756};
4757
4758static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004760static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004761 .family = PF_BLUETOOTH,
4762 .owner = THIS_MODULE,
4763 .release = l2cap_sock_release,
4764 .bind = l2cap_sock_bind,
4765 .connect = l2cap_sock_connect,
4766 .listen = l2cap_sock_listen,
4767 .accept = l2cap_sock_accept,
4768 .getname = l2cap_sock_getname,
4769 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004770 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004772 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773 .mmap = sock_no_mmap,
4774 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775 .shutdown = l2cap_sock_shutdown,
4776 .setsockopt = l2cap_sock_setsockopt,
4777 .getsockopt = l2cap_sock_getsockopt
4778};
4779
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004780static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781 .family = PF_BLUETOOTH,
4782 .owner = THIS_MODULE,
4783 .create = l2cap_sock_create,
4784};
4785
4786static struct hci_proto l2cap_hci_proto = {
4787 .name = "L2CAP",
4788 .id = HCI_PROTO_L2CAP,
4789 .connect_ind = l2cap_connect_ind,
4790 .connect_cfm = l2cap_connect_cfm,
4791 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004792 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004793 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794 .recv_acldata = l2cap_recv_acldata
4795};
4796
4797static int __init l2cap_init(void)
4798{
4799 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004800
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801 err = proto_register(&l2cap_proto, 0);
4802 if (err < 0)
4803 return err;
4804
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004805 _busy_wq = create_singlethread_workqueue("l2cap");
4806 if (!_busy_wq)
4807 goto error;
4808
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4810 if (err < 0) {
4811 BT_ERR("L2CAP socket registration failed");
4812 goto error;
4813 }
4814
4815 err = hci_register_proto(&l2cap_hci_proto);
4816 if (err < 0) {
4817 BT_ERR("L2CAP protocol registration failed");
4818 bt_sock_unregister(BTPROTO_L2CAP);
4819 goto error;
4820 }
4821
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004822 if (bt_debugfs) {
4823 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4824 bt_debugfs, NULL, &l2cap_debugfs_fops);
4825 if (!l2cap_debugfs)
4826 BT_ERR("Failed to create L2CAP debug file");
4827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828
4829 BT_INFO("L2CAP ver %s", VERSION);
4830 BT_INFO("L2CAP socket layer initialized");
4831
4832 return 0;
4833
4834error:
4835 proto_unregister(&l2cap_proto);
4836 return err;
4837}
4838
4839static void __exit l2cap_exit(void)
4840{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004841 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004842
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004843 flush_workqueue(_busy_wq);
4844 destroy_workqueue(_busy_wq);
4845
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4847 BT_ERR("L2CAP socket unregistration failed");
4848
4849 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4850 BT_ERR("L2CAP protocol unregistration failed");
4851
4852 proto_unregister(&l2cap_proto);
4853}
4854
4855void l2cap_load(void)
4856{
4857 /* Dummy function to trigger automatic L2CAP module loading by
4858 * other modules that use L2CAP sockets but don't use any other
4859 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004860}
4861EXPORT_SYMBOL(l2cap_load);
4862
4863module_init(l2cap_init);
4864module_exit(l2cap_exit);
4865
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004866module_param(disable_ertm, bool, 0644);
4867MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004868
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004869MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4871MODULE_VERSION(VERSION);
4872MODULE_LICENSE("GPL");
4873MODULE_ALIAS("bt-proto-0");