blob: 2f625b87a89e63a5938eedd0f40d9313d18a70ec [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
Mat Martineau0fba2552010-09-08 10:05:26 -07001011 if (la.l2_psm) {
1012 __u16 psm = __le16_to_cpu(la.l2_psm);
1013
1014 /* PSM must be odd and lsb of upper byte must be 0 */
1015 if ((psm & 0x0101) != 0x0001) {
1016 err = -EINVAL;
1017 goto done;
1018 }
1019
1020 /* Restrict usage of well-known PSMs */
1021 if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
1022 err = -EACCES;
1023 goto done;
1024 }
Marcel Holtmann847641d2007-01-22 22:00:45 +01001025 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 write_lock_bh(&l2cap_sk_list.lock);
1028
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001029 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 err = -EADDRINUSE;
1031 } else {
1032 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001033 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
1034 l2cap_pi(sk)->psm = la.l2_psm;
1035 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001037
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001038 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
1039 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001040 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 }
1042
1043 write_unlock_bh(&l2cap_sk_list.lock);
1044
1045done:
1046 release_sock(sk);
1047 return err;
1048}
1049
1050static int l2cap_do_connect(struct sock *sk)
1051{
1052 bdaddr_t *src = &bt_sk(sk)->src;
1053 bdaddr_t *dst = &bt_sk(sk)->dst;
1054 struct l2cap_conn *conn;
1055 struct hci_conn *hcon;
1056 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001057 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001058 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001060 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
1061 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001063 hdev = hci_get_route(dst, src);
1064 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return -EHOSTUNREACH;
1066
1067 hci_dev_lock_bh(hdev);
1068
1069 err = -ENOMEM;
1070
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001071 if (sk->sk_type == SOCK_RAW) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001072 switch (l2cap_pi(sk)->sec_level) {
1073 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001074 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001075 break;
1076 case BT_SECURITY_MEDIUM:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001077 auth_type = HCI_AT_DEDICATED_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001078 break;
1079 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001080 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001081 break;
1082 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001083 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001084 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001085 auth_type = HCI_AT_NO_BONDING_MITM;
1086 else
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001087 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann435fef22009-02-09 03:55:28 +01001088
1089 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
1090 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001091 } else {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001092 switch (l2cap_pi(sk)->sec_level) {
1093 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001094 auth_type = HCI_AT_GENERAL_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001095 break;
1096 case BT_SECURITY_MEDIUM:
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001097 auth_type = HCI_AT_GENERAL_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001098 break;
1099 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001100 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001101 break;
1102 }
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001103 }
1104
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001105 hcon = hci_connect(hdev, ACL_LINK, dst,
1106 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 if (!hcon)
1108 goto done;
1109
1110 conn = l2cap_conn_add(hcon, 0);
1111 if (!conn) {
1112 hci_conn_put(hcon);
1113 goto done;
1114 }
1115
1116 err = 0;
1117
1118 /* Update source addr of the socket */
1119 bacpy(src, conn->src);
1120
1121 l2cap_chan_add(conn, sk, NULL);
1122
1123 sk->sk_state = BT_CONNECT;
1124 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1125
1126 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001127 if (sk->sk_type != SOCK_SEQPACKET &&
1128 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 l2cap_sock_clear_timer(sk);
1130 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001131 } else
1132 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 }
1134
1135done:
1136 hci_dev_unlock_bh(hdev);
1137 hci_dev_put(hdev);
1138 return err;
1139}
1140
1141static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
1142{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001144 struct sockaddr_l2 la;
1145 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 BT_DBG("sk %p", sk);
1148
Changli Gao6503d962010-03-31 22:58:26 +00001149 if (!addr || alen < sizeof(addr->sa_family) ||
1150 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001151 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001153 memset(&la, 0, sizeof(la));
1154 len = min_t(unsigned int, sizeof(la), alen);
1155 memcpy(&la, addr, len);
1156
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001157 if (la.l2_cid)
1158 return -EINVAL;
1159
1160 lock_sock(sk);
1161
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001162 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
1163 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 err = -EINVAL;
1165 goto done;
1166 }
1167
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001168 switch (l2cap_pi(sk)->mode) {
1169 case L2CAP_MODE_BASIC:
1170 break;
1171 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001172 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001173 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001174 break;
1175 /* fall through */
1176 default:
1177 err = -ENOTSUPP;
1178 goto done;
1179 }
1180
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001181 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 case BT_CONNECT:
1183 case BT_CONNECT2:
1184 case BT_CONFIG:
1185 /* Already connecting */
1186 goto wait;
1187
1188 case BT_CONNECTED:
1189 /* Already connected */
João Paulo Rechi Vita8b0dc6d2010-06-22 13:56:22 -03001190 err = -EISCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 goto done;
1192
1193 case BT_OPEN:
1194 case BT_BOUND:
1195 /* Can connect */
1196 break;
1197
1198 default:
1199 err = -EBADFD;
1200 goto done;
1201 }
1202
Mat Martineau0fba2552010-09-08 10:05:26 -07001203 /* PSM must be odd and lsb of upper byte must be 0 */
1204 if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
1205 sk->sk_type != SOCK_RAW) {
1206 err = -EINVAL;
1207 goto done;
1208 }
1209
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001211 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1212 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001214 err = l2cap_do_connect(sk);
1215 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 goto done;
1217
1218wait:
1219 err = bt_sock_wait_state(sk, BT_CONNECTED,
1220 sock_sndtimeo(sk, flags & O_NONBLOCK));
1221done:
1222 release_sock(sk);
1223 return err;
1224}
1225
1226static int l2cap_sock_listen(struct socket *sock, int backlog)
1227{
1228 struct sock *sk = sock->sk;
1229 int err = 0;
1230
1231 BT_DBG("sk %p backlog %d", sk, backlog);
1232
1233 lock_sock(sk);
1234
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001235 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1236 || sk->sk_state != BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 err = -EBADFD;
1238 goto done;
1239 }
1240
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001241 switch (l2cap_pi(sk)->mode) {
1242 case L2CAP_MODE_BASIC:
1243 break;
1244 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001245 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001246 if (!disable_ertm)
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001247 break;
1248 /* fall through */
1249 default:
1250 err = -ENOTSUPP;
1251 goto done;
1252 }
1253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 if (!l2cap_pi(sk)->psm) {
1255 bdaddr_t *src = &bt_sk(sk)->src;
1256 u16 psm;
1257
1258 err = -EINVAL;
1259
1260 write_lock_bh(&l2cap_sk_list.lock);
1261
1262 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001263 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1264 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1265 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 err = 0;
1267 break;
1268 }
1269
1270 write_unlock_bh(&l2cap_sk_list.lock);
1271
1272 if (err < 0)
1273 goto done;
1274 }
1275
1276 sk->sk_max_ack_backlog = backlog;
1277 sk->sk_ack_backlog = 0;
1278 sk->sk_state = BT_LISTEN;
1279
1280done:
1281 release_sock(sk);
1282 return err;
1283}
1284
1285static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
1286{
1287 DECLARE_WAITQUEUE(wait, current);
1288 struct sock *sk = sock->sk, *nsk;
1289 long timeo;
1290 int err = 0;
1291
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001292 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 if (sk->sk_state != BT_LISTEN) {
1295 err = -EBADFD;
1296 goto done;
1297 }
1298
1299 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1300
1301 BT_DBG("sk %p timeo %ld", sk, timeo);
1302
1303 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001304 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1306 set_current_state(TASK_INTERRUPTIBLE);
1307 if (!timeo) {
1308 err = -EAGAIN;
1309 break;
1310 }
1311
1312 release_sock(sk);
1313 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001314 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
1316 if (sk->sk_state != BT_LISTEN) {
1317 err = -EBADFD;
1318 break;
1319 }
1320
1321 if (signal_pending(current)) {
1322 err = sock_intr_errno(timeo);
1323 break;
1324 }
1325 }
1326 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001327 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329 if (err)
1330 goto done;
1331
1332 newsock->state = SS_CONNECTED;
1333
1334 BT_DBG("new socket %p", nsk);
1335
1336done:
1337 release_sock(sk);
1338 return err;
1339}
1340
1341static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
1342{
1343 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1344 struct sock *sk = sock->sk;
1345
1346 BT_DBG("sock %p, sk %p", sock, sk);
1347
1348 addr->sa_family = AF_BLUETOOTH;
1349 *len = sizeof(struct sockaddr_l2);
1350
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001351 if (peer) {
1352 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001354 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001355 } else {
1356 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001358 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 return 0;
1362}
1363
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001364static int __l2cap_wait_ack(struct sock *sk)
1365{
1366 DECLARE_WAITQUEUE(wait, current);
1367 int err = 0;
1368 int timeo = HZ/5;
1369
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001370 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001371 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
1372 set_current_state(TASK_INTERRUPTIBLE);
1373
1374 if (!timeo)
1375 timeo = HZ/5;
1376
1377 if (signal_pending(current)) {
1378 err = sock_intr_errno(timeo);
1379 break;
1380 }
1381
1382 release_sock(sk);
1383 timeo = schedule_timeout(timeo);
1384 lock_sock(sk);
1385
1386 err = sock_error(sk);
1387 if (err)
1388 break;
1389 }
1390 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001391 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001392 return err;
1393}
1394
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001395static void l2cap_monitor_timeout(unsigned long arg)
1396{
1397 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001398
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001399 BT_DBG("sk %p", sk);
1400
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001401 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001402 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001403 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001404 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001405 return;
1406 }
1407
1408 l2cap_pi(sk)->retry_count++;
1409 __mod_monitor_timer();
1410
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001411 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001412 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001413}
1414
1415static void l2cap_retrans_timeout(unsigned long arg)
1416{
1417 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001418
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001419 BT_DBG("sk %p", sk);
1420
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001421 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001422 l2cap_pi(sk)->retry_count = 1;
1423 __mod_monitor_timer();
1424
1425 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1426
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001427 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001428 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001429}
1430
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001431static void l2cap_drop_acked_frames(struct sock *sk)
1432{
1433 struct sk_buff *skb;
1434
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001435 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1436 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1438 break;
1439
1440 skb = skb_dequeue(TX_QUEUE(sk));
1441 kfree_skb(skb);
1442
1443 l2cap_pi(sk)->unacked_frames--;
1444 }
1445
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001446 if (!l2cap_pi(sk)->unacked_frames)
1447 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448}
1449
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001450static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451{
1452 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001453
1454 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1455
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001456 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001457}
1458
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001459static void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001460{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001461 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001462 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001463 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001464
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001465 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1466 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001467 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001468 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001469
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001470 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001471 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1472 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001473 }
1474
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001475 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001476
1477 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001478 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001479}
1480
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001481static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001482{
1483 struct l2cap_pinfo *pi = l2cap_pi(sk);
1484 struct sk_buff *skb, *tx_skb;
1485 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001486
1487 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001488 if (!skb)
1489 return;
1490
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001491 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001492 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001493 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001494
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001495 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1496 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001497
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001498 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001499
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001500 if (pi->remote_max_tx &&
1501 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001502 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001503 return;
1504 }
1505
1506 tx_skb = skb_clone(skb, GFP_ATOMIC);
1507 bt_cb(skb)->retries++;
1508 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001509
1510 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1511 control |= L2CAP_CTRL_FINAL;
1512 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1513 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001514
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001515 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1516 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001517
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001518 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1519
1520 if (pi->fcs == L2CAP_FCS_CRC16) {
1521 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1522 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1523 }
1524
1525 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001526}
1527
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001528static int l2cap_ertm_send(struct sock *sk)
1529{
1530 struct sk_buff *skb, *tx_skb;
1531 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001532 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001533 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001534
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001535 if (sk->sk_state != BT_CONNECTED)
1536 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001537
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001538 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001539
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001540 if (pi->remote_max_tx &&
1541 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001542 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001543 break;
1544 }
1545
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001546 tx_skb = skb_clone(skb, GFP_ATOMIC);
1547
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001548 bt_cb(skb)->retries++;
1549
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001551 control &= L2CAP_CTRL_SAR;
1552
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001553 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1554 control |= L2CAP_CTRL_FINAL;
1555 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1556 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001557 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1559 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1560
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001561
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001562 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001563 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1564 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1565 }
1566
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001567 l2cap_do_send(sk, tx_skb);
1568
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001569 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001570
1571 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1572 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1573
1574 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001575 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001576
1577 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1578 sk->sk_send_head = NULL;
1579 else
1580 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001581
1582 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001583 }
1584
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001585 return nsent;
1586}
1587
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001588static int l2cap_retransmit_frames(struct sock *sk)
1589{
1590 struct l2cap_pinfo *pi = l2cap_pi(sk);
1591 int ret;
1592
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001593 if (!skb_queue_empty(TX_QUEUE(sk)))
1594 sk->sk_send_head = TX_QUEUE(sk)->next;
1595
1596 pi->next_tx_seq = pi->expected_ack_seq;
1597 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001598 return ret;
1599}
1600
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001601static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001602{
1603 struct sock *sk = (struct sock *)pi;
1604 u16 control = 0;
1605
1606 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1607
1608 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1609 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001610 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001611 l2cap_send_sframe(pi, control);
1612 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001613 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001614
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001615 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001616 return;
1617
1618 control |= L2CAP_SUPER_RCV_READY;
1619 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001620}
1621
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001622static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001623{
1624 struct srej_list *tail;
1625 u16 control;
1626
1627 control = L2CAP_SUPER_SELECT_REJECT;
1628 control |= L2CAP_CTRL_FINAL;
1629
1630 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1631 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1632
1633 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001634}
1635
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001636static 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 -07001637{
1638 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001639 struct sk_buff **frag;
1640 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001642 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001643 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 sent += count;
1646 len -= count;
1647
1648 /* Continuation fragments (no L2CAP header) */
1649 frag = &skb_shinfo(skb)->frag_list;
1650 while (len) {
1651 count = min_t(unsigned int, conn->mtu, len);
1652
1653 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1654 if (!*frag)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001655 return -EFAULT;
1656 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1657 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
1659 sent += count;
1660 len -= count;
1661
1662 frag = &(*frag)->next;
1663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
1665 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001666}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001668static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1669{
1670 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1671 struct sk_buff *skb;
1672 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1673 struct l2cap_hdr *lh;
1674
1675 BT_DBG("sk %p len %d", sk, (int)len);
1676
1677 count = min_t(unsigned int, (conn->mtu - hlen), len);
1678 skb = bt_skb_send_alloc(sk, count + hlen,
1679 msg->msg_flags & MSG_DONTWAIT, &err);
1680 if (!skb)
1681 return ERR_PTR(-ENOMEM);
1682
1683 /* Create L2CAP header */
1684 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1685 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1686 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1687 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1688
1689 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1690 if (unlikely(err < 0)) {
1691 kfree_skb(skb);
1692 return ERR_PTR(err);
1693 }
1694 return skb;
1695}
1696
1697static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1698{
1699 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1700 struct sk_buff *skb;
1701 int err, count, hlen = L2CAP_HDR_SIZE;
1702 struct l2cap_hdr *lh;
1703
1704 BT_DBG("sk %p len %d", sk, (int)len);
1705
1706 count = min_t(unsigned int, (conn->mtu - hlen), len);
1707 skb = bt_skb_send_alloc(sk, count + hlen,
1708 msg->msg_flags & MSG_DONTWAIT, &err);
1709 if (!skb)
1710 return ERR_PTR(-ENOMEM);
1711
1712 /* Create L2CAP header */
1713 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1714 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1715 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1716
1717 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1718 if (unlikely(err < 0)) {
1719 kfree_skb(skb);
1720 return ERR_PTR(err);
1721 }
1722 return skb;
1723}
1724
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001725static 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 -03001726{
1727 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1728 struct sk_buff *skb;
1729 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1730 struct l2cap_hdr *lh;
1731
1732 BT_DBG("sk %p len %d", sk, (int)len);
1733
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001734 if (!conn)
1735 return ERR_PTR(-ENOTCONN);
1736
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001737 if (sdulen)
1738 hlen += 2;
1739
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001740 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1741 hlen += 2;
1742
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001743 count = min_t(unsigned int, (conn->mtu - hlen), len);
1744 skb = bt_skb_send_alloc(sk, count + hlen,
1745 msg->msg_flags & MSG_DONTWAIT, &err);
1746 if (!skb)
1747 return ERR_PTR(-ENOMEM);
1748
1749 /* Create L2CAP header */
1750 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1751 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1752 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1753 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001754 if (sdulen)
1755 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001756
1757 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1758 if (unlikely(err < 0)) {
1759 kfree_skb(skb);
1760 return ERR_PTR(err);
1761 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001762
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001763 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1764 put_unaligned_le16(0, skb_put(skb, 2));
1765
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001766 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001767 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768}
1769
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001770static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1771{
1772 struct l2cap_pinfo *pi = l2cap_pi(sk);
1773 struct sk_buff *skb;
1774 struct sk_buff_head sar_queue;
1775 u16 control;
1776 size_t size = 0;
1777
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001778 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001779 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001780 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001781 if (IS_ERR(skb))
1782 return PTR_ERR(skb);
1783
1784 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001785 len -= pi->remote_mps;
1786 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001787
1788 while (len > 0) {
1789 size_t buflen;
1790
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001791 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001792 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001793 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001794 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001795 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001796 buflen = len;
1797 }
1798
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001799 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001800 if (IS_ERR(skb)) {
1801 skb_queue_purge(&sar_queue);
1802 return PTR_ERR(skb);
1803 }
1804
1805 __skb_queue_tail(&sar_queue, skb);
1806 len -= buflen;
1807 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001808 }
1809 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1810 if (sk->sk_send_head == NULL)
1811 sk->sk_send_head = sar_queue.next;
1812
1813 return size;
1814}
1815
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
1817{
1818 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001819 struct l2cap_pinfo *pi = l2cap_pi(sk);
1820 struct sk_buff *skb;
1821 u16 control;
1822 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
1824 BT_DBG("sock %p, sk %p", sock, sk);
1825
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001826 err = sock_error(sk);
1827 if (err)
1828 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
1830 if (msg->msg_flags & MSG_OOB)
1831 return -EOPNOTSUPP;
1832
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 lock_sock(sk);
1834
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001835 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001837 goto done;
1838 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001840 /* Connectionless channel */
1841 if (sk->sk_type == SOCK_DGRAM) {
1842 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001843 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001844 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001845 } else {
1846 l2cap_do_send(sk, skb);
1847 err = len;
1848 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001849 goto done;
1850 }
1851
1852 switch (pi->mode) {
1853 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001854 /* Check outgoing MTU */
1855 if (len > pi->omtu) {
João Paulo Rechi Vitaf9dd11b2010-06-22 13:56:24 -03001856 err = -EMSGSIZE;
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001857 goto done;
1858 }
1859
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001860 /* Create a basic PDU */
1861 skb = l2cap_create_basic_pdu(sk, msg, len);
1862 if (IS_ERR(skb)) {
1863 err = PTR_ERR(skb);
1864 goto done;
1865 }
1866
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001867 l2cap_do_send(sk, skb);
1868 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001869 break;
1870
1871 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001872 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001873 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001874 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001875 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001876 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001877 if (IS_ERR(skb)) {
1878 err = PTR_ERR(skb);
1879 goto done;
1880 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001881 __skb_queue_tail(TX_QUEUE(sk), skb);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001882
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001883 if (sk->sk_send_head == NULL)
1884 sk->sk_send_head = skb;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001885
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001886 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001887 /* Segment SDU into multiples PDUs */
1888 err = l2cap_sar_segment_sdu(sk, msg, len);
1889 if (err < 0)
1890 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001891 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001892
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001893 if (pi->mode == L2CAP_MODE_STREAMING) {
João Paulo Rechi Vita305682e2010-06-22 13:56:23 -03001894 l2cap_streaming_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001895 } else {
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001896 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
1897 pi->conn_state && L2CAP_CONN_WAIT_F) {
1898 err = len;
1899 break;
1900 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001901 err = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001902 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001903
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001904 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001905 err = len;
1906 break;
1907
1908 default:
1909 BT_DBG("bad state %1.1x", pi->mode);
João Paulo Rechi Vitabc766db22010-06-22 13:56:25 -03001910 err = -EBADFD;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001911 }
1912
1913done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 release_sock(sk);
1915 return err;
1916}
1917
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001918static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1919{
1920 struct sock *sk = sock->sk;
1921
1922 lock_sock(sk);
1923
1924 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1925 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001926 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1927 u8 buf[128];
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001928
1929 sk->sk_state = BT_CONFIG;
1930
1931 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1932 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1933 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1934 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1935 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1936 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1937
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001938 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
1939 release_sock(sk);
1940 return 0;
1941 }
1942
1943 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1944 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1945 l2cap_build_conf_req(sk, buf), buf);
1946 l2cap_pi(sk)->num_conf_req++;
1947
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001948 release_sock(sk);
1949 return 0;
1950 }
1951
1952 release_sock(sk);
1953
1954 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1955}
1956
David S. Millerb7058842009-09-30 16:12:20 -07001957static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958{
1959 struct sock *sk = sock->sk;
1960 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001961 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 u32 opt;
1963
1964 BT_DBG("sk %p", sk);
1965
1966 lock_sock(sk);
1967
1968 switch (optname) {
1969 case L2CAP_OPTIONS:
Gustavo F. Padovaneaa71b32010-10-04 19:28:52 -03001970 if (sk->sk_state == BT_CONNECTED) {
1971 err = -EINVAL;
1972 break;
1973 }
1974
Marcel Holtmann0878b662007-05-05 00:35:59 +02001975 opts.imtu = l2cap_pi(sk)->imtu;
1976 opts.omtu = l2cap_pi(sk)->omtu;
1977 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001978 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001979 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001980 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001981 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 len = min_t(unsigned int, sizeof(opts), optlen);
1984 if (copy_from_user((char *) &opts, optval, len)) {
1985 err = -EFAULT;
1986 break;
1987 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001988
Gustavo F. Padovan45d65c42010-06-07 19:21:30 -03001989 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
1990 err = -EINVAL;
1991 break;
1992 }
1993
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001994 l2cap_pi(sk)->mode = opts.mode;
1995 switch (l2cap_pi(sk)->mode) {
1996 case L2CAP_MODE_BASIC:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001997 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001998 break;
1999 case L2CAP_MODE_ERTM:
2000 case L2CAP_MODE_STREAMING:
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002001 if (!disable_ertm)
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03002002 break;
2003 /* fall through */
2004 default:
2005 err = -EINVAL;
2006 break;
2007 }
2008
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07002009 l2cap_pi(sk)->imtu = opts.imtu;
2010 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002011 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002012 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002013 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 break;
2015
2016 case L2CAP_LM:
2017 if (get_user(opt, (u32 __user *) optval)) {
2018 err = -EFAULT;
2019 break;
2020 }
2021
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002022 if (opt & L2CAP_LM_AUTH)
2023 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
2024 if (opt & L2CAP_LM_ENCRYPT)
2025 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
2026 if (opt & L2CAP_LM_SECURE)
2027 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
2028
2029 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
2030 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 break;
2032
2033 default:
2034 err = -ENOPROTOOPT;
2035 break;
2036 }
2037
2038 release_sock(sk);
2039 return err;
2040}
2041
David S. Millerb7058842009-09-30 16:12:20 -07002042static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002043{
2044 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002045 struct bt_security sec;
2046 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002047 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002048
2049 BT_DBG("sk %p", sk);
2050
2051 if (level == SOL_L2CAP)
2052 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
2053
Marcel Holtmann0588d942009-01-16 10:06:13 +01002054 if (level != SOL_BLUETOOTH)
2055 return -ENOPROTOOPT;
2056
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002057 lock_sock(sk);
2058
2059 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002060 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002061 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2062 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002063 err = -EINVAL;
2064 break;
2065 }
2066
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002067 sec.level = BT_SECURITY_LOW;
2068
2069 len = min_t(unsigned int, sizeof(sec), optlen);
2070 if (copy_from_user((char *) &sec, optval, len)) {
2071 err = -EFAULT;
2072 break;
2073 }
2074
2075 if (sec.level < BT_SECURITY_LOW ||
2076 sec.level > BT_SECURITY_HIGH) {
2077 err = -EINVAL;
2078 break;
2079 }
2080
2081 l2cap_pi(sk)->sec_level = sec.level;
2082 break;
2083
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002084 case BT_DEFER_SETUP:
2085 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2086 err = -EINVAL;
2087 break;
2088 }
2089
2090 if (get_user(opt, (u32 __user *) optval)) {
2091 err = -EFAULT;
2092 break;
2093 }
2094
2095 bt_sk(sk)->defer_setup = opt;
2096 break;
2097
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002098 default:
2099 err = -ENOPROTOOPT;
2100 break;
2101 }
2102
2103 release_sock(sk);
2104 return err;
2105}
2106
2107static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
2109 struct sock *sk = sock->sk;
2110 struct l2cap_options opts;
2111 struct l2cap_conninfo cinfo;
2112 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002113 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
2115 BT_DBG("sk %p", sk);
2116
2117 if (get_user(len, optlen))
2118 return -EFAULT;
2119
2120 lock_sock(sk);
2121
2122 switch (optname) {
2123 case L2CAP_OPTIONS:
2124 opts.imtu = l2cap_pi(sk)->imtu;
2125 opts.omtu = l2cap_pi(sk)->omtu;
2126 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07002127 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002128 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002129 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002130 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
2132 len = min_t(unsigned int, len, sizeof(opts));
2133 if (copy_to_user(optval, (char *) &opts, len))
2134 err = -EFAULT;
2135
2136 break;
2137
2138 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002139 switch (l2cap_pi(sk)->sec_level) {
2140 case BT_SECURITY_LOW:
2141 opt = L2CAP_LM_AUTH;
2142 break;
2143 case BT_SECURITY_MEDIUM:
2144 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
2145 break;
2146 case BT_SECURITY_HIGH:
2147 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
2148 L2CAP_LM_SECURE;
2149 break;
2150 default:
2151 opt = 0;
2152 break;
2153 }
2154
2155 if (l2cap_pi(sk)->role_switch)
2156 opt |= L2CAP_LM_MASTER;
2157
2158 if (l2cap_pi(sk)->force_reliable)
2159 opt |= L2CAP_LM_RELIABLE;
2160
2161 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 err = -EFAULT;
2163 break;
2164
2165 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002166 if (sk->sk_state != BT_CONNECTED &&
2167 !(sk->sk_state == BT_CONNECT2 &&
2168 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 err = -ENOTCONN;
2170 break;
2171 }
2172
2173 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
2174 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
2175
2176 len = min_t(unsigned int, len, sizeof(cinfo));
2177 if (copy_to_user(optval, (char *) &cinfo, len))
2178 err = -EFAULT;
2179
2180 break;
2181
2182 default:
2183 err = -ENOPROTOOPT;
2184 break;
2185 }
2186
2187 release_sock(sk);
2188 return err;
2189}
2190
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002191static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
2192{
2193 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002194 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002195 int len, err = 0;
2196
2197 BT_DBG("sk %p", sk);
2198
2199 if (level == SOL_L2CAP)
2200 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
2201
Marcel Holtmann0588d942009-01-16 10:06:13 +01002202 if (level != SOL_BLUETOOTH)
2203 return -ENOPROTOOPT;
2204
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002205 if (get_user(len, optlen))
2206 return -EFAULT;
2207
2208 lock_sock(sk);
2209
2210 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002211 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002212 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2213 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002214 err = -EINVAL;
2215 break;
2216 }
2217
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002218 sec.level = l2cap_pi(sk)->sec_level;
2219
2220 len = min_t(unsigned int, len, sizeof(sec));
2221 if (copy_to_user(optval, (char *) &sec, len))
2222 err = -EFAULT;
2223
2224 break;
2225
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002226 case BT_DEFER_SETUP:
2227 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2228 err = -EINVAL;
2229 break;
2230 }
2231
2232 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
2233 err = -EFAULT;
2234
2235 break;
2236
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002237 default:
2238 err = -ENOPROTOOPT;
2239 break;
2240 }
2241
2242 release_sock(sk);
2243 return err;
2244}
2245
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246static int l2cap_sock_shutdown(struct socket *sock, int how)
2247{
2248 struct sock *sk = sock->sk;
2249 int err = 0;
2250
2251 BT_DBG("sock %p, sk %p", sock, sk);
2252
2253 if (!sk)
2254 return 0;
2255
2256 lock_sock(sk);
2257 if (!sk->sk_shutdown) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03002258 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2259 err = __l2cap_wait_ack(sk);
2260
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 sk->sk_shutdown = SHUTDOWN_MASK;
2262 l2cap_sock_clear_timer(sk);
2263 __l2cap_sock_close(sk, 0);
2264
2265 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002266 err = bt_sock_wait_state(sk, BT_CLOSED,
2267 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 }
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002269
2270 if (!err && sk->sk_err)
2271 err = -sk->sk_err;
2272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 release_sock(sk);
2274 return err;
2275}
2276
2277static int l2cap_sock_release(struct socket *sock)
2278{
2279 struct sock *sk = sock->sk;
2280 int err;
2281
2282 BT_DBG("sock %p, sk %p", sock, sk);
2283
2284 if (!sk)
2285 return 0;
2286
2287 err = l2cap_sock_shutdown(sock, 2);
2288
2289 sock_orphan(sk);
2290 l2cap_sock_kill(sk);
2291 return err;
2292}
2293
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294static void l2cap_chan_ready(struct sock *sk)
2295{
2296 struct sock *parent = bt_sk(sk)->parent;
2297
2298 BT_DBG("sk %p, parent %p", sk, parent);
2299
2300 l2cap_pi(sk)->conf_state = 0;
2301 l2cap_sock_clear_timer(sk);
2302
2303 if (!parent) {
2304 /* Outgoing channel.
2305 * Wake up socket sleeping on connect.
2306 */
2307 sk->sk_state = BT_CONNECTED;
2308 sk->sk_state_change(sk);
2309 } else {
2310 /* Incoming channel.
2311 * Wake up socket sleeping on accept.
2312 */
2313 parent->sk_data_ready(parent, 0);
2314 }
2315}
2316
2317/* Copy frame to all raw sockets on that connection */
2318static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2319{
2320 struct l2cap_chan_list *l = &conn->chan_list;
2321 struct sk_buff *nskb;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002322 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
2324 BT_DBG("conn %p", conn);
2325
2326 read_lock(&l->lock);
2327 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2328 if (sk->sk_type != SOCK_RAW)
2329 continue;
2330
2331 /* Don't send frame to the socket it came from */
2332 if (skb->sk == sk)
2333 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002334 nskb = skb_clone(skb, GFP_ATOMIC);
2335 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 continue;
2337
2338 if (sock_queue_rcv_skb(sk, nskb))
2339 kfree_skb(nskb);
2340 }
2341 read_unlock(&l->lock);
2342}
2343
2344/* ---- L2CAP signalling commands ---- */
2345static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2346 u8 code, u8 ident, u16 dlen, void *data)
2347{
2348 struct sk_buff *skb, **frag;
2349 struct l2cap_cmd_hdr *cmd;
2350 struct l2cap_hdr *lh;
2351 int len, count;
2352
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002353 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2354 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
2356 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2357 count = min_t(unsigned int, conn->mtu, len);
2358
2359 skb = bt_skb_alloc(count, GFP_ATOMIC);
2360 if (!skb)
2361 return NULL;
2362
2363 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002364 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002365 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
2367 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2368 cmd->code = code;
2369 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002370 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
2372 if (dlen) {
2373 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2374 memcpy(skb_put(skb, count), data, count);
2375 data += count;
2376 }
2377
2378 len -= skb->len;
2379
2380 /* Continuation fragments (no L2CAP header) */
2381 frag = &skb_shinfo(skb)->frag_list;
2382 while (len) {
2383 count = min_t(unsigned int, conn->mtu, len);
2384
2385 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2386 if (!*frag)
2387 goto fail;
2388
2389 memcpy(skb_put(*frag, count), data, count);
2390
2391 len -= count;
2392 data += count;
2393
2394 frag = &(*frag)->next;
2395 }
2396
2397 return skb;
2398
2399fail:
2400 kfree_skb(skb);
2401 return NULL;
2402}
2403
2404static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2405{
2406 struct l2cap_conf_opt *opt = *ptr;
2407 int len;
2408
2409 len = L2CAP_CONF_OPT_SIZE + opt->len;
2410 *ptr += len;
2411
2412 *type = opt->type;
2413 *olen = opt->len;
2414
2415 switch (opt->len) {
2416 case 1:
2417 *val = *((u8 *) opt->val);
2418 break;
2419
2420 case 2:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002421 *val = __le16_to_cpu(*((__le16 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 break;
2423
2424 case 4:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002425 *val = __le32_to_cpu(*((__le32 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 break;
2427
2428 default:
2429 *val = (unsigned long) opt->val;
2430 break;
2431 }
2432
2433 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2434 return len;
2435}
2436
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2438{
2439 struct l2cap_conf_opt *opt = *ptr;
2440
2441 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2442
2443 opt->type = type;
2444 opt->len = len;
2445
2446 switch (len) {
2447 case 1:
2448 *((u8 *) opt->val) = val;
2449 break;
2450
2451 case 2:
Al Viro8e036fc2007-07-29 00:16:36 -07002452 *((__le16 *) opt->val) = cpu_to_le16(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 break;
2454
2455 case 4:
Al Viro8e036fc2007-07-29 00:16:36 -07002456 *((__le32 *) opt->val) = cpu_to_le32(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 break;
2458
2459 default:
2460 memcpy(opt->val, (void *) val, len);
2461 break;
2462 }
2463
2464 *ptr += L2CAP_CONF_OPT_SIZE + len;
2465}
2466
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002467static void l2cap_ack_timeout(unsigned long arg)
2468{
2469 struct sock *sk = (void *) arg;
2470
2471 bh_lock_sock(sk);
2472 l2cap_send_ack(l2cap_pi(sk));
2473 bh_unlock_sock(sk);
2474}
2475
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002476static inline void l2cap_ertm_init(struct sock *sk)
2477{
2478 l2cap_pi(sk)->expected_ack_seq = 0;
2479 l2cap_pi(sk)->unacked_frames = 0;
2480 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002481 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002482 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002483
2484 setup_timer(&l2cap_pi(sk)->retrans_timer,
2485 l2cap_retrans_timeout, (unsigned long) sk);
2486 setup_timer(&l2cap_pi(sk)->monitor_timer,
2487 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002488 setup_timer(&l2cap_pi(sk)->ack_timer,
2489 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002490
2491 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002492 __skb_queue_head_init(BUSY_QUEUE(sk));
2493
2494 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03002495
2496 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002497}
2498
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002499static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2500{
2501 switch (mode) {
2502 case L2CAP_MODE_STREAMING:
2503 case L2CAP_MODE_ERTM:
2504 if (l2cap_mode_supported(mode, remote_feat_mask))
2505 return mode;
2506 /* fall through */
2507 default:
2508 return L2CAP_MODE_BASIC;
2509 }
2510}
2511
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512static int l2cap_build_conf_req(struct sock *sk, void *data)
2513{
2514 struct l2cap_pinfo *pi = l2cap_pi(sk);
2515 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002516 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 void *ptr = req->data;
2518
2519 BT_DBG("sk %p", sk);
2520
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002521 if (pi->num_conf_req || pi->num_conf_rsp)
2522 goto done;
2523
2524 switch (pi->mode) {
2525 case L2CAP_MODE_STREAMING:
2526 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002527 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002528 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002529
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002530 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002531 default:
2532 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2533 break;
2534 }
2535
2536done:
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002537 switch (pi->mode) {
2538 case L2CAP_MODE_BASIC:
2539 if (pi->imtu != L2CAP_DEFAULT_MTU)
2540 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002541
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002542 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2543 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
2544 break;
2545
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002546 rfc.mode = L2CAP_MODE_BASIC;
2547 rfc.txwin_size = 0;
2548 rfc.max_transmit = 0;
2549 rfc.retrans_timeout = 0;
2550 rfc.monitor_timeout = 0;
2551 rfc.max_pdu_size = 0;
2552
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002553 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2554 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002555 break;
2556
2557 case L2CAP_MODE_ERTM:
2558 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002559 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002560 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002561 rfc.retrans_timeout = 0;
2562 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002563 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002564 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002565 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002566
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002567 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2568 (unsigned long) &rfc);
2569
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002570 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2571 break;
2572
2573 if (pi->fcs == L2CAP_FCS_NONE ||
2574 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2575 pi->fcs = L2CAP_FCS_NONE;
2576 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2577 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002578 break;
2579
2580 case L2CAP_MODE_STREAMING:
2581 rfc.mode = L2CAP_MODE_STREAMING;
2582 rfc.txwin_size = 0;
2583 rfc.max_transmit = 0;
2584 rfc.retrans_timeout = 0;
2585 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002586 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002587 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002588 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002589
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002590 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2591 (unsigned long) &rfc);
2592
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002593 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2594 break;
2595
2596 if (pi->fcs == L2CAP_FCS_NONE ||
2597 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2598 pi->fcs = L2CAP_FCS_NONE;
2599 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2600 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002601 break;
2602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
2604 /* FIXME: Need actual value of the flush timeout */
2605 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2606 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2607
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002608 req->dcid = cpu_to_le16(pi->dcid);
2609 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
2611 return ptr - data;
2612}
2613
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002614static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615{
2616 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002617 struct l2cap_conf_rsp *rsp = data;
2618 void *ptr = rsp->data;
2619 void *req = pi->conf_req;
2620 int len = pi->conf_len;
2621 int type, hint, olen;
2622 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002623 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002624 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002625 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002627 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002628
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002629 while (len >= L2CAP_CONF_OPT_SIZE) {
2630 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002632 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002633 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002634
2635 switch (type) {
2636 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002637 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002638 break;
2639
2640 case L2CAP_CONF_FLUSH_TO:
2641 pi->flush_to = val;
2642 break;
2643
2644 case L2CAP_CONF_QOS:
2645 break;
2646
Marcel Holtmann6464f352007-10-20 13:39:51 +02002647 case L2CAP_CONF_RFC:
2648 if (olen == sizeof(rfc))
2649 memcpy(&rfc, (void *) val, olen);
2650 break;
2651
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002652 case L2CAP_CONF_FCS:
2653 if (val == L2CAP_FCS_NONE)
2654 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2655
2656 break;
2657
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002658 default:
2659 if (hint)
2660 break;
2661
2662 result = L2CAP_CONF_UNKNOWN;
2663 *((u8 *) ptr++) = type;
2664 break;
2665 }
2666 }
2667
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002668 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002669 goto done;
2670
2671 switch (pi->mode) {
2672 case L2CAP_MODE_STREAMING:
2673 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002674 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
2675 pi->mode = l2cap_select_mode(rfc.mode,
2676 pi->conn->feat_mask);
2677 break;
2678 }
2679
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002680 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002681 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002682
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002683 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002684 }
2685
2686done:
2687 if (pi->mode != rfc.mode) {
2688 result = L2CAP_CONF_UNACCEPT;
2689 rfc.mode = pi->mode;
2690
2691 if (pi->num_conf_rsp == 1)
2692 return -ECONNREFUSED;
2693
2694 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2695 sizeof(rfc), (unsigned long) &rfc);
2696 }
2697
2698
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002699 if (result == L2CAP_CONF_SUCCESS) {
2700 /* Configure output options and let the other side know
2701 * which ones we don't like. */
2702
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002703 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2704 result = L2CAP_CONF_UNACCEPT;
2705 else {
2706 pi->omtu = mtu;
2707 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2708 }
2709 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002710
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002711 switch (rfc.mode) {
2712 case L2CAP_MODE_BASIC:
2713 pi->fcs = L2CAP_FCS_NONE;
2714 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2715 break;
2716
2717 case L2CAP_MODE_ERTM:
2718 pi->remote_tx_win = rfc.txwin_size;
2719 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002720
2721 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2722 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002723
2724 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002725
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002726 rfc.retrans_timeout =
2727 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2728 rfc.monitor_timeout =
2729 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002730
2731 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002732
2733 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2734 sizeof(rfc), (unsigned long) &rfc);
2735
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002736 break;
2737
2738 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07002739 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
2740 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002741
2742 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002743
2744 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002745
2746 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2747 sizeof(rfc), (unsigned long) &rfc);
2748
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002749 break;
2750
2751 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002752 result = L2CAP_CONF_UNACCEPT;
2753
2754 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002755 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002756 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002757
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002758 if (result == L2CAP_CONF_SUCCESS)
2759 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2760 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002761 rsp->scid = cpu_to_le16(pi->dcid);
2762 rsp->result = cpu_to_le16(result);
2763 rsp->flags = cpu_to_le16(0x0000);
2764
2765 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766}
2767
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002768static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2769{
2770 struct l2cap_pinfo *pi = l2cap_pi(sk);
2771 struct l2cap_conf_req *req = data;
2772 void *ptr = req->data;
2773 int type, olen;
2774 unsigned long val;
2775 struct l2cap_conf_rfc rfc;
2776
2777 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2778
2779 while (len >= L2CAP_CONF_OPT_SIZE) {
2780 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2781
2782 switch (type) {
2783 case L2CAP_CONF_MTU:
2784 if (val < L2CAP_DEFAULT_MIN_MTU) {
2785 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002786 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002787 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03002788 pi->imtu = val;
2789 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002790 break;
2791
2792 case L2CAP_CONF_FLUSH_TO:
2793 pi->flush_to = val;
2794 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2795 2, pi->flush_to);
2796 break;
2797
2798 case L2CAP_CONF_RFC:
2799 if (olen == sizeof(rfc))
2800 memcpy(&rfc, (void *)val, olen);
2801
2802 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2803 rfc.mode != pi->mode)
2804 return -ECONNREFUSED;
2805
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002806 pi->fcs = 0;
2807
2808 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2809 sizeof(rfc), (unsigned long) &rfc);
2810 break;
2811 }
2812 }
2813
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002814 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
2815 return -ECONNREFUSED;
2816
2817 pi->mode = rfc.mode;
2818
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002819 if (*result == L2CAP_CONF_SUCCESS) {
2820 switch (rfc.mode) {
2821 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002822 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2823 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002824 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002825 break;
2826 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002827 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002828 }
2829 }
2830
2831 req->dcid = cpu_to_le16(pi->dcid);
2832 req->flags = cpu_to_le16(0x0000);
2833
2834 return ptr - data;
2835}
2836
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002837static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838{
2839 struct l2cap_conf_rsp *rsp = data;
2840 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002842 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002844 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002845 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002846 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847
2848 return ptr - data;
2849}
2850
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002851static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2852{
2853 struct l2cap_pinfo *pi = l2cap_pi(sk);
2854 int type, olen;
2855 unsigned long val;
2856 struct l2cap_conf_rfc rfc;
2857
2858 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2859
2860 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2861 return;
2862
2863 while (len >= L2CAP_CONF_OPT_SIZE) {
2864 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2865
2866 switch (type) {
2867 case L2CAP_CONF_RFC:
2868 if (olen == sizeof(rfc))
2869 memcpy(&rfc, (void *)val, olen);
2870 goto done;
2871 }
2872 }
2873
2874done:
2875 switch (rfc.mode) {
2876 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002877 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2878 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002879 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2880 break;
2881 case L2CAP_MODE_STREAMING:
2882 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2883 }
2884}
2885
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002886static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2887{
2888 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2889
2890 if (rej->reason != 0x0000)
2891 return 0;
2892
2893 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2894 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002895 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002896
2897 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002898 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002899
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002900 l2cap_conn_start(conn);
2901 }
2902
2903 return 0;
2904}
2905
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2907{
2908 struct l2cap_chan_list *list = &conn->chan_list;
2909 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2910 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002911 struct sock *parent, *uninitialized_var(sk);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002912 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
2914 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002915 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
2917 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2918
2919 /* Check if we have socket listening on psm */
2920 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2921 if (!parent) {
2922 result = L2CAP_CR_BAD_PSM;
2923 goto sendresp;
2924 }
2925
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002926 /* Check if the ACL is secure enough (if not SDP) */
2927 if (psm != cpu_to_le16(0x0001) &&
2928 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002929 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002930 result = L2CAP_CR_SEC_BLOCK;
2931 goto response;
2932 }
2933
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 result = L2CAP_CR_NO_MEM;
2935
2936 /* Check for backlog size */
2937 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002938 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 goto response;
2940 }
2941
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002942 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 if (!sk)
2944 goto response;
2945
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002946 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947
2948 /* Check if we already have channel with that dcid */
2949 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002950 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 sock_set_flag(sk, SOCK_ZAPPED);
2952 l2cap_sock_kill(sk);
2953 goto response;
2954 }
2955
2956 hci_conn_hold(conn->hcon);
2957
2958 l2cap_sock_init(sk, parent);
2959 bacpy(&bt_sk(sk)->src, conn->src);
2960 bacpy(&bt_sk(sk)->dst, conn->dst);
2961 l2cap_pi(sk)->psm = psm;
2962 l2cap_pi(sk)->dcid = scid;
2963
2964 __l2cap_chan_add(conn, sk, parent);
2965 dcid = l2cap_pi(sk)->scid;
2966
2967 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2968
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 l2cap_pi(sk)->ident = cmd->ident;
2970
Marcel Holtmann984947d2009-02-06 23:35:19 +01002971 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002972 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002973 if (bt_sk(sk)->defer_setup) {
2974 sk->sk_state = BT_CONNECT2;
2975 result = L2CAP_CR_PEND;
2976 status = L2CAP_CS_AUTHOR_PEND;
2977 parent->sk_data_ready(parent, 0);
2978 } else {
2979 sk->sk_state = BT_CONFIG;
2980 result = L2CAP_CR_SUCCESS;
2981 status = L2CAP_CS_NO_INFO;
2982 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002983 } else {
2984 sk->sk_state = BT_CONNECT2;
2985 result = L2CAP_CR_PEND;
2986 status = L2CAP_CS_AUTHEN_PEND;
2987 }
2988 } else {
2989 sk->sk_state = BT_CONNECT2;
2990 result = L2CAP_CR_PEND;
2991 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 }
2993
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002994 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995
2996response:
2997 bh_unlock_sock(parent);
2998
2999sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003000 rsp.scid = cpu_to_le16(scid);
3001 rsp.dcid = cpu_to_le16(dcid);
3002 rsp.result = cpu_to_le16(result);
3003 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003005
3006 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
3007 struct l2cap_info_req info;
3008 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3009
3010 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
3011 conn->info_ident = l2cap_get_ident(conn);
3012
3013 mod_timer(&conn->info_timer, jiffies +
3014 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
3015
3016 l2cap_send_cmd(conn, conn->info_ident,
3017 L2CAP_INFO_REQ, sizeof(info), &info);
3018 }
3019
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003020 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
3021 result == L2CAP_CR_SUCCESS) {
3022 u8 buf[128];
3023 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3024 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3025 l2cap_build_conf_req(sk, buf), buf);
3026 l2cap_pi(sk)->num_conf_req++;
3027 }
3028
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 return 0;
3030}
3031
3032static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3033{
3034 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3035 u16 scid, dcid, result, status;
3036 struct sock *sk;
3037 u8 req[128];
3038
3039 scid = __le16_to_cpu(rsp->scid);
3040 dcid = __le16_to_cpu(rsp->dcid);
3041 result = __le16_to_cpu(rsp->result);
3042 status = __le16_to_cpu(rsp->status);
3043
3044 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
3045
3046 if (scid) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003047 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3048 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003049 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 } else {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003051 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
3052 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03003053 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 }
3055
3056 switch (result) {
3057 case L2CAP_CR_SUCCESS:
3058 sk->sk_state = BT_CONFIG;
3059 l2cap_pi(sk)->ident = 0;
3060 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003061 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
3062
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003063 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
3064 break;
3065
3066 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3067
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3069 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003070 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 break;
3072
3073 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003074 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 break;
3076
3077 default:
3078 l2cap_chan_del(sk, ECONNREFUSED);
3079 break;
3080 }
3081
3082 bh_unlock_sock(sk);
3083 return 0;
3084}
3085
Mat Martineau8c462b62010-08-24 15:35:42 -07003086static inline void set_default_fcs(struct l2cap_pinfo *pi)
3087{
3088 /* FCS is enabled only in ERTM or streaming mode, if one or both
3089 * sides request it.
3090 */
3091 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
3092 pi->fcs = L2CAP_FCS_NONE;
3093 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
3094 pi->fcs = L2CAP_FCS_CRC16;
3095}
3096
Al Viro88219a02007-07-29 00:17:25 -07003097static 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 -07003098{
3099 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3100 u16 dcid, flags;
3101 u8 rsp[64];
3102 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003103 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
3105 dcid = __le16_to_cpu(req->dcid);
3106 flags = __le16_to_cpu(req->flags);
3107
3108 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3109
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003110 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3111 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 return -ENOENT;
3113
Gustavo F. Padovanb0239c82010-09-08 14:59:44 -03003114 if (sk->sk_state == BT_DISCONN)
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003115 goto unlock;
3116
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003117 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003118 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003119 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
3120 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3121 l2cap_build_conf_rsp(sk, rsp,
3122 L2CAP_CONF_REJECT, flags), rsp);
3123 goto unlock;
3124 }
3125
3126 /* Store config. */
3127 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
3128 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129
3130 if (flags & 0x0001) {
3131 /* Incomplete config. Send empty response. */
3132 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003133 l2cap_build_conf_rsp(sk, rsp,
3134 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 goto unlock;
3136 }
3137
3138 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003139 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003140 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003141 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003145 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003146 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003147
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003148 /* Reset config buffer. */
3149 l2cap_pi(sk)->conf_len = 0;
3150
Marcel Holtmann876d9482007-10-20 13:35:42 +02003151 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
3152 goto unlock;
3153
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003155 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003156
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003158
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003159 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003160 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003161 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003162 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3163 l2cap_ertm_init(sk);
3164
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02003166 goto unlock;
3167 }
3168
3169 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003170 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003172 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003173 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 }
3175
3176unlock:
3177 bh_unlock_sock(sk);
3178 return 0;
3179}
3180
3181static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3182{
3183 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3184 u16 scid, flags, result;
3185 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003186 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
3188 scid = __le16_to_cpu(rsp->scid);
3189 flags = __le16_to_cpu(rsp->flags);
3190 result = __le16_to_cpu(rsp->result);
3191
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003192 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
3193 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003195 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3196 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 return 0;
3198
3199 switch (result) {
3200 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003201 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 break;
3203
3204 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003205 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003206 char req[64];
3207
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003208 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003209 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003210 goto done;
3211 }
3212
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003213 /* throw out any old stored conf requests */
3214 result = L2CAP_CONF_SUCCESS;
3215 len = l2cap_parse_conf_rsp(sk, rsp->data,
3216 len, req, &result);
3217 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003218 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003219 goto done;
3220 }
3221
3222 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3223 L2CAP_CONF_REQ, len, req);
3224 l2cap_pi(sk)->num_conf_req++;
3225 if (result != L2CAP_CONF_SUCCESS)
3226 goto done;
3227 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 }
3229
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003230 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003231 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003233 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 goto done;
3235 }
3236
3237 if (flags & 0x01)
3238 goto done;
3239
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3241
3242 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07003243 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003244
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003246 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003248 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003249 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3250 l2cap_ertm_init(sk);
3251
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 l2cap_chan_ready(sk);
3253 }
3254
3255done:
3256 bh_unlock_sock(sk);
3257 return 0;
3258}
3259
3260static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3261{
3262 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3263 struct l2cap_disconn_rsp rsp;
3264 u16 dcid, scid;
3265 struct sock *sk;
3266
3267 scid = __le16_to_cpu(req->scid);
3268 dcid = __le16_to_cpu(req->dcid);
3269
3270 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3271
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003272 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3273 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 return 0;
3275
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003276 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3277 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3279
3280 sk->sk_shutdown = SHUTDOWN_MASK;
3281
3282 l2cap_chan_del(sk, ECONNRESET);
3283 bh_unlock_sock(sk);
3284
3285 l2cap_sock_kill(sk);
3286 return 0;
3287}
3288
3289static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3290{
3291 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3292 u16 dcid, scid;
3293 struct sock *sk;
3294
3295 scid = __le16_to_cpu(rsp->scid);
3296 dcid = __le16_to_cpu(rsp->dcid);
3297
3298 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3299
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003300 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3301 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 return 0;
3303
3304 l2cap_chan_del(sk, 0);
3305 bh_unlock_sock(sk);
3306
3307 l2cap_sock_kill(sk);
3308 return 0;
3309}
3310
3311static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3312{
3313 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 u16 type;
3315
3316 type = __le16_to_cpu(req->type);
3317
3318 BT_DBG("type 0x%4.4x", type);
3319
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003320 if (type == L2CAP_IT_FEAT_MASK) {
3321 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003322 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003323 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3324 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3325 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003326 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003327 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3328 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003329 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003330 l2cap_send_cmd(conn, cmd->ident,
3331 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003332 } else if (type == L2CAP_IT_FIXED_CHAN) {
3333 u8 buf[12];
3334 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3335 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3336 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3337 memcpy(buf + 4, l2cap_fixed_chan, 8);
3338 l2cap_send_cmd(conn, cmd->ident,
3339 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003340 } else {
3341 struct l2cap_info_rsp rsp;
3342 rsp.type = cpu_to_le16(type);
3343 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3344 l2cap_send_cmd(conn, cmd->ident,
3345 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347
3348 return 0;
3349}
3350
3351static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3352{
3353 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3354 u16 type, result;
3355
3356 type = __le16_to_cpu(rsp->type);
3357 result = __le16_to_cpu(rsp->result);
3358
3359 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3360
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003361 del_timer(&conn->info_timer);
3362
Ville Tervoadb08ed2010-08-04 09:43:33 +03003363 if (result != L2CAP_IR_SUCCESS) {
3364 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3365 conn->info_ident = 0;
3366
3367 l2cap_conn_start(conn);
3368
3369 return 0;
3370 }
3371
Marcel Holtmann984947d2009-02-06 23:35:19 +01003372 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003373 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003374
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003375 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003376 struct l2cap_info_req req;
3377 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3378
3379 conn->info_ident = l2cap_get_ident(conn);
3380
3381 l2cap_send_cmd(conn, conn->info_ident,
3382 L2CAP_INFO_REQ, sizeof(req), &req);
3383 } else {
3384 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3385 conn->info_ident = 0;
3386
3387 l2cap_conn_start(conn);
3388 }
3389 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003390 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003391 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003392
3393 l2cap_conn_start(conn);
3394 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003395
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 return 0;
3397}
3398
3399static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3400{
3401 u8 *data = skb->data;
3402 int len = skb->len;
3403 struct l2cap_cmd_hdr cmd;
3404 int err = 0;
3405
3406 l2cap_raw_recv(conn, skb);
3407
3408 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003409 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3411 data += L2CAP_CMD_HDR_SIZE;
3412 len -= L2CAP_CMD_HDR_SIZE;
3413
Al Viro88219a02007-07-29 00:17:25 -07003414 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
Al Viro88219a02007-07-29 00:17:25 -07003416 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 -07003417
Al Viro88219a02007-07-29 00:17:25 -07003418 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 BT_DBG("corrupted command");
3420 break;
3421 }
3422
3423 switch (cmd.code) {
3424 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003425 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 break;
3427
3428 case L2CAP_CONN_REQ:
3429 err = l2cap_connect_req(conn, &cmd, data);
3430 break;
3431
3432 case L2CAP_CONN_RSP:
3433 err = l2cap_connect_rsp(conn, &cmd, data);
3434 break;
3435
3436 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003437 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 break;
3439
3440 case L2CAP_CONF_RSP:
3441 err = l2cap_config_rsp(conn, &cmd, data);
3442 break;
3443
3444 case L2CAP_DISCONN_REQ:
3445 err = l2cap_disconnect_req(conn, &cmd, data);
3446 break;
3447
3448 case L2CAP_DISCONN_RSP:
3449 err = l2cap_disconnect_rsp(conn, &cmd, data);
3450 break;
3451
3452 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003453 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 break;
3455
3456 case L2CAP_ECHO_RSP:
3457 break;
3458
3459 case L2CAP_INFO_REQ:
3460 err = l2cap_information_req(conn, &cmd, data);
3461 break;
3462
3463 case L2CAP_INFO_RSP:
3464 err = l2cap_information_rsp(conn, &cmd, data);
3465 break;
3466
3467 default:
3468 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3469 err = -EINVAL;
3470 break;
3471 }
3472
3473 if (err) {
3474 struct l2cap_cmd_rej rej;
3475 BT_DBG("error %d", err);
3476
3477 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003478 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3480 }
3481
Al Viro88219a02007-07-29 00:17:25 -07003482 data += cmd_len;
3483 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 }
3485
3486 kfree_skb(skb);
3487}
3488
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003489static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3490{
3491 u16 our_fcs, rcv_fcs;
3492 int hdr_size = L2CAP_HDR_SIZE + 2;
3493
3494 if (pi->fcs == L2CAP_FCS_CRC16) {
3495 skb_trim(skb, skb->len - 2);
3496 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3497 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3498
3499 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003500 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003501 }
3502 return 0;
3503}
3504
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003505static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3506{
3507 struct l2cap_pinfo *pi = l2cap_pi(sk);
3508 u16 control = 0;
3509
3510 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003511
3512 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3513
3514 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003515 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003516 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003517 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003518 }
3519
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03003520 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3521 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003522
3523 l2cap_ertm_send(sk);
3524
3525 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3526 pi->frames_sent == 0) {
3527 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003528 l2cap_send_sframe(pi, control);
3529 }
3530}
3531
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003532static 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 -03003533{
3534 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003535 struct l2cap_pinfo *pi = l2cap_pi(sk);
3536 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003537
3538 bt_cb(skb)->tx_seq = tx_seq;
3539 bt_cb(skb)->sar = sar;
3540
3541 next_skb = skb_peek(SREJ_QUEUE(sk));
3542 if (!next_skb) {
3543 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003544 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003545 }
3546
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003547 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3548 if (tx_seq_offset < 0)
3549 tx_seq_offset += 64;
3550
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003551 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003552 if (bt_cb(next_skb)->tx_seq == tx_seq)
3553 return -EINVAL;
3554
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003555 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
3556 pi->buffer_seq) % 64;
3557 if (next_tx_seq_offset < 0)
3558 next_tx_seq_offset += 64;
3559
3560 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003561 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003562 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003563 }
3564
3565 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3566 break;
3567
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003568 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003569
3570 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003571
3572 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003573}
3574
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003575static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3576{
3577 struct l2cap_pinfo *pi = l2cap_pi(sk);
3578 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003579 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003580
3581 switch (control & L2CAP_CTRL_SAR) {
3582 case L2CAP_SDU_UNSEGMENTED:
3583 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3584 goto drop;
3585
3586 err = sock_queue_rcv_skb(sk, skb);
3587 if (!err)
3588 return err;
3589
3590 break;
3591
3592 case L2CAP_SDU_START:
3593 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3594 goto drop;
3595
3596 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003597
3598 if (pi->sdu_len > pi->imtu)
3599 goto disconnect;
3600
3601 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003602 if (!pi->sdu)
3603 return -ENOMEM;
3604
3605 /* pull sdu_len bytes only after alloc, because of Local Busy
3606 * condition we have to be sure that this will be executed
3607 * only once, i.e., when alloc does not fail */
3608 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003609
3610 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3611
3612 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3613 pi->partial_sdu_len = skb->len;
3614 break;
3615
3616 case L2CAP_SDU_CONTINUE:
3617 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3618 goto disconnect;
3619
3620 if (!pi->sdu)
3621 goto disconnect;
3622
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003623 pi->partial_sdu_len += skb->len;
3624 if (pi->partial_sdu_len > pi->sdu_len)
3625 goto drop;
3626
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003627 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3628
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003629 break;
3630
3631 case L2CAP_SDU_END:
3632 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3633 goto disconnect;
3634
3635 if (!pi->sdu)
3636 goto disconnect;
3637
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003638 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003639 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003640
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003641 if (pi->partial_sdu_len > pi->imtu)
3642 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003643
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003644 if (pi->partial_sdu_len != pi->sdu_len)
3645 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003646
3647 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003648 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003649
3650 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003651 if (!_skb) {
3652 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3653 return -ENOMEM;
3654 }
3655
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003656 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003657 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003658 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003659 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3660 return err;
3661 }
3662
3663 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3664 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003665
3666 kfree_skb(pi->sdu);
3667 break;
3668 }
3669
3670 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003671 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003672
3673drop:
3674 kfree_skb(pi->sdu);
3675 pi->sdu = NULL;
3676
3677disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003678 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003679 kfree_skb(skb);
3680 return 0;
3681}
3682
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003683static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003684{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003685 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003686 struct sk_buff *skb;
3687 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003688 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003689
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003690 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3691 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3692 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3693 if (err < 0) {
3694 skb_queue_head(BUSY_QUEUE(sk), skb);
3695 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003696 }
3697
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003698 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003699 }
3700
3701 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3702 goto done;
3703
3704 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3705 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3706 l2cap_send_sframe(pi, control);
3707 l2cap_pi(sk)->retry_count = 1;
3708
3709 del_timer(&pi->retrans_timer);
3710 __mod_monitor_timer();
3711
3712 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3713
3714done:
3715 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3716 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3717
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003718 BT_DBG("sk %p, Exit local busy", sk);
3719
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003720 return 0;
3721}
3722
3723static void l2cap_busy_work(struct work_struct *work)
3724{
3725 DECLARE_WAITQUEUE(wait, current);
3726 struct l2cap_pinfo *pi =
3727 container_of(work, struct l2cap_pinfo, busy_work);
3728 struct sock *sk = (struct sock *)pi;
3729 int n_tries = 0, timeo = HZ/5, err;
3730 struct sk_buff *skb;
3731
3732 lock_sock(sk);
3733
3734 add_wait_queue(sk_sleep(sk), &wait);
3735 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3736 set_current_state(TASK_INTERRUPTIBLE);
3737
3738 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3739 err = -EBUSY;
3740 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3741 break;
3742 }
3743
3744 if (!timeo)
3745 timeo = HZ/5;
3746
3747 if (signal_pending(current)) {
3748 err = sock_intr_errno(timeo);
3749 break;
3750 }
3751
3752 release_sock(sk);
3753 timeo = schedule_timeout(timeo);
3754 lock_sock(sk);
3755
3756 err = sock_error(sk);
3757 if (err)
3758 break;
3759
3760 if (l2cap_try_push_rx_skb(sk) == 0)
3761 break;
3762 }
3763
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003765 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003766
3767 release_sock(sk);
3768}
3769
3770static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3771{
3772 struct l2cap_pinfo *pi = l2cap_pi(sk);
3773 int sctrl, err;
3774
3775 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3776 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3777 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003778 return l2cap_try_push_rx_skb(sk);
3779
3780
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003781 }
3782
3783 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3784 if (err >= 0) {
3785 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3786 return err;
3787 }
3788
3789 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003790 BT_DBG("sk %p, Enter local busy", sk);
3791
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003792 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3793 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3794 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3795
3796 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3797 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3798 l2cap_send_sframe(pi, sctrl);
3799
3800 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3801
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003802 del_timer(&pi->ack_timer);
3803
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003804 queue_work(_busy_wq, &pi->busy_work);
3805
3806 return err;
3807}
3808
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003809static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003810{
3811 struct l2cap_pinfo *pi = l2cap_pi(sk);
3812 struct sk_buff *_skb;
3813 int err = -EINVAL;
3814
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003815 /*
3816 * TODO: We have to notify the userland if some data is lost with the
3817 * Streaming Mode.
3818 */
3819
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003820 switch (control & L2CAP_CTRL_SAR) {
3821 case L2CAP_SDU_UNSEGMENTED:
3822 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3823 kfree_skb(pi->sdu);
3824 break;
3825 }
3826
3827 err = sock_queue_rcv_skb(sk, skb);
3828 if (!err)
3829 return 0;
3830
3831 break;
3832
3833 case L2CAP_SDU_START:
3834 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3835 kfree_skb(pi->sdu);
3836 break;
3837 }
3838
3839 pi->sdu_len = get_unaligned_le16(skb->data);
3840 skb_pull(skb, 2);
3841
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003842 if (pi->sdu_len > pi->imtu) {
3843 err = -EMSGSIZE;
3844 break;
3845 }
3846
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003847 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3848 if (!pi->sdu) {
3849 err = -ENOMEM;
3850 break;
3851 }
3852
3853 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3854
3855 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3856 pi->partial_sdu_len = skb->len;
3857 err = 0;
3858 break;
3859
3860 case L2CAP_SDU_CONTINUE:
3861 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3862 break;
3863
3864 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3865
3866 pi->partial_sdu_len += skb->len;
3867 if (pi->partial_sdu_len > pi->sdu_len)
3868 kfree_skb(pi->sdu);
3869 else
3870 err = 0;
3871
3872 break;
3873
3874 case L2CAP_SDU_END:
3875 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3876 break;
3877
3878 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3879
3880 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3881 pi->partial_sdu_len += skb->len;
3882
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003883 if (pi->partial_sdu_len > pi->imtu)
3884 goto drop;
3885
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003886 if (pi->partial_sdu_len == pi->sdu_len) {
3887 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3888 err = sock_queue_rcv_skb(sk, _skb);
3889 if (err < 0)
3890 kfree_skb(_skb);
3891 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003892 err = 0;
3893
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003894drop:
3895 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003896 break;
3897 }
3898
3899 kfree_skb(skb);
3900 return err;
3901}
3902
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003903static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3904{
3905 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003906 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003907
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003908 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003909 if (bt_cb(skb)->tx_seq != tx_seq)
3910 break;
3911
3912 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003913 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003914 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003915 l2cap_pi(sk)->buffer_seq_srej =
3916 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003917 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003918 }
3919}
3920
3921static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3922{
3923 struct l2cap_pinfo *pi = l2cap_pi(sk);
3924 struct srej_list *l, *tmp;
3925 u16 control;
3926
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003927 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003928 if (l->tx_seq == tx_seq) {
3929 list_del(&l->list);
3930 kfree(l);
3931 return;
3932 }
3933 control = L2CAP_SUPER_SELECT_REJECT;
3934 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3935 l2cap_send_sframe(pi, control);
3936 list_del(&l->list);
3937 list_add_tail(&l->list, SREJ_LIST(sk));
3938 }
3939}
3940
3941static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3942{
3943 struct l2cap_pinfo *pi = l2cap_pi(sk);
3944 struct srej_list *new;
3945 u16 control;
3946
3947 while (tx_seq != pi->expected_tx_seq) {
3948 control = L2CAP_SUPER_SELECT_REJECT;
3949 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3950 l2cap_send_sframe(pi, control);
3951
3952 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003953 new->tx_seq = pi->expected_tx_seq;
3954 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003955 list_add_tail(&new->list, SREJ_LIST(sk));
3956 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003957 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003958}
3959
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003960static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3961{
3962 struct l2cap_pinfo *pi = l2cap_pi(sk);
3963 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003964 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003965 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003966 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003967 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003968 int err = 0;
3969
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003970 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3971 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003972
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003973 if (L2CAP_CTRL_FINAL & rx_control &&
3974 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003975 del_timer(&pi->monitor_timer);
3976 if (pi->unacked_frames > 0)
3977 __mod_retrans_timer();
3978 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3979 }
3980
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003981 pi->expected_ack_seq = req_seq;
3982 l2cap_drop_acked_frames(sk);
3983
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003984 if (tx_seq == pi->expected_tx_seq)
3985 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003987 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3988 if (tx_seq_offset < 0)
3989 tx_seq_offset += 64;
3990
3991 /* invalid tx_seq */
3992 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003993 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003994 goto drop;
3995 }
3996
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003997 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3998 goto drop;
3999
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004000 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4001 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004002
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004003 first = list_first_entry(SREJ_LIST(sk),
4004 struct srej_list, list);
4005 if (tx_seq == first->tx_seq) {
4006 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
4007 l2cap_check_srej_gap(sk, tx_seq);
4008
4009 list_del(&first->list);
4010 kfree(first);
4011
4012 if (list_empty(SREJ_LIST(sk))) {
4013 pi->buffer_seq = pi->buffer_seq_srej;
4014 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03004015 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004016 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004017 }
4018 } else {
4019 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004020
4021 /* duplicated tx_seq */
4022 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
4023 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004024
4025 list_for_each_entry(l, SREJ_LIST(sk), list) {
4026 if (l->tx_seq == tx_seq) {
4027 l2cap_resend_srejframe(sk, tx_seq);
4028 return 0;
4029 }
4030 }
4031 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004032 }
4033 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004034 expected_tx_seq_offset =
4035 (pi->expected_tx_seq - pi->buffer_seq) % 64;
4036 if (expected_tx_seq_offset < 0)
4037 expected_tx_seq_offset += 64;
4038
4039 /* duplicated tx_seq */
4040 if (tx_seq_offset < expected_tx_seq_offset)
4041 goto drop;
4042
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004043 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004044
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004045 BT_DBG("sk %p, Enter SREJ", sk);
4046
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004047 INIT_LIST_HEAD(SREJ_LIST(sk));
4048 pi->buffer_seq_srej = pi->buffer_seq;
4049
4050 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004051 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004052 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
4053
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004054 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
4055
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004056 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03004057
4058 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004059 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004060 return 0;
4061
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004062expected:
4063 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4064
4065 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03004066 bt_cb(skb)->tx_seq = tx_seq;
4067 bt_cb(skb)->sar = sar;
4068 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004069 return 0;
4070 }
4071
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004072 err = l2cap_push_rx_skb(sk, skb, rx_control);
4073 if (err < 0)
4074 return 0;
4075
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004076 if (rx_control & L2CAP_CTRL_FINAL) {
4077 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4078 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004079 else
4080 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004081 }
4082
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004083 __mod_ack_timer();
4084
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03004085 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
4086 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004087 l2cap_send_ack(pi);
4088
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004089 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004090
4091drop:
4092 kfree_skb(skb);
4093 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004094}
4095
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004096static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004097{
4098 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004099
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004100 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
4101 rx_control);
4102
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03004103 pi->expected_ack_seq = __get_reqseq(rx_control);
4104 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004105
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004106 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004107 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004108 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
4109 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4110 (pi->unacked_frames > 0))
4111 __mod_retrans_timer();
4112
4113 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4114 l2cap_send_srejtail(sk);
4115 } else {
4116 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004117 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004118
4119 } else if (rx_control & L2CAP_CTRL_FINAL) {
4120 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004121
4122 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4123 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004124 else
4125 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004126
4127 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004128 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
4129 (pi->unacked_frames > 0))
4130 __mod_retrans_timer();
4131
4132 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004133 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004134 l2cap_send_ack(pi);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004135 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004136 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004137 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004138 }
4139}
4140
4141static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
4142{
4143 struct l2cap_pinfo *pi = l2cap_pi(sk);
4144 u8 tx_seq = __get_reqseq(rx_control);
4145
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004146 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4147
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004148 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4149
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03004150 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004151 l2cap_drop_acked_frames(sk);
4152
4153 if (rx_control & L2CAP_CTRL_FINAL) {
4154 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
4155 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004156 else
4157 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004158 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004159 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004160
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03004161 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004162 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004163 }
4164}
4165static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
4166{
4167 struct l2cap_pinfo *pi = l2cap_pi(sk);
4168 u8 tx_seq = __get_reqseq(rx_control);
4169
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004170 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4171
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004172 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
4173
4174 if (rx_control & L2CAP_CTRL_POLL) {
4175 pi->expected_ack_seq = tx_seq;
4176 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004177
4178 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004179 l2cap_retransmit_one_frame(sk, tx_seq);
4180
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004181 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004182
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004183 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4184 pi->srej_save_reqseq = tx_seq;
4185 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4186 }
4187 } else if (rx_control & L2CAP_CTRL_FINAL) {
4188 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
4189 pi->srej_save_reqseq == tx_seq)
4190 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
4191 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004192 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004193 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004194 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004195 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
4196 pi->srej_save_reqseq = tx_seq;
4197 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
4198 }
4199 }
4200}
4201
4202static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
4203{
4204 struct l2cap_pinfo *pi = l2cap_pi(sk);
4205 u8 tx_seq = __get_reqseq(rx_control);
4206
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004207 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
4208
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004209 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
4210 pi->expected_ack_seq = tx_seq;
4211 l2cap_drop_acked_frames(sk);
4212
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004213 if (rx_control & L2CAP_CTRL_POLL)
4214 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
4215
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004216 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
4217 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03004218 if (rx_control & L2CAP_CTRL_POLL)
4219 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004220 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004221 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004222
4223 if (rx_control & L2CAP_CTRL_POLL)
4224 l2cap_send_srejtail(sk);
4225 else
4226 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004227}
4228
4229static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
4230{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004231 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
4232
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03004233 if (L2CAP_CTRL_FINAL & rx_control &&
4234 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004235 del_timer(&l2cap_pi(sk)->monitor_timer);
4236 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004237 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004238 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004239 }
4240
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004241 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
4242 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004243 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004244 break;
4245
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004246 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004247 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004248 break;
4249
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004250 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004251 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004252 break;
4253
4254 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004255 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004256 break;
4257 }
4258
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004259 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004260 return 0;
4261}
4262
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004263static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4264{
4265 struct l2cap_pinfo *pi = l2cap_pi(sk);
4266 u16 control;
4267 u8 req_seq;
4268 int len, next_tx_seq_offset, req_seq_offset;
4269
4270 control = get_unaligned_le16(skb->data);
4271 skb_pull(skb, 2);
4272 len = skb->len;
4273
4274 /*
4275 * We can just drop the corrupted I-frame here.
4276 * Receiver will miss it and start proper recovery
4277 * procedures and ask retransmission.
4278 */
4279 if (l2cap_check_fcs(pi, skb))
4280 goto drop;
4281
4282 if (__is_sar_start(control) && __is_iframe(control))
4283 len -= 2;
4284
4285 if (pi->fcs == L2CAP_FCS_CRC16)
4286 len -= 2;
4287
4288 if (len > pi->mps) {
4289 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4290 goto drop;
4291 }
4292
4293 req_seq = __get_reqseq(control);
4294 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
4295 if (req_seq_offset < 0)
4296 req_seq_offset += 64;
4297
4298 next_tx_seq_offset =
4299 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
4300 if (next_tx_seq_offset < 0)
4301 next_tx_seq_offset += 64;
4302
4303 /* check for invalid req-seq */
4304 if (req_seq_offset > next_tx_seq_offset) {
4305 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4306 goto drop;
4307 }
4308
4309 if (__is_iframe(control)) {
4310 if (len < 0) {
4311 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4312 goto drop;
4313 }
4314
4315 l2cap_data_channel_iframe(sk, control, skb);
4316 } else {
4317 if (len != 0) {
4318 BT_ERR("%d", len);
4319 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
4320 goto drop;
4321 }
4322
4323 l2cap_data_channel_sframe(sk, control, skb);
4324 }
4325
4326 return 0;
4327
4328drop:
4329 kfree_skb(skb);
4330 return 0;
4331}
4332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4334{
4335 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004336 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04004337 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004338 u8 tx_seq;
4339 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
4341 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
4342 if (!sk) {
4343 BT_DBG("unknown cid 0x%4.4x", cid);
4344 goto drop;
4345 }
4346
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004347 pi = l2cap_pi(sk);
4348
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 BT_DBG("sk %p, len %d", sk, skb->len);
4350
4351 if (sk->sk_state != BT_CONNECTED)
4352 goto drop;
4353
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004354 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004355 case L2CAP_MODE_BASIC:
4356 /* If socket recv buffers overflows we drop data here
4357 * which is *bad* because L2CAP has to be reliable.
4358 * But we don't have any other choice. L2CAP doesn't
4359 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004361 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004362 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004364 if (!sock_queue_rcv_skb(sk, skb))
4365 goto done;
4366 break;
4367
4368 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004369 if (!sock_owned_by_user(sk)) {
4370 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004371 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004372 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004373 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004374 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004375
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004376 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004377
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004378 case L2CAP_MODE_STREAMING:
4379 control = get_unaligned_le16(skb->data);
4380 skb_pull(skb, 2);
4381 len = skb->len;
4382
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004383 if (l2cap_check_fcs(pi, skb))
4384 goto drop;
4385
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004386 if (__is_sar_start(control))
4387 len -= 2;
4388
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004389 if (pi->fcs == L2CAP_FCS_CRC16)
4390 len -= 2;
4391
Nathan Holstein51893f82010-06-09 15:46:25 -04004392 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004393 goto drop;
4394
4395 tx_seq = __get_txseq(control);
4396
4397 if (pi->expected_tx_seq == tx_seq)
4398 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
4399 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03004400 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004401
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004402 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004403
4404 goto done;
4405
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004406 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03004407 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004408 break;
4409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
4411drop:
4412 kfree_skb(skb);
4413
4414done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004415 if (sk)
4416 bh_unlock_sock(sk);
4417
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 return 0;
4419}
4420
Al Viro8e036fc2007-07-29 00:16:36 -07004421static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422{
4423 struct sock *sk;
4424
4425 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4426 if (!sk)
4427 goto drop;
4428
4429 BT_DBG("sk %p, len %d", sk, skb->len);
4430
4431 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4432 goto drop;
4433
4434 if (l2cap_pi(sk)->imtu < skb->len)
4435 goto drop;
4436
4437 if (!sock_queue_rcv_skb(sk, skb))
4438 goto done;
4439
4440drop:
4441 kfree_skb(skb);
4442
4443done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004444 if (sk)
4445 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 return 0;
4447}
4448
4449static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4450{
4451 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004452 u16 cid, len;
4453 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454
4455 skb_pull(skb, L2CAP_HDR_SIZE);
4456 cid = __le16_to_cpu(lh->cid);
4457 len = __le16_to_cpu(lh->len);
4458
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004459 if (len != skb->len) {
4460 kfree_skb(skb);
4461 return;
4462 }
4463
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4465
4466 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004467 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468 l2cap_sig_channel(conn, skb);
4469 break;
4470
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004471 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004472 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473 skb_pull(skb, 2);
4474 l2cap_conless_channel(conn, psm, skb);
4475 break;
4476
4477 default:
4478 l2cap_data_channel(conn, cid, skb);
4479 break;
4480 }
4481}
4482
4483/* ---- L2CAP interface with lower layer (HCI) ---- */
4484
4485static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4486{
4487 int exact = 0, lm1 = 0, lm2 = 0;
4488 register struct sock *sk;
4489 struct hlist_node *node;
4490
4491 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004492 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493
4494 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4495
4496 /* Find listening sockets and check their link_mode */
4497 read_lock(&l2cap_sk_list.lock);
4498 sk_for_each(sk, node, &l2cap_sk_list.head) {
4499 if (sk->sk_state != BT_LISTEN)
4500 continue;
4501
4502 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004503 lm1 |= HCI_LM_ACCEPT;
4504 if (l2cap_pi(sk)->role_switch)
4505 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004507 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4508 lm2 |= HCI_LM_ACCEPT;
4509 if (l2cap_pi(sk)->role_switch)
4510 lm2 |= HCI_LM_MASTER;
4511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 }
4513 read_unlock(&l2cap_sk_list.lock);
4514
4515 return exact ? lm1 : lm2;
4516}
4517
4518static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4519{
Marcel Holtmann01394182006-07-03 10:02:46 +02004520 struct l2cap_conn *conn;
4521
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4523
4524 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004525 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526
4527 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 conn = l2cap_conn_add(hcon, status);
4529 if (conn)
4530 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004531 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 l2cap_conn_del(hcon, bt_err(status));
4533
4534 return 0;
4535}
4536
Marcel Holtmann2950f212009-02-12 14:02:50 +01004537static int l2cap_disconn_ind(struct hci_conn *hcon)
4538{
4539 struct l2cap_conn *conn = hcon->l2cap_data;
4540
4541 BT_DBG("hcon %p", hcon);
4542
4543 if (hcon->type != ACL_LINK || !conn)
4544 return 0x13;
4545
4546 return conn->disc_reason;
4547}
4548
4549static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550{
4551 BT_DBG("hcon %p reason %d", hcon, reason);
4552
4553 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004554 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555
4556 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004557
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 return 0;
4559}
4560
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004561static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4562{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004563 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004564 return;
4565
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004566 if (encrypt == 0x00) {
4567 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4568 l2cap_sock_clear_timer(sk);
4569 l2cap_sock_set_timer(sk, HZ * 5);
4570 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4571 __l2cap_sock_close(sk, ECONNREFUSED);
4572 } else {
4573 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4574 l2cap_sock_clear_timer(sk);
4575 }
4576}
4577
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004578static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579{
4580 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004581 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583
Marcel Holtmann01394182006-07-03 10:02:46 +02004584 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004586
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 l = &conn->chan_list;
4588
4589 BT_DBG("conn %p", conn);
4590
4591 read_lock(&l->lock);
4592
4593 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4594 bh_lock_sock(sk);
4595
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004596 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4597 bh_unlock_sock(sk);
4598 continue;
4599 }
4600
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004601 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004602 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004603 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004604 bh_unlock_sock(sk);
4605 continue;
4606 }
4607
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004608 if (sk->sk_state == BT_CONNECT) {
4609 if (!status) {
4610 struct l2cap_conn_req req;
4611 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4612 req.psm = l2cap_pi(sk)->psm;
4613
4614 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03004615 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004616
4617 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4618 L2CAP_CONN_REQ, sizeof(req), &req);
4619 } else {
4620 l2cap_sock_clear_timer(sk);
4621 l2cap_sock_set_timer(sk, HZ / 10);
4622 }
4623 } else if (sk->sk_state == BT_CONNECT2) {
4624 struct l2cap_conn_rsp rsp;
4625 __u16 result;
4626
4627 if (!status) {
4628 sk->sk_state = BT_CONFIG;
4629 result = L2CAP_CR_SUCCESS;
4630 } else {
4631 sk->sk_state = BT_DISCONN;
4632 l2cap_sock_set_timer(sk, HZ / 10);
4633 result = L2CAP_CR_SEC_BLOCK;
4634 }
4635
4636 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4637 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4638 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004639 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004640 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4641 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642 }
4643
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644 bh_unlock_sock(sk);
4645 }
4646
4647 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004648
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649 return 0;
4650}
4651
4652static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4653{
4654 struct l2cap_conn *conn = hcon->l2cap_data;
4655
4656 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
4657 goto drop;
4658
4659 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4660
4661 if (flags & ACL_START) {
4662 struct l2cap_hdr *hdr;
4663 int len;
4664
4665 if (conn->rx_len) {
4666 BT_ERR("Unexpected start frame (len %d)", skb->len);
4667 kfree_skb(conn->rx_skb);
4668 conn->rx_skb = NULL;
4669 conn->rx_len = 0;
4670 l2cap_conn_unreliable(conn, ECOMM);
4671 }
4672
4673 if (skb->len < 2) {
4674 BT_ERR("Frame is too short (len %d)", skb->len);
4675 l2cap_conn_unreliable(conn, ECOMM);
4676 goto drop;
4677 }
4678
4679 hdr = (struct l2cap_hdr *) skb->data;
4680 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
4681
4682 if (len == skb->len) {
4683 /* Complete frame received */
4684 l2cap_recv_frame(conn, skb);
4685 return 0;
4686 }
4687
4688 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4689
4690 if (skb->len > len) {
4691 BT_ERR("Frame is too long (len %d, expected len %d)",
4692 skb->len, len);
4693 l2cap_conn_unreliable(conn, ECOMM);
4694 goto drop;
4695 }
4696
4697 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004698 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4699 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700 goto drop;
4701
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004702 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004703 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704 conn->rx_len = len - skb->len;
4705 } else {
4706 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4707
4708 if (!conn->rx_len) {
4709 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4710 l2cap_conn_unreliable(conn, ECOMM);
4711 goto drop;
4712 }
4713
4714 if (skb->len > conn->rx_len) {
4715 BT_ERR("Fragment is too long (len %d, expected %d)",
4716 skb->len, conn->rx_len);
4717 kfree_skb(conn->rx_skb);
4718 conn->rx_skb = NULL;
4719 conn->rx_len = 0;
4720 l2cap_conn_unreliable(conn, ECOMM);
4721 goto drop;
4722 }
4723
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004724 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004725 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 conn->rx_len -= skb->len;
4727
4728 if (!conn->rx_len) {
4729 /* Complete frame received */
4730 l2cap_recv_frame(conn, conn->rx_skb);
4731 conn->rx_skb = NULL;
4732 }
4733 }
4734
4735drop:
4736 kfree_skb(skb);
4737 return 0;
4738}
4739
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004740static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741{
4742 struct sock *sk;
4743 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744
4745 read_lock_bh(&l2cap_sk_list.lock);
4746
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004747 sk_for_each(sk, node, &l2cap_sk_list.head) {
4748 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004750 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4751 batostr(&bt_sk(sk)->src),
4752 batostr(&bt_sk(sk)->dst),
4753 sk->sk_state, __le16_to_cpu(pi->psm),
4754 pi->scid, pi->dcid,
4755 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757
Linus Torvalds1da177e2005-04-16 15:20:36 -07004758 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004759
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004760 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004761}
4762
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004763static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4764{
4765 return single_open(file, l2cap_debugfs_show, inode->i_private);
4766}
4767
4768static const struct file_operations l2cap_debugfs_fops = {
4769 .open = l2cap_debugfs_open,
4770 .read = seq_read,
4771 .llseek = seq_lseek,
4772 .release = single_release,
4773};
4774
4775static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004777static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 .family = PF_BLUETOOTH,
4779 .owner = THIS_MODULE,
4780 .release = l2cap_sock_release,
4781 .bind = l2cap_sock_bind,
4782 .connect = l2cap_sock_connect,
4783 .listen = l2cap_sock_listen,
4784 .accept = l2cap_sock_accept,
4785 .getname = l2cap_sock_getname,
4786 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004787 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004789 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790 .mmap = sock_no_mmap,
4791 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792 .shutdown = l2cap_sock_shutdown,
4793 .setsockopt = l2cap_sock_setsockopt,
4794 .getsockopt = l2cap_sock_getsockopt
4795};
4796
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004797static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798 .family = PF_BLUETOOTH,
4799 .owner = THIS_MODULE,
4800 .create = l2cap_sock_create,
4801};
4802
4803static struct hci_proto l2cap_hci_proto = {
4804 .name = "L2CAP",
4805 .id = HCI_PROTO_L2CAP,
4806 .connect_ind = l2cap_connect_ind,
4807 .connect_cfm = l2cap_connect_cfm,
4808 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004809 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004810 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004811 .recv_acldata = l2cap_recv_acldata
4812};
4813
4814static int __init l2cap_init(void)
4815{
4816 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004817
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818 err = proto_register(&l2cap_proto, 0);
4819 if (err < 0)
4820 return err;
4821
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004822 _busy_wq = create_singlethread_workqueue("l2cap");
4823 if (!_busy_wq)
4824 goto error;
4825
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4827 if (err < 0) {
4828 BT_ERR("L2CAP socket registration failed");
4829 goto error;
4830 }
4831
4832 err = hci_register_proto(&l2cap_hci_proto);
4833 if (err < 0) {
4834 BT_ERR("L2CAP protocol registration failed");
4835 bt_sock_unregister(BTPROTO_L2CAP);
4836 goto error;
4837 }
4838
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004839 if (bt_debugfs) {
4840 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4841 bt_debugfs, NULL, &l2cap_debugfs_fops);
4842 if (!l2cap_debugfs)
4843 BT_ERR("Failed to create L2CAP debug file");
4844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845
4846 BT_INFO("L2CAP ver %s", VERSION);
4847 BT_INFO("L2CAP socket layer initialized");
4848
4849 return 0;
4850
4851error:
4852 proto_unregister(&l2cap_proto);
4853 return err;
4854}
4855
4856static void __exit l2cap_exit(void)
4857{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004858 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004860 flush_workqueue(_busy_wq);
4861 destroy_workqueue(_busy_wq);
4862
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4864 BT_ERR("L2CAP socket unregistration failed");
4865
4866 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4867 BT_ERR("L2CAP protocol unregistration failed");
4868
4869 proto_unregister(&l2cap_proto);
4870}
4871
4872void l2cap_load(void)
4873{
4874 /* Dummy function to trigger automatic L2CAP module loading by
4875 * other modules that use L2CAP sockets but don't use any other
4876 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004877}
4878EXPORT_SYMBOL(l2cap_load);
4879
4880module_init(l2cap_init);
4881module_exit(l2cap_exit);
4882
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004883module_param(disable_ertm, bool, 0644);
4884MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004885
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004886MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004887MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4888MODULE_VERSION(VERSION);
4889MODULE_LICENSE("GPL");
4890MODULE_ALIAS("bt-proto-0");