blob: f2062aace406aa7a80a81e7a9a6a7b3818a9834f [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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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. Padovanaf05b302009-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:
Marcel Holtmann0878b662007-05-05 00:35:59 +02001953 opts.imtu = l2cap_pi(sk)->imtu;
1954 opts.omtu = l2cap_pi(sk)->omtu;
1955 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001956 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001957 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001958 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001959 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 len = min_t(unsigned int, sizeof(opts), optlen);
1962 if (copy_from_user((char *) &opts, optval, len)) {
1963 err = -EFAULT;
1964 break;
1965 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001966
Gustavo F. Padovan45d65c42010-06-07 19:21:30 -03001967 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
1968 err = -EINVAL;
1969 break;
1970 }
1971
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001972 l2cap_pi(sk)->mode = opts.mode;
1973 switch (l2cap_pi(sk)->mode) {
1974 case L2CAP_MODE_BASIC:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001975 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001976 break;
1977 case L2CAP_MODE_ERTM:
1978 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001979 if (!disable_ertm)
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001980 break;
1981 /* fall through */
1982 default:
1983 err = -EINVAL;
1984 break;
1985 }
1986
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001987 l2cap_pi(sk)->imtu = opts.imtu;
1988 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001989 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001990 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001991 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 break;
1993
1994 case L2CAP_LM:
1995 if (get_user(opt, (u32 __user *) optval)) {
1996 err = -EFAULT;
1997 break;
1998 }
1999
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002000 if (opt & L2CAP_LM_AUTH)
2001 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
2002 if (opt & L2CAP_LM_ENCRYPT)
2003 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
2004 if (opt & L2CAP_LM_SECURE)
2005 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
2006
2007 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
2008 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 break;
2010
2011 default:
2012 err = -ENOPROTOOPT;
2013 break;
2014 }
2015
2016 release_sock(sk);
2017 return err;
2018}
2019
David S. Millerb7058842009-09-30 16:12:20 -07002020static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002021{
2022 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002023 struct bt_security sec;
2024 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002025 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002026
2027 BT_DBG("sk %p", sk);
2028
2029 if (level == SOL_L2CAP)
2030 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
2031
Marcel Holtmann0588d942009-01-16 10:06:13 +01002032 if (level != SOL_BLUETOOTH)
2033 return -ENOPROTOOPT;
2034
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002035 lock_sock(sk);
2036
2037 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002038 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002039 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2040 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002041 err = -EINVAL;
2042 break;
2043 }
2044
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002045 sec.level = BT_SECURITY_LOW;
2046
2047 len = min_t(unsigned int, sizeof(sec), optlen);
2048 if (copy_from_user((char *) &sec, optval, len)) {
2049 err = -EFAULT;
2050 break;
2051 }
2052
2053 if (sec.level < BT_SECURITY_LOW ||
2054 sec.level > BT_SECURITY_HIGH) {
2055 err = -EINVAL;
2056 break;
2057 }
2058
2059 l2cap_pi(sk)->sec_level = sec.level;
2060 break;
2061
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002062 case BT_DEFER_SETUP:
2063 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2064 err = -EINVAL;
2065 break;
2066 }
2067
2068 if (get_user(opt, (u32 __user *) optval)) {
2069 err = -EFAULT;
2070 break;
2071 }
2072
2073 bt_sk(sk)->defer_setup = opt;
2074 break;
2075
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002076 default:
2077 err = -ENOPROTOOPT;
2078 break;
2079 }
2080
2081 release_sock(sk);
2082 return err;
2083}
2084
2085static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086{
2087 struct sock *sk = sock->sk;
2088 struct l2cap_options opts;
2089 struct l2cap_conninfo cinfo;
2090 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002091 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
2093 BT_DBG("sk %p", sk);
2094
2095 if (get_user(len, optlen))
2096 return -EFAULT;
2097
2098 lock_sock(sk);
2099
2100 switch (optname) {
2101 case L2CAP_OPTIONS:
2102 opts.imtu = l2cap_pi(sk)->imtu;
2103 opts.omtu = l2cap_pi(sk)->omtu;
2104 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07002105 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002106 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002107 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002108 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
2110 len = min_t(unsigned int, len, sizeof(opts));
2111 if (copy_to_user(optval, (char *) &opts, len))
2112 err = -EFAULT;
2113
2114 break;
2115
2116 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002117 switch (l2cap_pi(sk)->sec_level) {
2118 case BT_SECURITY_LOW:
2119 opt = L2CAP_LM_AUTH;
2120 break;
2121 case BT_SECURITY_MEDIUM:
2122 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
2123 break;
2124 case BT_SECURITY_HIGH:
2125 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
2126 L2CAP_LM_SECURE;
2127 break;
2128 default:
2129 opt = 0;
2130 break;
2131 }
2132
2133 if (l2cap_pi(sk)->role_switch)
2134 opt |= L2CAP_LM_MASTER;
2135
2136 if (l2cap_pi(sk)->force_reliable)
2137 opt |= L2CAP_LM_RELIABLE;
2138
2139 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 err = -EFAULT;
2141 break;
2142
2143 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002144 if (sk->sk_state != BT_CONNECTED &&
2145 !(sk->sk_state == BT_CONNECT2 &&
2146 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 err = -ENOTCONN;
2148 break;
2149 }
2150
2151 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
2152 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
2153
2154 len = min_t(unsigned int, len, sizeof(cinfo));
2155 if (copy_to_user(optval, (char *) &cinfo, len))
2156 err = -EFAULT;
2157
2158 break;
2159
2160 default:
2161 err = -ENOPROTOOPT;
2162 break;
2163 }
2164
2165 release_sock(sk);
2166 return err;
2167}
2168
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002169static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
2170{
2171 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002172 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002173 int len, err = 0;
2174
2175 BT_DBG("sk %p", sk);
2176
2177 if (level == SOL_L2CAP)
2178 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
2179
Marcel Holtmann0588d942009-01-16 10:06:13 +01002180 if (level != SOL_BLUETOOTH)
2181 return -ENOPROTOOPT;
2182
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002183 if (get_user(len, optlen))
2184 return -EFAULT;
2185
2186 lock_sock(sk);
2187
2188 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002189 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002190 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2191 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002192 err = -EINVAL;
2193 break;
2194 }
2195
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002196 sec.level = l2cap_pi(sk)->sec_level;
2197
2198 len = min_t(unsigned int, len, sizeof(sec));
2199 if (copy_to_user(optval, (char *) &sec, len))
2200 err = -EFAULT;
2201
2202 break;
2203
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002204 case BT_DEFER_SETUP:
2205 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2206 err = -EINVAL;
2207 break;
2208 }
2209
2210 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
2211 err = -EFAULT;
2212
2213 break;
2214
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002215 default:
2216 err = -ENOPROTOOPT;
2217 break;
2218 }
2219
2220 release_sock(sk);
2221 return err;
2222}
2223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224static int l2cap_sock_shutdown(struct socket *sock, int how)
2225{
2226 struct sock *sk = sock->sk;
2227 int err = 0;
2228
2229 BT_DBG("sock %p, sk %p", sock, sk);
2230
2231 if (!sk)
2232 return 0;
2233
2234 lock_sock(sk);
2235 if (!sk->sk_shutdown) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03002236 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2237 err = __l2cap_wait_ack(sk);
2238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 sk->sk_shutdown = SHUTDOWN_MASK;
2240 l2cap_sock_clear_timer(sk);
2241 __l2cap_sock_close(sk, 0);
2242
2243 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002244 err = bt_sock_wait_state(sk, BT_CLOSED,
2245 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 }
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002247
2248 if (!err && sk->sk_err)
2249 err = -sk->sk_err;
2250
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 release_sock(sk);
2252 return err;
2253}
2254
2255static int l2cap_sock_release(struct socket *sock)
2256{
2257 struct sock *sk = sock->sk;
2258 int err;
2259
2260 BT_DBG("sock %p, sk %p", sock, sk);
2261
2262 if (!sk)
2263 return 0;
2264
2265 err = l2cap_sock_shutdown(sock, 2);
2266
2267 sock_orphan(sk);
2268 l2cap_sock_kill(sk);
2269 return err;
2270}
2271
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272static void l2cap_chan_ready(struct sock *sk)
2273{
2274 struct sock *parent = bt_sk(sk)->parent;
2275
2276 BT_DBG("sk %p, parent %p", sk, parent);
2277
2278 l2cap_pi(sk)->conf_state = 0;
2279 l2cap_sock_clear_timer(sk);
2280
2281 if (!parent) {
2282 /* Outgoing channel.
2283 * Wake up socket sleeping on connect.
2284 */
2285 sk->sk_state = BT_CONNECTED;
2286 sk->sk_state_change(sk);
2287 } else {
2288 /* Incoming channel.
2289 * Wake up socket sleeping on accept.
2290 */
2291 parent->sk_data_ready(parent, 0);
2292 }
2293}
2294
2295/* Copy frame to all raw sockets on that connection */
2296static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2297{
2298 struct l2cap_chan_list *l = &conn->chan_list;
2299 struct sk_buff *nskb;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002300 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
2302 BT_DBG("conn %p", conn);
2303
2304 read_lock(&l->lock);
2305 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2306 if (sk->sk_type != SOCK_RAW)
2307 continue;
2308
2309 /* Don't send frame to the socket it came from */
2310 if (skb->sk == sk)
2311 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002312 nskb = skb_clone(skb, GFP_ATOMIC);
2313 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 continue;
2315
2316 if (sock_queue_rcv_skb(sk, nskb))
2317 kfree_skb(nskb);
2318 }
2319 read_unlock(&l->lock);
2320}
2321
2322/* ---- L2CAP signalling commands ---- */
2323static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2324 u8 code, u8 ident, u16 dlen, void *data)
2325{
2326 struct sk_buff *skb, **frag;
2327 struct l2cap_cmd_hdr *cmd;
2328 struct l2cap_hdr *lh;
2329 int len, count;
2330
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002331 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2332 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
2334 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2335 count = min_t(unsigned int, conn->mtu, len);
2336
2337 skb = bt_skb_alloc(count, GFP_ATOMIC);
2338 if (!skb)
2339 return NULL;
2340
2341 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002342 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002343 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
2345 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2346 cmd->code = code;
2347 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002348 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
2350 if (dlen) {
2351 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2352 memcpy(skb_put(skb, count), data, count);
2353 data += count;
2354 }
2355
2356 len -= skb->len;
2357
2358 /* Continuation fragments (no L2CAP header) */
2359 frag = &skb_shinfo(skb)->frag_list;
2360 while (len) {
2361 count = min_t(unsigned int, conn->mtu, len);
2362
2363 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2364 if (!*frag)
2365 goto fail;
2366
2367 memcpy(skb_put(*frag, count), data, count);
2368
2369 len -= count;
2370 data += count;
2371
2372 frag = &(*frag)->next;
2373 }
2374
2375 return skb;
2376
2377fail:
2378 kfree_skb(skb);
2379 return NULL;
2380}
2381
2382static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2383{
2384 struct l2cap_conf_opt *opt = *ptr;
2385 int len;
2386
2387 len = L2CAP_CONF_OPT_SIZE + opt->len;
2388 *ptr += len;
2389
2390 *type = opt->type;
2391 *olen = opt->len;
2392
2393 switch (opt->len) {
2394 case 1:
2395 *val = *((u8 *) opt->val);
2396 break;
2397
2398 case 2:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002399 *val = __le16_to_cpu(*((__le16 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 break;
2401
2402 case 4:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002403 *val = __le32_to_cpu(*((__le32 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 break;
2405
2406 default:
2407 *val = (unsigned long) opt->val;
2408 break;
2409 }
2410
2411 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2412 return len;
2413}
2414
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2416{
2417 struct l2cap_conf_opt *opt = *ptr;
2418
2419 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2420
2421 opt->type = type;
2422 opt->len = len;
2423
2424 switch (len) {
2425 case 1:
2426 *((u8 *) opt->val) = val;
2427 break;
2428
2429 case 2:
Al Viro8e036fc2007-07-29 00:16:36 -07002430 *((__le16 *) opt->val) = cpu_to_le16(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 break;
2432
2433 case 4:
Al Viro8e036fc2007-07-29 00:16:36 -07002434 *((__le32 *) opt->val) = cpu_to_le32(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 break;
2436
2437 default:
2438 memcpy(opt->val, (void *) val, len);
2439 break;
2440 }
2441
2442 *ptr += L2CAP_CONF_OPT_SIZE + len;
2443}
2444
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002445static void l2cap_ack_timeout(unsigned long arg)
2446{
2447 struct sock *sk = (void *) arg;
2448
2449 bh_lock_sock(sk);
2450 l2cap_send_ack(l2cap_pi(sk));
2451 bh_unlock_sock(sk);
2452}
2453
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002454static inline void l2cap_ertm_init(struct sock *sk)
2455{
2456 l2cap_pi(sk)->expected_ack_seq = 0;
2457 l2cap_pi(sk)->unacked_frames = 0;
2458 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002459 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002460 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002461
2462 setup_timer(&l2cap_pi(sk)->retrans_timer,
2463 l2cap_retrans_timeout, (unsigned long) sk);
2464 setup_timer(&l2cap_pi(sk)->monitor_timer,
2465 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002466 setup_timer(&l2cap_pi(sk)->ack_timer,
2467 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002468
2469 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002470 __skb_queue_head_init(BUSY_QUEUE(sk));
2471
2472 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03002473
2474 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002475}
2476
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002477static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2478{
2479 switch (mode) {
2480 case L2CAP_MODE_STREAMING:
2481 case L2CAP_MODE_ERTM:
2482 if (l2cap_mode_supported(mode, remote_feat_mask))
2483 return mode;
2484 /* fall through */
2485 default:
2486 return L2CAP_MODE_BASIC;
2487 }
2488}
2489
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490static int l2cap_build_conf_req(struct sock *sk, void *data)
2491{
2492 struct l2cap_pinfo *pi = l2cap_pi(sk);
2493 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002494 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 void *ptr = req->data;
2496
2497 BT_DBG("sk %p", sk);
2498
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002499 if (pi->num_conf_req || pi->num_conf_rsp)
2500 goto done;
2501
2502 switch (pi->mode) {
2503 case L2CAP_MODE_STREAMING:
2504 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002505 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002506 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002507
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002508 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002509 default:
2510 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2511 break;
2512 }
2513
2514done:
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002515 switch (pi->mode) {
2516 case L2CAP_MODE_BASIC:
2517 if (pi->imtu != L2CAP_DEFAULT_MTU)
2518 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002519
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002520 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2521 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
2522 break;
2523
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002524 rfc.mode = L2CAP_MODE_BASIC;
2525 rfc.txwin_size = 0;
2526 rfc.max_transmit = 0;
2527 rfc.retrans_timeout = 0;
2528 rfc.monitor_timeout = 0;
2529 rfc.max_pdu_size = 0;
2530
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002531 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2532 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002533 break;
2534
2535 case L2CAP_MODE_ERTM:
2536 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002537 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002538 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002539 rfc.retrans_timeout = 0;
2540 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002541 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002542 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002543 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002544
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002545 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2546 (unsigned long) &rfc);
2547
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002548 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2549 break;
2550
2551 if (pi->fcs == L2CAP_FCS_NONE ||
2552 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2553 pi->fcs = L2CAP_FCS_NONE;
2554 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2555 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002556 break;
2557
2558 case L2CAP_MODE_STREAMING:
2559 rfc.mode = L2CAP_MODE_STREAMING;
2560 rfc.txwin_size = 0;
2561 rfc.max_transmit = 0;
2562 rfc.retrans_timeout = 0;
2563 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002564 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002565 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002566 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002567
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002568 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2569 (unsigned long) &rfc);
2570
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002571 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2572 break;
2573
2574 if (pi->fcs == L2CAP_FCS_NONE ||
2575 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2576 pi->fcs = L2CAP_FCS_NONE;
2577 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2578 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002579 break;
2580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581
2582 /* FIXME: Need actual value of the flush timeout */
2583 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2584 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2585
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002586 req->dcid = cpu_to_le16(pi->dcid);
2587 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
2589 return ptr - data;
2590}
2591
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002592static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593{
2594 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002595 struct l2cap_conf_rsp *rsp = data;
2596 void *ptr = rsp->data;
2597 void *req = pi->conf_req;
2598 int len = pi->conf_len;
2599 int type, hint, olen;
2600 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002601 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002602 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002603 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002605 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002606
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002607 while (len >= L2CAP_CONF_OPT_SIZE) {
2608 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002610 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002611 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002612
2613 switch (type) {
2614 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002615 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002616 break;
2617
2618 case L2CAP_CONF_FLUSH_TO:
2619 pi->flush_to = val;
2620 break;
2621
2622 case L2CAP_CONF_QOS:
2623 break;
2624
Marcel Holtmann6464f352007-10-20 13:39:51 +02002625 case L2CAP_CONF_RFC:
2626 if (olen == sizeof(rfc))
2627 memcpy(&rfc, (void *) val, olen);
2628 break;
2629
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002630 case L2CAP_CONF_FCS:
2631 if (val == L2CAP_FCS_NONE)
2632 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2633
2634 break;
2635
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002636 default:
2637 if (hint)
2638 break;
2639
2640 result = L2CAP_CONF_UNKNOWN;
2641 *((u8 *) ptr++) = type;
2642 break;
2643 }
2644 }
2645
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002646 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 goto done;
2648
2649 switch (pi->mode) {
2650 case L2CAP_MODE_STREAMING:
2651 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002652 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
2653 pi->mode = l2cap_select_mode(rfc.mode,
2654 pi->conn->feat_mask);
2655 break;
2656 }
2657
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002658 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002659 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002660
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002661 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002662 }
2663
2664done:
2665 if (pi->mode != rfc.mode) {
2666 result = L2CAP_CONF_UNACCEPT;
2667 rfc.mode = pi->mode;
2668
2669 if (pi->num_conf_rsp == 1)
2670 return -ECONNREFUSED;
2671
2672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2673 sizeof(rfc), (unsigned long) &rfc);
2674 }
2675
2676
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002677 if (result == L2CAP_CONF_SUCCESS) {
2678 /* Configure output options and let the other side know
2679 * which ones we don't like. */
2680
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002681 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2682 result = L2CAP_CONF_UNACCEPT;
2683 else {
2684 pi->omtu = mtu;
2685 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2686 }
2687 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002688
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002689 switch (rfc.mode) {
2690 case L2CAP_MODE_BASIC:
2691 pi->fcs = L2CAP_FCS_NONE;
2692 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2693 break;
2694
2695 case L2CAP_MODE_ERTM:
2696 pi->remote_tx_win = rfc.txwin_size;
2697 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002698
2699 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2700 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002701
2702 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002703
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002704 rfc.retrans_timeout =
2705 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2706 rfc.monitor_timeout =
2707 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002708
2709 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002710
2711 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2712 sizeof(rfc), (unsigned long) &rfc);
2713
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002714 break;
2715
2716 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07002717 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2718 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002719
2720 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002721
2722 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002723
2724 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2725 sizeof(rfc), (unsigned long) &rfc);
2726
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002727 break;
2728
2729 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002730 result = L2CAP_CONF_UNACCEPT;
2731
2732 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002733 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002734 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002735
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002736 if (result == L2CAP_CONF_SUCCESS)
2737 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2738 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002739 rsp->scid = cpu_to_le16(pi->dcid);
2740 rsp->result = cpu_to_le16(result);
2741 rsp->flags = cpu_to_le16(0x0000);
2742
2743 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744}
2745
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002746static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2747{
2748 struct l2cap_pinfo *pi = l2cap_pi(sk);
2749 struct l2cap_conf_req *req = data;
2750 void *ptr = req->data;
2751 int type, olen;
2752 unsigned long val;
2753 struct l2cap_conf_rfc rfc;
2754
2755 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2756
2757 while (len >= L2CAP_CONF_OPT_SIZE) {
2758 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2759
2760 switch (type) {
2761 case L2CAP_CONF_MTU:
2762 if (val < L2CAP_DEFAULT_MIN_MTU) {
2763 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002764 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002765 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002766 pi->imtu = val;
2767 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002768 break;
2769
2770 case L2CAP_CONF_FLUSH_TO:
2771 pi->flush_to = val;
2772 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2773 2, pi->flush_to);
2774 break;
2775
2776 case L2CAP_CONF_RFC:
2777 if (olen == sizeof(rfc))
2778 memcpy(&rfc, (void *)val, olen);
2779
2780 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2781 rfc.mode != pi->mode)
2782 return -ECONNREFUSED;
2783
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002784 pi->fcs = 0;
2785
2786 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2787 sizeof(rfc), (unsigned long) &rfc);
2788 break;
2789 }
2790 }
2791
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002792 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
2793 return -ECONNREFUSED;
2794
2795 pi->mode = rfc.mode;
2796
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002797 if (*result == L2CAP_CONF_SUCCESS) {
2798 switch (rfc.mode) {
2799 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002800 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2801 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002802 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002803 break;
2804 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002805 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002806 }
2807 }
2808
2809 req->dcid = cpu_to_le16(pi->dcid);
2810 req->flags = cpu_to_le16(0x0000);
2811
2812 return ptr - data;
2813}
2814
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002815static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816{
2817 struct l2cap_conf_rsp *rsp = data;
2818 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002820 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002822 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002823 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002824 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
2826 return ptr - data;
2827}
2828
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002829static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2830{
2831 struct l2cap_pinfo *pi = l2cap_pi(sk);
2832 int type, olen;
2833 unsigned long val;
2834 struct l2cap_conf_rfc rfc;
2835
2836 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2837
2838 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2839 return;
2840
2841 while (len >= L2CAP_CONF_OPT_SIZE) {
2842 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2843
2844 switch (type) {
2845 case L2CAP_CONF_RFC:
2846 if (olen == sizeof(rfc))
2847 memcpy(&rfc, (void *)val, olen);
2848 goto done;
2849 }
2850 }
2851
2852done:
2853 switch (rfc.mode) {
2854 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002855 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2856 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002857 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2858 break;
2859 case L2CAP_MODE_STREAMING:
2860 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2861 }
2862}
2863
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002864static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2865{
2866 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2867
2868 if (rej->reason != 0x0000)
2869 return 0;
2870
2871 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2872 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002873 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002874
2875 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002876 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002877
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002878 l2cap_conn_start(conn);
2879 }
2880
2881 return 0;
2882}
2883
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2885{
2886 struct l2cap_chan_list *list = &conn->chan_list;
2887 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2888 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002889 struct sock *parent, *uninitialized_var(sk);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002890 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891
2892 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002893 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
2895 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2896
2897 /* Check if we have socket listening on psm */
2898 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2899 if (!parent) {
2900 result = L2CAP_CR_BAD_PSM;
2901 goto sendresp;
2902 }
2903
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002904 /* Check if the ACL is secure enough (if not SDP) */
2905 if (psm != cpu_to_le16(0x0001) &&
2906 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002907 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002908 result = L2CAP_CR_SEC_BLOCK;
2909 goto response;
2910 }
2911
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 result = L2CAP_CR_NO_MEM;
2913
2914 /* Check for backlog size */
2915 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002916 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 goto response;
2918 }
2919
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002920 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 if (!sk)
2922 goto response;
2923
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002924 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
2926 /* Check if we already have channel with that dcid */
2927 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002928 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 sock_set_flag(sk, SOCK_ZAPPED);
2930 l2cap_sock_kill(sk);
2931 goto response;
2932 }
2933
2934 hci_conn_hold(conn->hcon);
2935
2936 l2cap_sock_init(sk, parent);
2937 bacpy(&bt_sk(sk)->src, conn->src);
2938 bacpy(&bt_sk(sk)->dst, conn->dst);
2939 l2cap_pi(sk)->psm = psm;
2940 l2cap_pi(sk)->dcid = scid;
2941
2942 __l2cap_chan_add(conn, sk, parent);
2943 dcid = l2cap_pi(sk)->scid;
2944
2945 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2946
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 l2cap_pi(sk)->ident = cmd->ident;
2948
Marcel Holtmann984947d2009-02-06 23:35:19 +01002949 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002950 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002951 if (bt_sk(sk)->defer_setup) {
2952 sk->sk_state = BT_CONNECT2;
2953 result = L2CAP_CR_PEND;
2954 status = L2CAP_CS_AUTHOR_PEND;
2955 parent->sk_data_ready(parent, 0);
2956 } else {
2957 sk->sk_state = BT_CONFIG;
2958 result = L2CAP_CR_SUCCESS;
2959 status = L2CAP_CS_NO_INFO;
2960 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002961 } else {
2962 sk->sk_state = BT_CONNECT2;
2963 result = L2CAP_CR_PEND;
2964 status = L2CAP_CS_AUTHEN_PEND;
2965 }
2966 } else {
2967 sk->sk_state = BT_CONNECT2;
2968 result = L2CAP_CR_PEND;
2969 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 }
2971
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002972 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973
2974response:
2975 bh_unlock_sock(parent);
2976
2977sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002978 rsp.scid = cpu_to_le16(scid);
2979 rsp.dcid = cpu_to_le16(dcid);
2980 rsp.result = cpu_to_le16(result);
2981 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002983
2984 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2985 struct l2cap_info_req info;
2986 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2987
2988 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2989 conn->info_ident = l2cap_get_ident(conn);
2990
2991 mod_timer(&conn->info_timer, jiffies +
2992 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2993
2994 l2cap_send_cmd(conn, conn->info_ident,
2995 L2CAP_INFO_REQ, sizeof(info), &info);
2996 }
2997
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002998 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
2999 result == L2CAP_CR_SUCCESS) {
3000 u8 buf[128];
3001 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3002 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3003 l2cap_build_conf_req(sk, buf), buf);
3004 l2cap_pi(sk)->num_conf_req++;
3005 }
3006
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return 0;
3008}
3009
3010static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3011{
3012 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3013 u16 scid, dcid, result, status;
3014 struct sock *sk;
3015 u8 req[128];
3016
3017 scid = __le16_to_cpu(rsp->scid);
3018 dcid = __le16_to_cpu(rsp->dcid);
3019 result = __le16_to_cpu(rsp->result);
3020 status = __le16_to_cpu(rsp->status);
3021
3022 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
3023
3024 if (scid) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003025 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3026 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003027 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 } else {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003029 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
3030 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003031 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 }
3033
3034 switch (result) {
3035 case L2CAP_CR_SUCCESS:
3036 sk->sk_state = BT_CONFIG;
3037 l2cap_pi(sk)->ident = 0;
3038 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003039 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
3040
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003041 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
3042 break;
3043
3044 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3045
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3047 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003048 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 break;
3050
3051 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003052 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 break;
3054
3055 default:
3056 l2cap_chan_del(sk, ECONNREFUSED);
3057 break;
3058 }
3059
3060 bh_unlock_sock(sk);
3061 return 0;
3062}
3063
Mat Martineau8c462b62010-08-24 15:35:42 -07003064static inline void set_default_fcs(struct l2cap_pinfo *pi)
3065{
3066 /* FCS is enabled only in ERTM or streaming mode, if one or both
3067 * sides request it.
3068 */
3069 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
3070 pi->fcs = L2CAP_FCS_NONE;
3071 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
3072 pi->fcs = L2CAP_FCS_CRC16;
3073}
3074
Al Viro88219a02007-07-29 00:17:25 -07003075static 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 -07003076{
3077 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3078 u16 dcid, flags;
3079 u8 rsp[64];
3080 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003081 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
3083 dcid = __le16_to_cpu(req->dcid);
3084 flags = __le16_to_cpu(req->flags);
3085
3086 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3087
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003088 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3089 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 return -ENOENT;
3091
Gustavo F. Padovan8cb8e6f2010-06-14 02:26:15 -03003092 if (sk->sk_state != BT_CONFIG) {
3093 struct l2cap_cmd_rej rej;
3094
3095 rej.reason = cpu_to_le16(0x0002);
3096 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3097 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003098 goto unlock;
Gustavo F. Padovan8cb8e6f2010-06-14 02:26:15 -03003099 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003100
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003101 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003102 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003103 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
3104 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3105 l2cap_build_conf_rsp(sk, rsp,
3106 L2CAP_CONF_REJECT, flags), rsp);
3107 goto unlock;
3108 }
3109
3110 /* Store config. */
3111 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
3112 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113
3114 if (flags & 0x0001) {
3115 /* Incomplete config. Send empty response. */
3116 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003117 l2cap_build_conf_rsp(sk, rsp,
3118 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 goto unlock;
3120 }
3121
3122 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003123 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003124 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003125 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003129 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003130 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003131
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003132 /* Reset config buffer. */
3133 l2cap_pi(sk)->conf_len = 0;
3134
Marcel Holtmann876d9482007-10-20 13:35:42 +02003135 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
3136 goto unlock;
3137
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003139 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003140
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003142
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003143 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003144 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003145 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003146 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3147 l2cap_ertm_init(sk);
3148
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02003150 goto unlock;
3151 }
3152
3153 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003154 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003156 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003157 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 }
3159
3160unlock:
3161 bh_unlock_sock(sk);
3162 return 0;
3163}
3164
3165static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3166{
3167 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3168 u16 scid, flags, result;
3169 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003170 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171
3172 scid = __le16_to_cpu(rsp->scid);
3173 flags = __le16_to_cpu(rsp->flags);
3174 result = __le16_to_cpu(rsp->result);
3175
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003176 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
3177 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003179 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3180 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 return 0;
3182
3183 switch (result) {
3184 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003185 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 break;
3187
3188 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003189 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003190 char req[64];
3191
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003192 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003193 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003194 goto done;
3195 }
3196
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003197 /* throw out any old stored conf requests */
3198 result = L2CAP_CONF_SUCCESS;
3199 len = l2cap_parse_conf_rsp(sk, rsp->data,
3200 len, req, &result);
3201 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003202 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003203 goto done;
3204 }
3205
3206 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3207 L2CAP_CONF_REQ, len, req);
3208 l2cap_pi(sk)->num_conf_req++;
3209 if (result != L2CAP_CONF_SUCCESS)
3210 goto done;
3211 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 }
3213
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003214 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003215 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003217 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 goto done;
3219 }
3220
3221 if (flags & 0x01)
3222 goto done;
3223
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3225
3226 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003227 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003228
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003230 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003231 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003232 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003233 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3234 l2cap_ertm_init(sk);
3235
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 l2cap_chan_ready(sk);
3237 }
3238
3239done:
3240 bh_unlock_sock(sk);
3241 return 0;
3242}
3243
3244static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3245{
3246 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3247 struct l2cap_disconn_rsp rsp;
3248 u16 dcid, scid;
3249 struct sock *sk;
3250
3251 scid = __le16_to_cpu(req->scid);
3252 dcid = __le16_to_cpu(req->dcid);
3253
3254 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3255
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003256 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3257 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 return 0;
3259
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003260 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3261 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3263
3264 sk->sk_shutdown = SHUTDOWN_MASK;
3265
3266 l2cap_chan_del(sk, ECONNRESET);
3267 bh_unlock_sock(sk);
3268
3269 l2cap_sock_kill(sk);
3270 return 0;
3271}
3272
3273static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3274{
3275 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3276 u16 dcid, scid;
3277 struct sock *sk;
3278
3279 scid = __le16_to_cpu(rsp->scid);
3280 dcid = __le16_to_cpu(rsp->dcid);
3281
3282 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3283
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003284 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3285 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286 return 0;
3287
3288 l2cap_chan_del(sk, 0);
3289 bh_unlock_sock(sk);
3290
3291 l2cap_sock_kill(sk);
3292 return 0;
3293}
3294
3295static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3296{
3297 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 u16 type;
3299
3300 type = __le16_to_cpu(req->type);
3301
3302 BT_DBG("type 0x%4.4x", type);
3303
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003304 if (type == L2CAP_IT_FEAT_MASK) {
3305 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003306 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003307 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3308 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3309 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003310 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003311 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3312 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003313 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003314 l2cap_send_cmd(conn, cmd->ident,
3315 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003316 } else if (type == L2CAP_IT_FIXED_CHAN) {
3317 u8 buf[12];
3318 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3319 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3320 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3321 memcpy(buf + 4, l2cap_fixed_chan, 8);
3322 l2cap_send_cmd(conn, cmd->ident,
3323 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003324 } else {
3325 struct l2cap_info_rsp rsp;
3326 rsp.type = cpu_to_le16(type);
3327 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3328 l2cap_send_cmd(conn, cmd->ident,
3329 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3330 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331
3332 return 0;
3333}
3334
3335static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3336{
3337 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3338 u16 type, result;
3339
3340 type = __le16_to_cpu(rsp->type);
3341 result = __le16_to_cpu(rsp->result);
3342
3343 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3344
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003345 del_timer(&conn->info_timer);
3346
Ville Tervoadb08ed2010-08-04 09:43:33 +03003347 if (result != L2CAP_IR_SUCCESS) {
3348 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3349 conn->info_ident = 0;
3350
3351 l2cap_conn_start(conn);
3352
3353 return 0;
3354 }
3355
Marcel Holtmann984947d2009-02-06 23:35:19 +01003356 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003357 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003358
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003359 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003360 struct l2cap_info_req req;
3361 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3362
3363 conn->info_ident = l2cap_get_ident(conn);
3364
3365 l2cap_send_cmd(conn, conn->info_ident,
3366 L2CAP_INFO_REQ, sizeof(req), &req);
3367 } else {
3368 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3369 conn->info_ident = 0;
3370
3371 l2cap_conn_start(conn);
3372 }
3373 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003374 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003375 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003376
3377 l2cap_conn_start(conn);
3378 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003379
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 return 0;
3381}
3382
3383static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3384{
3385 u8 *data = skb->data;
3386 int len = skb->len;
3387 struct l2cap_cmd_hdr cmd;
3388 int err = 0;
3389
3390 l2cap_raw_recv(conn, skb);
3391
3392 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003393 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3395 data += L2CAP_CMD_HDR_SIZE;
3396 len -= L2CAP_CMD_HDR_SIZE;
3397
Al Viro88219a02007-07-29 00:17:25 -07003398 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399
Al Viro88219a02007-07-29 00:17:25 -07003400 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 -07003401
Al Viro88219a02007-07-29 00:17:25 -07003402 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403 BT_DBG("corrupted command");
3404 break;
3405 }
3406
3407 switch (cmd.code) {
3408 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003409 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 break;
3411
3412 case L2CAP_CONN_REQ:
3413 err = l2cap_connect_req(conn, &cmd, data);
3414 break;
3415
3416 case L2CAP_CONN_RSP:
3417 err = l2cap_connect_rsp(conn, &cmd, data);
3418 break;
3419
3420 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003421 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 break;
3423
3424 case L2CAP_CONF_RSP:
3425 err = l2cap_config_rsp(conn, &cmd, data);
3426 break;
3427
3428 case L2CAP_DISCONN_REQ:
3429 err = l2cap_disconnect_req(conn, &cmd, data);
3430 break;
3431
3432 case L2CAP_DISCONN_RSP:
3433 err = l2cap_disconnect_rsp(conn, &cmd, data);
3434 break;
3435
3436 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003437 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 break;
3439
3440 case L2CAP_ECHO_RSP:
3441 break;
3442
3443 case L2CAP_INFO_REQ:
3444 err = l2cap_information_req(conn, &cmd, data);
3445 break;
3446
3447 case L2CAP_INFO_RSP:
3448 err = l2cap_information_rsp(conn, &cmd, data);
3449 break;
3450
3451 default:
3452 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3453 err = -EINVAL;
3454 break;
3455 }
3456
3457 if (err) {
3458 struct l2cap_cmd_rej rej;
3459 BT_DBG("error %d", err);
3460
3461 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003462 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3464 }
3465
Al Viro88219a02007-07-29 00:17:25 -07003466 data += cmd_len;
3467 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 }
3469
3470 kfree_skb(skb);
3471}
3472
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003473static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3474{
3475 u16 our_fcs, rcv_fcs;
3476 int hdr_size = L2CAP_HDR_SIZE + 2;
3477
3478 if (pi->fcs == L2CAP_FCS_CRC16) {
3479 skb_trim(skb, skb->len - 2);
3480 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3481 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3482
3483 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003484 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003485 }
3486 return 0;
3487}
3488
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003489static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3490{
3491 struct l2cap_pinfo *pi = l2cap_pi(sk);
3492 u16 control = 0;
3493
3494 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003495
3496 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3497
3498 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003499 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003500 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003501 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003502 }
3503
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003504 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3505 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003506
3507 l2cap_ertm_send(sk);
3508
3509 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3510 pi->frames_sent == 0) {
3511 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003512 l2cap_send_sframe(pi, control);
3513 }
3514}
3515
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003516static 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 -03003517{
3518 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003519 struct l2cap_pinfo *pi = l2cap_pi(sk);
3520 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003521
3522 bt_cb(skb)->tx_seq = tx_seq;
3523 bt_cb(skb)->sar = sar;
3524
3525 next_skb = skb_peek(SREJ_QUEUE(sk));
3526 if (!next_skb) {
3527 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003528 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529 }
3530
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003531 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3532 if (tx_seq_offset < 0)
3533 tx_seq_offset += 64;
3534
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003535 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003536 if (bt_cb(next_skb)->tx_seq == tx_seq)
3537 return -EINVAL;
3538
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003539 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3540 pi->buffer_seq) % 64;
3541 if (next_tx_seq_offset < 0)
3542 next_tx_seq_offset += 64;
3543
3544 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003545 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003546 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003547 }
3548
3549 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3550 break;
3551
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003552 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003553
3554 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003555
3556 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003557}
3558
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003559static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3560{
3561 struct l2cap_pinfo *pi = l2cap_pi(sk);
3562 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003563 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003564
3565 switch (control & L2CAP_CTRL_SAR) {
3566 case L2CAP_SDU_UNSEGMENTED:
3567 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3568 goto drop;
3569
3570 err = sock_queue_rcv_skb(sk, skb);
3571 if (!err)
3572 return err;
3573
3574 break;
3575
3576 case L2CAP_SDU_START:
3577 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3578 goto drop;
3579
3580 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003581
3582 if (pi->sdu_len > pi->imtu)
3583 goto disconnect;
3584
3585 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003586 if (!pi->sdu)
3587 return -ENOMEM;
3588
3589 /* pull sdu_len bytes only after alloc, because of Local Busy
3590 * condition we have to be sure that this will be executed
3591 * only once, i.e., when alloc does not fail */
3592 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003593
3594 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3595
3596 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3597 pi->partial_sdu_len = skb->len;
3598 break;
3599
3600 case L2CAP_SDU_CONTINUE:
3601 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3602 goto disconnect;
3603
3604 if (!pi->sdu)
3605 goto disconnect;
3606
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003607 pi->partial_sdu_len += skb->len;
3608 if (pi->partial_sdu_len > pi->sdu_len)
3609 goto drop;
3610
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003611 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3612
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003613 break;
3614
3615 case L2CAP_SDU_END:
3616 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3617 goto disconnect;
3618
3619 if (!pi->sdu)
3620 goto disconnect;
3621
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003622 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003623 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003624
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003625 if (pi->partial_sdu_len > pi->imtu)
3626 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003627
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003628 if (pi->partial_sdu_len != pi->sdu_len)
3629 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003630
3631 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003632 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003633
3634 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003635 if (!_skb) {
3636 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3637 return -ENOMEM;
3638 }
3639
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003640 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003641 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003642 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003643 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3644 return err;
3645 }
3646
3647 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3648 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003649
3650 kfree_skb(pi->sdu);
3651 break;
3652 }
3653
3654 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003655 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003656
3657drop:
3658 kfree_skb(pi->sdu);
3659 pi->sdu = NULL;
3660
3661disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003662 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003663 kfree_skb(skb);
3664 return 0;
3665}
3666
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003667static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003668{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003669 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003670 struct sk_buff *skb;
3671 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003672 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003673
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003674 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3675 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3676 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3677 if (err < 0) {
3678 skb_queue_head(BUSY_QUEUE(sk), skb);
3679 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003680 }
3681
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003682 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003683 }
3684
3685 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3686 goto done;
3687
3688 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3689 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3690 l2cap_send_sframe(pi, control);
3691 l2cap_pi(sk)->retry_count = 1;
3692
3693 del_timer(&pi->retrans_timer);
3694 __mod_monitor_timer();
3695
3696 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3697
3698done:
3699 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3700 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3701
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003702 BT_DBG("sk %p, Exit local busy", sk);
3703
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003704 return 0;
3705}
3706
3707static void l2cap_busy_work(struct work_struct *work)
3708{
3709 DECLARE_WAITQUEUE(wait, current);
3710 struct l2cap_pinfo *pi =
3711 container_of(work, struct l2cap_pinfo, busy_work);
3712 struct sock *sk = (struct sock *)pi;
3713 int n_tries = 0, timeo = HZ/5, err;
3714 struct sk_buff *skb;
3715
3716 lock_sock(sk);
3717
3718 add_wait_queue(sk_sleep(sk), &wait);
3719 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3720 set_current_state(TASK_INTERRUPTIBLE);
3721
3722 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3723 err = -EBUSY;
3724 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3725 break;
3726 }
3727
3728 if (!timeo)
3729 timeo = HZ/5;
3730
3731 if (signal_pending(current)) {
3732 err = sock_intr_errno(timeo);
3733 break;
3734 }
3735
3736 release_sock(sk);
3737 timeo = schedule_timeout(timeo);
3738 lock_sock(sk);
3739
3740 err = sock_error(sk);
3741 if (err)
3742 break;
3743
3744 if (l2cap_try_push_rx_skb(sk) == 0)
3745 break;
3746 }
3747
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003748 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003749 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003750
3751 release_sock(sk);
3752}
3753
3754static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3755{
3756 struct l2cap_pinfo *pi = l2cap_pi(sk);
3757 int sctrl, err;
3758
3759 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3760 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3761 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003762 return l2cap_try_push_rx_skb(sk);
3763
3764
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003765 }
3766
3767 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3768 if (err >= 0) {
3769 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3770 return err;
3771 }
3772
3773 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003774 BT_DBG("sk %p, Enter local busy", sk);
3775
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003776 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3777 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3778 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3779
3780 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3781 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3782 l2cap_send_sframe(pi, sctrl);
3783
3784 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3785
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003786 del_timer(&pi->ack_timer);
3787
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003788 queue_work(_busy_wq, &pi->busy_work);
3789
3790 return err;
3791}
3792
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003793static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003794{
3795 struct l2cap_pinfo *pi = l2cap_pi(sk);
3796 struct sk_buff *_skb;
3797 int err = -EINVAL;
3798
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003799 /*
3800 * TODO: We have to notify the userland if some data is lost with the
3801 * Streaming Mode.
3802 */
3803
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003804 switch (control & L2CAP_CTRL_SAR) {
3805 case L2CAP_SDU_UNSEGMENTED:
3806 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3807 kfree_skb(pi->sdu);
3808 break;
3809 }
3810
3811 err = sock_queue_rcv_skb(sk, skb);
3812 if (!err)
3813 return 0;
3814
3815 break;
3816
3817 case L2CAP_SDU_START:
3818 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3819 kfree_skb(pi->sdu);
3820 break;
3821 }
3822
3823 pi->sdu_len = get_unaligned_le16(skb->data);
3824 skb_pull(skb, 2);
3825
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003826 if (pi->sdu_len > pi->imtu) {
3827 err = -EMSGSIZE;
3828 break;
3829 }
3830
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003831 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3832 if (!pi->sdu) {
3833 err = -ENOMEM;
3834 break;
3835 }
3836
3837 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3838
3839 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3840 pi->partial_sdu_len = skb->len;
3841 err = 0;
3842 break;
3843
3844 case L2CAP_SDU_CONTINUE:
3845 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3846 break;
3847
3848 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3849
3850 pi->partial_sdu_len += skb->len;
3851 if (pi->partial_sdu_len > pi->sdu_len)
3852 kfree_skb(pi->sdu);
3853 else
3854 err = 0;
3855
3856 break;
3857
3858 case L2CAP_SDU_END:
3859 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3860 break;
3861
3862 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3863
3864 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3865 pi->partial_sdu_len += skb->len;
3866
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003867 if (pi->partial_sdu_len > pi->imtu)
3868 goto drop;
3869
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003870 if (pi->partial_sdu_len == pi->sdu_len) {
3871 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3872 err = sock_queue_rcv_skb(sk, _skb);
3873 if (err < 0)
3874 kfree_skb(_skb);
3875 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003876 err = 0;
3877
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003878drop:
3879 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003880 break;
3881 }
3882
3883 kfree_skb(skb);
3884 return err;
3885}
3886
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003887static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3888{
3889 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003890 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003891
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003892 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003893 if (bt_cb(skb)->tx_seq != tx_seq)
3894 break;
3895
3896 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003897 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003898 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003899 l2cap_pi(sk)->buffer_seq_srej =
3900 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003901 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003902 }
3903}
3904
3905static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3906{
3907 struct l2cap_pinfo *pi = l2cap_pi(sk);
3908 struct srej_list *l, *tmp;
3909 u16 control;
3910
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003911 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003912 if (l->tx_seq == tx_seq) {
3913 list_del(&l->list);
3914 kfree(l);
3915 return;
3916 }
3917 control = L2CAP_SUPER_SELECT_REJECT;
3918 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3919 l2cap_send_sframe(pi, control);
3920 list_del(&l->list);
3921 list_add_tail(&l->list, SREJ_LIST(sk));
3922 }
3923}
3924
3925static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3926{
3927 struct l2cap_pinfo *pi = l2cap_pi(sk);
3928 struct srej_list *new;
3929 u16 control;
3930
3931 while (tx_seq != pi->expected_tx_seq) {
3932 control = L2CAP_SUPER_SELECT_REJECT;
3933 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3934 l2cap_send_sframe(pi, control);
3935
3936 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003937 new->tx_seq = pi->expected_tx_seq;
3938 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003939 list_add_tail(&new->list, SREJ_LIST(sk));
3940 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003941 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003942}
3943
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003944static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3945{
3946 struct l2cap_pinfo *pi = l2cap_pi(sk);
3947 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003948 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003949 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003950 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003951 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003952 int err = 0;
3953
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003954 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3955 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003956
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003957 if (L2CAP_CTRL_FINAL & rx_control &&
3958 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003959 del_timer(&pi->monitor_timer);
3960 if (pi->unacked_frames > 0)
3961 __mod_retrans_timer();
3962 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3963 }
3964
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003965 pi->expected_ack_seq = req_seq;
3966 l2cap_drop_acked_frames(sk);
3967
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003968 if (tx_seq == pi->expected_tx_seq)
3969 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003970
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003971 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3972 if (tx_seq_offset < 0)
3973 tx_seq_offset += 64;
3974
3975 /* invalid tx_seq */
3976 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003977 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003978 goto drop;
3979 }
3980
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003981 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3982 goto drop;
3983
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003984 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3985 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003987 first = list_first_entry(SREJ_LIST(sk),
3988 struct srej_list, list);
3989 if (tx_seq == first->tx_seq) {
3990 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3991 l2cap_check_srej_gap(sk, tx_seq);
3992
3993 list_del(&first->list);
3994 kfree(first);
3995
3996 if (list_empty(SREJ_LIST(sk))) {
3997 pi->buffer_seq = pi->buffer_seq_srej;
3998 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003999 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004000 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004001 }
4002 } else {
4003 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004004
4005 /* duplicated tx_seq */
4006 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
4007 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004008
4009 list_for_each_entry(l, SREJ_LIST(sk), list) {
4010 if (l->tx_seq == tx_seq) {
4011 l2cap_resend_srejframe(sk, tx_seq);
4012 return 0;
4013 }
4014 }
4015 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004016 }
4017 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004018 expected_tx_seq_offset =
4019 (pi->expected_tx_seq - pi->buffer_seq) % 64;
4020 if (expected_tx_seq_offset < 0)
4021 expected_tx_seq_offset += 64;
4022
4023 /* duplicated tx_seq */
4024 if (tx_seq_offset < expected_tx_seq_offset)
4025 goto drop;
4026
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004027 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004028
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004029 BT_DBG("sk %p, Enter SREJ", sk);
4030
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004031 INIT_LIST_HEAD(SREJ_LIST(sk));
4032 pi->buffer_seq_srej = pi->buffer_seq;
4033
4034 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004035 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004036 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
4037
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004038 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
4039
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004040 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03004041
4042 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004043 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004044 return 0;
4045
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004046expected:
4047 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4048
4049 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03004050 bt_cb(skb)->tx_seq = tx_seq;
4051 bt_cb(skb)->sar = sar;
4052 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004053 return 0;
4054 }
4055
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004056 err = l2cap_push_rx_skb(sk, skb, rx_control);
4057 if (err < 0)
4058 return 0;
4059
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004060 if (rx_control & L2CAP_CTRL_FINAL) {
4061 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4062 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004063 else
4064 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004065 }
4066
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004067 __mod_ack_timer();
4068
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03004069 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
4070 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004071 l2cap_send_ack(pi);
4072
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004073 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004074
4075drop:
4076 kfree_skb(skb);
4077 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004078}
4079
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004080static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004081{
4082 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004083
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004084 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
4085 rx_control);
4086
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004087 pi->expected_ack_seq = __get_reqseq(rx_control);
4088 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004089
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004090 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004091 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004092 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4093 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4094 (pi->unacked_frames > 0))
4095 __mod_retrans_timer();
4096
4097 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4098 l2cap_send_srejtail(sk);
4099 } else {
4100 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004101 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004102
4103 } else if (rx_control & L2CAP_CTRL_FINAL) {
4104 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004105
4106 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4107 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004108 else
4109 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004110
4111 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004112 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4113 (pi->unacked_frames > 0))
4114 __mod_retrans_timer();
4115
4116 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004117 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004118 l2cap_send_ack(pi);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004119 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004120 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004121 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004122 }
4123}
4124
4125static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
4126{
4127 struct l2cap_pinfo *pi = l2cap_pi(sk);
4128 u8 tx_seq = __get_reqseq(rx_control);
4129
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004130 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4131
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004132 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4133
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03004134 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004135 l2cap_drop_acked_frames(sk);
4136
4137 if (rx_control & L2CAP_CTRL_FINAL) {
4138 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4139 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004140 else
4141 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004142 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004143 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004144
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03004145 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004146 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004147 }
4148}
4149static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
4150{
4151 struct l2cap_pinfo *pi = l2cap_pi(sk);
4152 u8 tx_seq = __get_reqseq(rx_control);
4153
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004154 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4155
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004156 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4157
4158 if (rx_control & L2CAP_CTRL_POLL) {
4159 pi->expected_ack_seq = tx_seq;
4160 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004161
4162 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004163 l2cap_retransmit_one_frame(sk, tx_seq);
4164
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004165 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004166
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004167 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4168 pi->srej_save_reqseq = tx_seq;
4169 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4170 }
4171 } else if (rx_control & L2CAP_CTRL_FINAL) {
4172 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
4173 pi->srej_save_reqseq == tx_seq)
4174 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
4175 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004176 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004177 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004178 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004179 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4180 pi->srej_save_reqseq = tx_seq;
4181 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4182 }
4183 }
4184}
4185
4186static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
4187{
4188 struct l2cap_pinfo *pi = l2cap_pi(sk);
4189 u8 tx_seq = __get_reqseq(rx_control);
4190
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004191 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4192
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004193 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
4194 pi->expected_ack_seq = tx_seq;
4195 l2cap_drop_acked_frames(sk);
4196
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004197 if (rx_control & L2CAP_CTRL_POLL)
4198 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
4199
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004200 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
4201 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03004202 if (rx_control & L2CAP_CTRL_POLL)
4203 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004204 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004205 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004206
4207 if (rx_control & L2CAP_CTRL_POLL)
4208 l2cap_send_srejtail(sk);
4209 else
4210 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004211}
4212
4213static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
4214{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004215 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
4216
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03004217 if (L2CAP_CTRL_FINAL & rx_control &&
4218 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004219 del_timer(&l2cap_pi(sk)->monitor_timer);
4220 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004221 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004222 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004223 }
4224
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004225 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
4226 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004227 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004228 break;
4229
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004230 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004231 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004232 break;
4233
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004234 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004235 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004236 break;
4237
4238 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004239 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004240 break;
4241 }
4242
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004243 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004244 return 0;
4245}
4246
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004247static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4248{
4249 struct l2cap_pinfo *pi = l2cap_pi(sk);
4250 u16 control;
4251 u8 req_seq;
4252 int len, next_tx_seq_offset, req_seq_offset;
4253
4254 control = get_unaligned_le16(skb->data);
4255 skb_pull(skb, 2);
4256 len = skb->len;
4257
4258 /*
4259 * We can just drop the corrupted I-frame here.
4260 * Receiver will miss it and start proper recovery
4261 * procedures and ask retransmission.
4262 */
4263 if (l2cap_check_fcs(pi, skb))
4264 goto drop;
4265
4266 if (__is_sar_start(control) && __is_iframe(control))
4267 len -= 2;
4268
4269 if (pi->fcs == L2CAP_FCS_CRC16)
4270 len -= 2;
4271
4272 if (len > pi->mps) {
4273 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4274 goto drop;
4275 }
4276
4277 req_seq = __get_reqseq(control);
4278 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4279 if (req_seq_offset < 0)
4280 req_seq_offset += 64;
4281
4282 next_tx_seq_offset =
4283 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4284 if (next_tx_seq_offset < 0)
4285 next_tx_seq_offset += 64;
4286
4287 /* check for invalid req-seq */
4288 if (req_seq_offset > next_tx_seq_offset) {
4289 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4290 goto drop;
4291 }
4292
4293 if (__is_iframe(control)) {
4294 if (len < 0) {
4295 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4296 goto drop;
4297 }
4298
4299 l2cap_data_channel_iframe(sk, control, skb);
4300 } else {
4301 if (len != 0) {
4302 BT_ERR("%d", len);
4303 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4304 goto drop;
4305 }
4306
4307 l2cap_data_channel_sframe(sk, control, skb);
4308 }
4309
4310 return 0;
4311
4312drop:
4313 kfree_skb(skb);
4314 return 0;
4315}
4316
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4318{
4319 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004320 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004321 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004322 u8 tx_seq;
4323 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324
4325 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4326 if (!sk) {
4327 BT_DBG("unknown cid 0x%4.4x", cid);
4328 goto drop;
4329 }
4330
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004331 pi = l2cap_pi(sk);
4332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 BT_DBG("sk %p, len %d", sk, skb->len);
4334
4335 if (sk->sk_state != BT_CONNECTED)
4336 goto drop;
4337
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004338 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004339 case L2CAP_MODE_BASIC:
4340 /* If socket recv buffers overflows we drop data here
4341 * which is *bad* because L2CAP has to be reliable.
4342 * But we don't have any other choice. L2CAP doesn't
4343 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004345 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004346 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004348 if (!sock_queue_rcv_skb(sk, skb))
4349 goto done;
4350 break;
4351
4352 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004353 if (!sock_owned_by_user(sk)) {
4354 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004355 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004356 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004357 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004358 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004359
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004360 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004361
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004362 case L2CAP_MODE_STREAMING:
4363 control = get_unaligned_le16(skb->data);
4364 skb_pull(skb, 2);
4365 len = skb->len;
4366
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004367 if (l2cap_check_fcs(pi, skb))
4368 goto drop;
4369
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004370 if (__is_sar_start(control))
4371 len -= 2;
4372
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004373 if (pi->fcs == L2CAP_FCS_CRC16)
4374 len -= 2;
4375
Nathan Holstein51893f82010-06-09 15:46:25 -04004376 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004377 goto drop;
4378
4379 tx_seq = __get_txseq(control);
4380
4381 if (pi->expected_tx_seq == tx_seq)
4382 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4383 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004384 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004385
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004386 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004387
4388 goto done;
4389
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004390 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004391 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004392 break;
4393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394
4395drop:
4396 kfree_skb(skb);
4397
4398done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004399 if (sk)
4400 bh_unlock_sock(sk);
4401
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 return 0;
4403}
4404
Al Viro8e036fc2007-07-29 00:16:36 -07004405static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406{
4407 struct sock *sk;
4408
4409 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4410 if (!sk)
4411 goto drop;
4412
4413 BT_DBG("sk %p, len %d", sk, skb->len);
4414
4415 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4416 goto drop;
4417
4418 if (l2cap_pi(sk)->imtu < skb->len)
4419 goto drop;
4420
4421 if (!sock_queue_rcv_skb(sk, skb))
4422 goto done;
4423
4424drop:
4425 kfree_skb(skb);
4426
4427done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004428 if (sk)
4429 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 return 0;
4431}
4432
4433static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4434{
4435 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004436 u16 cid, len;
4437 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
4439 skb_pull(skb, L2CAP_HDR_SIZE);
4440 cid = __le16_to_cpu(lh->cid);
4441 len = __le16_to_cpu(lh->len);
4442
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004443 if (len != skb->len) {
4444 kfree_skb(skb);
4445 return;
4446 }
4447
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4449
4450 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004451 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 l2cap_sig_channel(conn, skb);
4453 break;
4454
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004455 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004456 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 skb_pull(skb, 2);
4458 l2cap_conless_channel(conn, psm, skb);
4459 break;
4460
4461 default:
4462 l2cap_data_channel(conn, cid, skb);
4463 break;
4464 }
4465}
4466
4467/* ---- L2CAP interface with lower layer (HCI) ---- */
4468
4469static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4470{
4471 int exact = 0, lm1 = 0, lm2 = 0;
4472 register struct sock *sk;
4473 struct hlist_node *node;
4474
4475 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004476 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
4478 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4479
4480 /* Find listening sockets and check their link_mode */
4481 read_lock(&l2cap_sk_list.lock);
4482 sk_for_each(sk, node, &l2cap_sk_list.head) {
4483 if (sk->sk_state != BT_LISTEN)
4484 continue;
4485
4486 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004487 lm1 |= HCI_LM_ACCEPT;
4488 if (l2cap_pi(sk)->role_switch)
4489 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004491 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4492 lm2 |= HCI_LM_ACCEPT;
4493 if (l2cap_pi(sk)->role_switch)
4494 lm2 |= HCI_LM_MASTER;
4495 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 }
4497 read_unlock(&l2cap_sk_list.lock);
4498
4499 return exact ? lm1 : lm2;
4500}
4501
4502static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4503{
Marcel Holtmann01394182006-07-03 10:02:46 +02004504 struct l2cap_conn *conn;
4505
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4507
4508 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004509 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
4511 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 conn = l2cap_conn_add(hcon, status);
4513 if (conn)
4514 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004515 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 l2cap_conn_del(hcon, bt_err(status));
4517
4518 return 0;
4519}
4520
Marcel Holtmann2950f212009-02-12 14:02:50 +01004521static int l2cap_disconn_ind(struct hci_conn *hcon)
4522{
4523 struct l2cap_conn *conn = hcon->l2cap_data;
4524
4525 BT_DBG("hcon %p", hcon);
4526
4527 if (hcon->type != ACL_LINK || !conn)
4528 return 0x13;
4529
4530 return conn->disc_reason;
4531}
4532
4533static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534{
4535 BT_DBG("hcon %p reason %d", hcon, reason);
4536
4537 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004538 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539
4540 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004541
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542 return 0;
4543}
4544
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004545static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4546{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004547 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004548 return;
4549
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004550 if (encrypt == 0x00) {
4551 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4552 l2cap_sock_clear_timer(sk);
4553 l2cap_sock_set_timer(sk, HZ * 5);
4554 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4555 __l2cap_sock_close(sk, ECONNREFUSED);
4556 } else {
4557 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4558 l2cap_sock_clear_timer(sk);
4559 }
4560}
4561
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004562static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563{
4564 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004565 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567
Marcel Holtmann01394182006-07-03 10:02:46 +02004568 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004570
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 l = &conn->chan_list;
4572
4573 BT_DBG("conn %p", conn);
4574
4575 read_lock(&l->lock);
4576
4577 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4578 bh_lock_sock(sk);
4579
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004580 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4581 bh_unlock_sock(sk);
4582 continue;
4583 }
4584
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004585 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004586 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004587 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004588 bh_unlock_sock(sk);
4589 continue;
4590 }
4591
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004592 if (sk->sk_state == BT_CONNECT) {
4593 if (!status) {
4594 struct l2cap_conn_req req;
4595 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4596 req.psm = l2cap_pi(sk)->psm;
4597
4598 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004599 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004600
4601 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4602 L2CAP_CONN_REQ, sizeof(req), &req);
4603 } else {
4604 l2cap_sock_clear_timer(sk);
4605 l2cap_sock_set_timer(sk, HZ / 10);
4606 }
4607 } else if (sk->sk_state == BT_CONNECT2) {
4608 struct l2cap_conn_rsp rsp;
4609 __u16 result;
4610
4611 if (!status) {
4612 sk->sk_state = BT_CONFIG;
4613 result = L2CAP_CR_SUCCESS;
4614 } else {
4615 sk->sk_state = BT_DISCONN;
4616 l2cap_sock_set_timer(sk, HZ / 10);
4617 result = L2CAP_CR_SEC_BLOCK;
4618 }
4619
4620 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4621 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4622 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004623 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004624 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4625 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 }
4627
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 bh_unlock_sock(sk);
4629 }
4630
4631 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004632
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633 return 0;
4634}
4635
4636static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4637{
4638 struct l2cap_conn *conn = hcon->l2cap_data;
4639
4640 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
4641 goto drop;
4642
4643 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4644
4645 if (flags & ACL_START) {
4646 struct l2cap_hdr *hdr;
4647 int len;
4648
4649 if (conn->rx_len) {
4650 BT_ERR("Unexpected start frame (len %d)", skb->len);
4651 kfree_skb(conn->rx_skb);
4652 conn->rx_skb = NULL;
4653 conn->rx_len = 0;
4654 l2cap_conn_unreliable(conn, ECOMM);
4655 }
4656
4657 if (skb->len < 2) {
4658 BT_ERR("Frame is too short (len %d)", skb->len);
4659 l2cap_conn_unreliable(conn, ECOMM);
4660 goto drop;
4661 }
4662
4663 hdr = (struct l2cap_hdr *) skb->data;
4664 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
4665
4666 if (len == skb->len) {
4667 /* Complete frame received */
4668 l2cap_recv_frame(conn, skb);
4669 return 0;
4670 }
4671
4672 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4673
4674 if (skb->len > len) {
4675 BT_ERR("Frame is too long (len %d, expected len %d)",
4676 skb->len, len);
4677 l2cap_conn_unreliable(conn, ECOMM);
4678 goto drop;
4679 }
4680
4681 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004682 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4683 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684 goto drop;
4685
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004686 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004687 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688 conn->rx_len = len - skb->len;
4689 } else {
4690 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4691
4692 if (!conn->rx_len) {
4693 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4694 l2cap_conn_unreliable(conn, ECOMM);
4695 goto drop;
4696 }
4697
4698 if (skb->len > conn->rx_len) {
4699 BT_ERR("Fragment is too long (len %d, expected %d)",
4700 skb->len, conn->rx_len);
4701 kfree_skb(conn->rx_skb);
4702 conn->rx_skb = NULL;
4703 conn->rx_len = 0;
4704 l2cap_conn_unreliable(conn, ECOMM);
4705 goto drop;
4706 }
4707
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004708 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004709 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004710 conn->rx_len -= skb->len;
4711
4712 if (!conn->rx_len) {
4713 /* Complete frame received */
4714 l2cap_recv_frame(conn, conn->rx_skb);
4715 conn->rx_skb = NULL;
4716 }
4717 }
4718
4719drop:
4720 kfree_skb(skb);
4721 return 0;
4722}
4723
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004724static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725{
4726 struct sock *sk;
4727 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728
4729 read_lock_bh(&l2cap_sk_list.lock);
4730
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004731 sk_for_each(sk, node, &l2cap_sk_list.head) {
4732 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004734 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4735 batostr(&bt_sk(sk)->src),
4736 batostr(&bt_sk(sk)->dst),
4737 sk->sk_state, __le16_to_cpu(pi->psm),
4738 pi->scid, pi->dcid,
4739 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004743
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004744 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745}
4746
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004747static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4748{
4749 return single_open(file, l2cap_debugfs_show, inode->i_private);
4750}
4751
4752static const struct file_operations l2cap_debugfs_fops = {
4753 .open = l2cap_debugfs_open,
4754 .read = seq_read,
4755 .llseek = seq_lseek,
4756 .release = single_release,
4757};
4758
4759static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004761static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 .family = PF_BLUETOOTH,
4763 .owner = THIS_MODULE,
4764 .release = l2cap_sock_release,
4765 .bind = l2cap_sock_bind,
4766 .connect = l2cap_sock_connect,
4767 .listen = l2cap_sock_listen,
4768 .accept = l2cap_sock_accept,
4769 .getname = l2cap_sock_getname,
4770 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004771 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004773 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774 .mmap = sock_no_mmap,
4775 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 .shutdown = l2cap_sock_shutdown,
4777 .setsockopt = l2cap_sock_setsockopt,
4778 .getsockopt = l2cap_sock_getsockopt
4779};
4780
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004781static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782 .family = PF_BLUETOOTH,
4783 .owner = THIS_MODULE,
4784 .create = l2cap_sock_create,
4785};
4786
4787static struct hci_proto l2cap_hci_proto = {
4788 .name = "L2CAP",
4789 .id = HCI_PROTO_L2CAP,
4790 .connect_ind = l2cap_connect_ind,
4791 .connect_cfm = l2cap_connect_cfm,
4792 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004793 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004794 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795 .recv_acldata = l2cap_recv_acldata
4796};
4797
4798static int __init l2cap_init(void)
4799{
4800 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004801
Linus Torvalds1da177e2005-04-16 15:20:36 -07004802 err = proto_register(&l2cap_proto, 0);
4803 if (err < 0)
4804 return err;
4805
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004806 _busy_wq = create_singlethread_workqueue("l2cap");
4807 if (!_busy_wq)
4808 goto error;
4809
Linus Torvalds1da177e2005-04-16 15:20:36 -07004810 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4811 if (err < 0) {
4812 BT_ERR("L2CAP socket registration failed");
4813 goto error;
4814 }
4815
4816 err = hci_register_proto(&l2cap_hci_proto);
4817 if (err < 0) {
4818 BT_ERR("L2CAP protocol registration failed");
4819 bt_sock_unregister(BTPROTO_L2CAP);
4820 goto error;
4821 }
4822
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004823 if (bt_debugfs) {
4824 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4825 bt_debugfs, NULL, &l2cap_debugfs_fops);
4826 if (!l2cap_debugfs)
4827 BT_ERR("Failed to create L2CAP debug file");
4828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829
4830 BT_INFO("L2CAP ver %s", VERSION);
4831 BT_INFO("L2CAP socket layer initialized");
4832
4833 return 0;
4834
4835error:
4836 proto_unregister(&l2cap_proto);
4837 return err;
4838}
4839
4840static void __exit l2cap_exit(void)
4841{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004842 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004843
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004844 flush_workqueue(_busy_wq);
4845 destroy_workqueue(_busy_wq);
4846
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4848 BT_ERR("L2CAP socket unregistration failed");
4849
4850 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4851 BT_ERR("L2CAP protocol unregistration failed");
4852
4853 proto_unregister(&l2cap_proto);
4854}
4855
4856void l2cap_load(void)
4857{
4858 /* Dummy function to trigger automatic L2CAP module loading by
4859 * other modules that use L2CAP sockets but don't use any other
4860 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861}
4862EXPORT_SYMBOL(l2cap_load);
4863
4864module_init(l2cap_init);
4865module_exit(l2cap_exit);
4866
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004867module_param(disable_ertm, bool, 0644);
4868MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004869
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004870MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4872MODULE_VERSION(VERSION);
4873MODULE_LICENSE("GPL");
4874MODULE_ALIAS("bt-proto-0");