blob: ca27f3a41536f35d4d608f9f0929b50105658f4d [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
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
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. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
73
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030074static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
75
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
77static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
78{
79 struct sock *s;
80 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
81 if (l2cap_pi(s)->dcid == cid)
82 break;
83 }
84 return s;
85}
86
87static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
88{
89 struct sock *s;
90 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
91 if (l2cap_pi(s)->scid == cid)
92 break;
93 }
94 return s;
95}
96
97/* Find channel with given SCID.
98 * Returns locked socket */
99static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
100{
101 struct sock *s;
102 read_lock(&l->lock);
103 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300104 if (s)
105 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200106 read_unlock(&l->lock);
107 return s;
108}
109
110static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
111{
112 struct sock *s;
113 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
114 if (l2cap_pi(s)->ident == ident)
115 break;
116 }
117 return s;
118}
119
120static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
121{
122 struct sock *s;
123 read_lock(&l->lock);
124 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300125 if (s)
126 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200127 read_unlock(&l->lock);
128 return s;
129}
130
131static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
132{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300133 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200134
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300135 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300136 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200137 return cid;
138 }
139
140 return 0;
141}
142
143static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
144{
145 sock_hold(sk);
146
147 if (l->head)
148 l2cap_pi(l->head)->prev_c = sk;
149
150 l2cap_pi(sk)->next_c = l->head;
151 l2cap_pi(sk)->prev_c = NULL;
152 l->head = sk;
153}
154
155static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
156{
157 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
158
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200159 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200160 if (sk == l->head)
161 l->head = next;
162
163 if (next)
164 l2cap_pi(next)->prev_c = prev;
165 if (prev)
166 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200167 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
169 __sock_put(sk);
170}
171
172static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
173{
174 struct l2cap_chan_list *l = &conn->chan_list;
175
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300176 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
177 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200178
Marcel Holtmann2950f212009-02-12 14:02:50 +0100179 conn->disc_reason = 0x13;
180
Marcel Holtmann01394182006-07-03 10:02:46 +0200181 l2cap_pi(sk)->conn = conn;
182
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300183 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300184 if (conn->hcon->type == LE_LINK) {
185 /* LE connection */
186 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
187 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
188 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
189 } else {
190 /* Alloc CID for connection-oriented socket */
191 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
192 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
193 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200194 } else if (sk->sk_type == SOCK_DGRAM) {
195 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300196 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
197 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200198 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
199 } else {
200 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300201 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
202 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200203 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
204 }
205
206 __l2cap_chan_link(l, sk);
207
208 if (parent)
209 bt_accept_enqueue(parent, sk);
210}
211
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900212/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200213 * Must be called on the locked socket. */
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200214void l2cap_chan_del(struct sock *sk, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200215{
216 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
217 struct sock *parent = bt_sk(sk)->parent;
218
219 l2cap_sock_clear_timer(sk);
220
221 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
222
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900223 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200224 /* Unlink from channel list */
225 l2cap_chan_unlink(&conn->chan_list, sk);
226 l2cap_pi(sk)->conn = NULL;
227 hci_conn_put(conn->hcon);
228 }
229
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200230 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200231 sock_set_flag(sk, SOCK_ZAPPED);
232
233 if (err)
234 sk->sk_err = err;
235
236 if (parent) {
237 bt_accept_unlink(sk);
238 parent->sk_data_ready(parent, 0);
239 } else
240 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300241
242 skb_queue_purge(TX_QUEUE(sk));
243
244 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
245 struct srej_list *l, *tmp;
246
247 del_timer(&l2cap_pi(sk)->retrans_timer);
248 del_timer(&l2cap_pi(sk)->monitor_timer);
249 del_timer(&l2cap_pi(sk)->ack_timer);
250
251 skb_queue_purge(SREJ_QUEUE(sk));
252 skb_queue_purge(BUSY_QUEUE(sk));
253
254 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
255 list_del(&l->list);
256 kfree(l);
257 }
258 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200259}
260
Johan Hedberg8556edd32011-01-19 12:06:50 +0530261static inline u8 l2cap_get_auth_type(struct sock *sk)
262{
263 if (sk->sk_type == SOCK_RAW) {
264 switch (l2cap_pi(sk)->sec_level) {
265 case BT_SECURITY_HIGH:
266 return HCI_AT_DEDICATED_BONDING_MITM;
267 case BT_SECURITY_MEDIUM:
268 return HCI_AT_DEDICATED_BONDING;
269 default:
270 return HCI_AT_NO_BONDING;
271 }
272 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
273 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
274 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
275
276 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
277 return HCI_AT_NO_BONDING_MITM;
278 else
279 return HCI_AT_NO_BONDING;
280 } else {
281 switch (l2cap_pi(sk)->sec_level) {
282 case BT_SECURITY_HIGH:
283 return HCI_AT_GENERAL_BONDING_MITM;
284 case BT_SECURITY_MEDIUM:
285 return HCI_AT_GENERAL_BONDING;
286 default:
287 return HCI_AT_NO_BONDING;
288 }
289 }
290}
291
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200292/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100293static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200294{
295 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100296 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200297
Johan Hedberg8556edd32011-01-19 12:06:50 +0530298 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100299
300 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
301 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200302}
303
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200304u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200305{
306 u8 id;
307
308 /* Get next available identificator.
309 * 1 - 128 are used by kernel.
310 * 129 - 199 are reserved.
311 * 200 - 254 are used by utilities like l2ping, etc.
312 */
313
314 spin_lock_bh(&conn->lock);
315
316 if (++conn->tx_ident > 128)
317 conn->tx_ident = 1;
318
319 id = conn->tx_ident;
320
321 spin_unlock_bh(&conn->lock);
322
323 return id;
324}
325
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200326void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200327{
328 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200329 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200330
331 BT_DBG("code 0x%2.2x", code);
332
333 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300334 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200335
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200336 if (lmp_no_flush_capable(conn->hcon->hdev))
337 flags = ACL_START_NO_FLUSH;
338 else
339 flags = ACL_START;
340
341 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200342}
343
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300344static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300345{
346 struct sk_buff *skb;
347 struct l2cap_hdr *lh;
348 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300349 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200351 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300352
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300353 if (sk->sk_state != BT_CONNECTED)
354 return;
355
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356 if (pi->fcs == L2CAP_FCS_CRC16)
357 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300358
359 BT_DBG("pi %p, control 0x%2.2x", pi, control);
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300362 control |= L2CAP_CTRL_FRAME_TYPE;
363
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300364 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
365 control |= L2CAP_CTRL_FINAL;
366 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
367 }
368
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300369 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
370 control |= L2CAP_CTRL_POLL;
371 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
372 }
373
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374 skb = bt_skb_alloc(count, GFP_ATOMIC);
375 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300376 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300377
378 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300379 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300380 lh->cid = cpu_to_le16(pi->dcid);
381 put_unaligned_le16(control, skb_put(skb, 2));
382
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300383 if (pi->fcs == L2CAP_FCS_CRC16) {
384 u16 fcs = crc16(0, (u8 *)lh, count - 2);
385 put_unaligned_le16(fcs, skb_put(skb, 2));
386 }
387
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200388 if (lmp_no_flush_capable(conn->hcon->hdev))
389 flags = ACL_START_NO_FLUSH;
390 else
391 flags = ACL_START;
392
393 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300394}
395
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300396static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300397{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300398 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300399 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300400 pi->conn_state |= L2CAP_CONN_RNR_SENT;
401 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402 control |= L2CAP_SUPER_RCV_READY;
403
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300404 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
405
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300406 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407}
408
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300409static inline int __l2cap_no_conn_pending(struct sock *sk)
410{
411 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
412}
413
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200414static void l2cap_do_start(struct sock *sk)
415{
416 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
417
418 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100419 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
420 return;
421
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300422 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200423 struct l2cap_conn_req req;
424 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
425 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200426
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200427 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300428 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200429
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200430 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200431 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200432 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200433 } else {
434 struct l2cap_info_req req;
435 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
436
437 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
438 conn->info_ident = l2cap_get_ident(conn);
439
440 mod_timer(&conn->info_timer, jiffies +
441 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
442
443 l2cap_send_cmd(conn, conn->info_ident,
444 L2CAP_INFO_REQ, sizeof(req), &req);
445 }
446}
447
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300448static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
449{
450 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300451 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300452 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
453
454 switch (mode) {
455 case L2CAP_MODE_ERTM:
456 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
457 case L2CAP_MODE_STREAMING:
458 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
459 default:
460 return 0x00;
461 }
462}
463
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200464void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300465{
466 struct l2cap_disconn_req req;
467
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300468 if (!conn)
469 return;
470
471 skb_queue_purge(TX_QUEUE(sk));
472
473 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
474 del_timer(&l2cap_pi(sk)->retrans_timer);
475 del_timer(&l2cap_pi(sk)->monitor_timer);
476 del_timer(&l2cap_pi(sk)->ack_timer);
477 }
478
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300479 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
480 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
481 l2cap_send_cmd(conn, l2cap_get_ident(conn),
482 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300483
484 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300485 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300486}
487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200489static void l2cap_conn_start(struct l2cap_conn *conn)
490{
491 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300492 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200493 struct sock *sk;
494
495 BT_DBG("conn %p", conn);
496
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300497 INIT_LIST_HEAD(&del.list);
498
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499 read_lock(&l->lock);
500
501 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
502 bh_lock_sock(sk);
503
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300504 if (sk->sk_type != SOCK_SEQPACKET &&
505 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200506 bh_unlock_sock(sk);
507 continue;
508 }
509
510 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300511 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300512
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300513 if (!l2cap_check_security(sk) ||
514 !__l2cap_no_conn_pending(sk)) {
515 bh_unlock_sock(sk);
516 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200517 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518
519 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
520 conn->feat_mask)
521 && l2cap_pi(sk)->conf_state &
522 L2CAP_CONF_STATE2_DEVICE) {
523 tmp1 = kzalloc(sizeof(struct sock_del_list),
524 GFP_ATOMIC);
525 tmp1->sk = sk;
526 list_add_tail(&tmp1->list, &del.list);
527 bh_unlock_sock(sk);
528 continue;
529 }
530
531 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
532 req.psm = l2cap_pi(sk)->psm;
533
534 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
535 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
536
537 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
538 L2CAP_CONN_REQ, sizeof(req), &req);
539
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200540 } else if (sk->sk_state == BT_CONNECT2) {
541 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300542 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200543 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
544 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
545
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100546 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100547 if (bt_sk(sk)->defer_setup) {
548 struct sock *parent = bt_sk(sk)->parent;
549 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
550 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
551 parent->sk_data_ready(parent, 0);
552
553 } else {
554 sk->sk_state = BT_CONFIG;
555 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
556 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
557 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200558 } else {
559 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
560 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
561 }
562
563 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
564 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300565
566 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
567 rsp.result != L2CAP_CR_SUCCESS) {
568 bh_unlock_sock(sk);
569 continue;
570 }
571
572 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
573 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
574 l2cap_build_conf_req(sk, buf), buf);
575 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200576 }
577
578 bh_unlock_sock(sk);
579 }
580
581 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300582
583 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
584 bh_lock_sock(tmp1->sk);
585 __l2cap_sock_close(tmp1->sk, ECONNRESET);
586 bh_unlock_sock(tmp1->sk);
587 list_del(&tmp1->list);
588 kfree(tmp1);
589 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
597 struct sock *s, *sk = NULL, *sk1 = NULL;
598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
616 s = node ? sk : sk1;
617 if (s)
618 bh_lock_sock(s);
619 read_unlock(&l2cap_sk_list.lock);
620
621 return s;
622}
623
624static void l2cap_le_conn_ready(struct l2cap_conn *conn)
625{
626 struct l2cap_chan_list *list = &conn->chan_list;
627 struct sock *parent, *uninitialized_var(sk);
628
629 BT_DBG("");
630
631 /* Check if we have socket listening on cid */
632 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
633 conn->src);
634 if (!parent)
635 return;
636
637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
647 write_lock_bh(&list->lock);
648
649 hci_conn_hold(conn->hcon);
650
651 l2cap_sock_init(sk, parent);
652 bacpy(&bt_sk(sk)->src, conn->src);
653 bacpy(&bt_sk(sk)->dst, conn->dst);
654
655 __l2cap_chan_add(conn, sk, parent);
656
657 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
658
659 sk->sk_state = BT_CONNECTED;
660 parent->sk_data_ready(parent, 0);
661
662 write_unlock_bh(&list->lock);
663
664clean:
665 bh_unlock_sock(parent);
666}
667
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200668static void l2cap_conn_ready(struct l2cap_conn *conn)
669{
670 struct l2cap_chan_list *l = &conn->chan_list;
671 struct sock *sk;
672
673 BT_DBG("conn %p", conn);
674
Ville Tervob62f3282011-02-10 22:38:50 -0300675 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
676 l2cap_le_conn_ready(conn);
677
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200678 read_lock(&l->lock);
679
680 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
681 bh_lock_sock(sk);
682
Ville Tervoacd7d372011-02-10 22:38:49 -0300683 if (conn->hcon->type == LE_LINK) {
684 l2cap_sock_clear_timer(sk);
685 sk->sk_state = BT_CONNECTED;
686 sk->sk_state_change(sk);
687 }
688
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300689 if (sk->sk_type != SOCK_SEQPACKET &&
690 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200691 l2cap_sock_clear_timer(sk);
692 sk->sk_state = BT_CONNECTED;
693 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200694 } else if (sk->sk_state == BT_CONNECT)
695 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200696
697 bh_unlock_sock(sk);
698 }
699
700 read_unlock(&l->lock);
701}
702
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703/* Notify sockets that we cannot guaranty reliability anymore */
704static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
705{
706 struct l2cap_chan_list *l = &conn->chan_list;
707 struct sock *sk;
708
709 BT_DBG("conn %p", conn);
710
711 read_lock(&l->lock);
712
713 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100714 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715 sk->sk_err = err;
716 }
717
718 read_unlock(&l->lock);
719}
720
721static void l2cap_info_timeout(unsigned long arg)
722{
723 struct l2cap_conn *conn = (void *) arg;
724
Marcel Holtmann984947d2009-02-06 23:35:19 +0100725 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100726 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100727
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 l2cap_conn_start(conn);
729}
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
732{
Marcel Holtmann01394182006-07-03 10:02:46 +0200733 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Marcel Holtmann01394182006-07-03 10:02:46 +0200735 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 return conn;
737
Marcel Holtmann01394182006-07-03 10:02:46 +0200738 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
739 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
742 hcon->l2cap_data = conn;
743 conn->hcon = hcon;
744
Marcel Holtmann01394182006-07-03 10:02:46 +0200745 BT_DBG("hcon %p conn %p", hcon, conn);
746
Ville Tervoacd7d372011-02-10 22:38:49 -0300747 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
748 conn->mtu = hcon->hdev->le_mtu;
749 else
750 conn->mtu = hcon->hdev->acl_mtu;
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 conn->src = &hcon->hdev->bdaddr;
753 conn->dst = &hcon->dst;
754
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200755 conn->feat_mask = 0;
756
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 spin_lock_init(&conn->lock);
758 rwlock_init(&conn->chan_list.lock);
759
Ville Tervob62f3282011-02-10 22:38:50 -0300760 if (hcon->type != LE_LINK)
761 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000762 (unsigned long) conn);
763
Marcel Holtmann2950f212009-02-12 14:02:50 +0100764 conn->disc_reason = 0x13;
765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return conn;
767}
768
Marcel Holtmann01394182006-07-03 10:02:46 +0200769static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
Marcel Holtmann01394182006-07-03 10:02:46 +0200771 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 struct sock *sk;
773
Marcel Holtmann01394182006-07-03 10:02:46 +0200774 if (!conn)
775 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
777 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
778
Wei Yongjun7585b972009-02-25 18:29:52 +0800779 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781 /* Kill channels */
782 while ((sk = conn->chan_list.head)) {
783 bh_lock_sock(sk);
784 l2cap_chan_del(sk, err);
785 bh_unlock_sock(sk);
786 l2cap_sock_kill(sk);
787 }
788
Dave Young8e8440f2008-03-03 12:18:55 -0800789 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
790 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800791
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 hcon->l2cap_data = NULL;
793 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794}
795
796static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
797{
798 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200799 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200801 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802}
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
806/* Find socket with psm and source bdaddr.
807 * Returns closest match.
808 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000809static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810{
811 struct sock *sk = NULL, *sk1 = NULL;
812 struct hlist_node *node;
813
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000814 read_lock(&l2cap_sk_list.lock);
815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 sk_for_each(sk, node, &l2cap_sk_list.head) {
817 if (state && sk->sk_state != state)
818 continue;
819
820 if (l2cap_pi(sk)->psm == psm) {
821 /* Exact match. */
822 if (!bacmp(&bt_sk(sk)->src, src))
823 break;
824
825 /* Closest match */
826 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
827 sk1 = sk;
828 }
829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000832
833 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834}
835
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200836int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837{
838 bdaddr_t *src = &bt_sk(sk)->src;
839 bdaddr_t *dst = &bt_sk(sk)->dst;
840 struct l2cap_conn *conn;
841 struct hci_conn *hcon;
842 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200843 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200844 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100846 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
847 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300849 hdev = hci_get_route(dst, src);
850 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 return -EHOSTUNREACH;
852
853 hci_dev_lock_bh(hdev);
854
Johan Hedberg8556edd32011-01-19 12:06:50 +0530855 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200856
Ville Tervoacd7d372011-02-10 22:38:49 -0300857 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
858 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100859 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300860 else
861 hcon = hci_connect(hdev, ACL_LINK, dst,
862 l2cap_pi(sk)->sec_level, auth_type);
863
Ville Tervo30e76272011-02-22 16:10:53 -0300864 if (IS_ERR(hcon)) {
865 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869 conn = l2cap_conn_add(hcon, 0);
870 if (!conn) {
871 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300872 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 goto done;
874 }
875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 /* Update source addr of the socket */
877 bacpy(src, conn->src);
878
879 l2cap_chan_add(conn, sk, NULL);
880
881 sk->sk_state = BT_CONNECT;
882 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
883
884 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300885 if (sk->sk_type != SOCK_SEQPACKET &&
886 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530888 if (l2cap_check_security(sk))
889 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200890 } else
891 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 }
893
Ville Tervo30e76272011-02-22 16:10:53 -0300894 err = 0;
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896done:
897 hci_dev_unlock_bh(hdev);
898 hci_dev_put(hdev);
899 return err;
900}
901
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200902int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300903{
904 DECLARE_WAITQUEUE(wait, current);
905 int err = 0;
906 int timeo = HZ/5;
907
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200908 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300909 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
910 set_current_state(TASK_INTERRUPTIBLE);
911
912 if (!timeo)
913 timeo = HZ/5;
914
915 if (signal_pending(current)) {
916 err = sock_intr_errno(timeo);
917 break;
918 }
919
920 release_sock(sk);
921 timeo = schedule_timeout(timeo);
922 lock_sock(sk);
923
924 err = sock_error(sk);
925 if (err)
926 break;
927 }
928 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200929 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300930 return err;
931}
932
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300933static void l2cap_monitor_timeout(unsigned long arg)
934{
935 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300936
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300937 BT_DBG("sk %p", sk);
938
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300939 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300940 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300941 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200942 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300943 return;
944 }
945
946 l2cap_pi(sk)->retry_count++;
947 __mod_monitor_timer();
948
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300949 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300950 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300951}
952
953static void l2cap_retrans_timeout(unsigned long arg)
954{
955 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300956
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300957 BT_DBG("sk %p", sk);
958
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300959 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300960 l2cap_pi(sk)->retry_count = 1;
961 __mod_monitor_timer();
962
963 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
964
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300965 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300967}
968
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300969static void l2cap_drop_acked_frames(struct sock *sk)
970{
971 struct sk_buff *skb;
972
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300973 while ((skb = skb_peek(TX_QUEUE(sk))) &&
974 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300975 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
976 break;
977
978 skb = skb_dequeue(TX_QUEUE(sk));
979 kfree_skb(skb);
980
981 l2cap_pi(sk)->unacked_frames--;
982 }
983
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984 if (!l2cap_pi(sk)->unacked_frames)
985 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300986}
987
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200988void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300989{
990 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200991 struct hci_conn *hcon = pi->conn->hcon;
992 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993
994 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
995
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200996 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
997 flags = ACL_START_NO_FLUSH;
998 else
999 flags = ACL_START;
1000
1001 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001002}
1003
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001004void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001005{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001006 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001007 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001008 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001009
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001010 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1011 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001012 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001013 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001014
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001015 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001016 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1017 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001018 }
1019
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001020 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001021
1022 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001023 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001024}
1025
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001026static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001027{
1028 struct l2cap_pinfo *pi = l2cap_pi(sk);
1029 struct sk_buff *skb, *tx_skb;
1030 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001031
1032 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001033 if (!skb)
1034 return;
1035
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001036 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001037 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001038 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001039
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001040 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1041 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001042
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001043 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001044
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001045 if (pi->remote_max_tx &&
1046 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001047 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001048 return;
1049 }
1050
1051 tx_skb = skb_clone(skb, GFP_ATOMIC);
1052 bt_cb(skb)->retries++;
1053 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001054
1055 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1056 control |= L2CAP_CTRL_FINAL;
1057 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1058 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001059
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1061 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001062
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1064
1065 if (pi->fcs == L2CAP_FCS_CRC16) {
1066 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1067 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1068 }
1069
1070 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001071}
1072
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001073int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001074{
1075 struct sk_buff *skb, *tx_skb;
1076 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001077 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001078 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001079
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001080 if (sk->sk_state != BT_CONNECTED)
1081 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001082
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001083 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001084
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001085 if (pi->remote_max_tx &&
1086 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001087 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001088 break;
1089 }
1090
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001091 tx_skb = skb_clone(skb, GFP_ATOMIC);
1092
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001093 bt_cb(skb)->retries++;
1094
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001095 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001096 control &= L2CAP_CTRL_SAR;
1097
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001098 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1099 control |= L2CAP_CTRL_FINAL;
1100 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1101 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001102 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1104 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1105
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001106
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001107 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001108 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1109 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1110 }
1111
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001112 l2cap_do_send(sk, tx_skb);
1113
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001115
1116 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1117 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1118
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301119 if (bt_cb(skb)->retries == 1)
1120 pi->unacked_frames++;
1121
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001123
1124 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1125 sk->sk_send_head = NULL;
1126 else
1127 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001128
1129 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001130 }
1131
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001132 return nsent;
1133}
1134
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001135static int l2cap_retransmit_frames(struct sock *sk)
1136{
1137 struct l2cap_pinfo *pi = l2cap_pi(sk);
1138 int ret;
1139
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001140 if (!skb_queue_empty(TX_QUEUE(sk)))
1141 sk->sk_send_head = TX_QUEUE(sk)->next;
1142
1143 pi->next_tx_seq = pi->expected_ack_seq;
1144 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001145 return ret;
1146}
1147
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001148static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001149{
1150 struct sock *sk = (struct sock *)pi;
1151 u16 control = 0;
1152
1153 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1154
1155 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1156 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001157 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001158 l2cap_send_sframe(pi, control);
1159 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001160 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001161
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001162 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001163 return;
1164
1165 control |= L2CAP_SUPER_RCV_READY;
1166 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001167}
1168
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001169static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001170{
1171 struct srej_list *tail;
1172 u16 control;
1173
1174 control = L2CAP_SUPER_SELECT_REJECT;
1175 control |= L2CAP_CTRL_FINAL;
1176
1177 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1178 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1179
1180 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001181}
1182
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001183static 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 -07001184{
1185 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001186 struct sk_buff **frag;
1187 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001189 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001190 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191
1192 sent += count;
1193 len -= count;
1194
1195 /* Continuation fragments (no L2CAP header) */
1196 frag = &skb_shinfo(skb)->frag_list;
1197 while (len) {
1198 count = min_t(unsigned int, conn->mtu, len);
1199
1200 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1201 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001202 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001203 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1204 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
1206 sent += count;
1207 len -= count;
1208
1209 frag = &(*frag)->next;
1210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
1212 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001213}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001215struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001216{
1217 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1218 struct sk_buff *skb;
1219 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1220 struct l2cap_hdr *lh;
1221
1222 BT_DBG("sk %p len %d", sk, (int)len);
1223
1224 count = min_t(unsigned int, (conn->mtu - hlen), len);
1225 skb = bt_skb_send_alloc(sk, count + hlen,
1226 msg->msg_flags & MSG_DONTWAIT, &err);
1227 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001228 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229
1230 /* Create L2CAP header */
1231 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1232 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1233 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1234 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1235
1236 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1237 if (unlikely(err < 0)) {
1238 kfree_skb(skb);
1239 return ERR_PTR(err);
1240 }
1241 return skb;
1242}
1243
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001244struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245{
1246 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1247 struct sk_buff *skb;
1248 int err, count, hlen = L2CAP_HDR_SIZE;
1249 struct l2cap_hdr *lh;
1250
1251 BT_DBG("sk %p len %d", sk, (int)len);
1252
1253 count = min_t(unsigned int, (conn->mtu - hlen), len);
1254 skb = bt_skb_send_alloc(sk, count + hlen,
1255 msg->msg_flags & MSG_DONTWAIT, &err);
1256 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001257 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001258
1259 /* Create L2CAP header */
1260 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1261 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1262 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1263
1264 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1265 if (unlikely(err < 0)) {
1266 kfree_skb(skb);
1267 return ERR_PTR(err);
1268 }
1269 return skb;
1270}
1271
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001272struct 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 -03001273{
1274 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1275 struct sk_buff *skb;
1276 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1277 struct l2cap_hdr *lh;
1278
1279 BT_DBG("sk %p len %d", sk, (int)len);
1280
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001281 if (!conn)
1282 return ERR_PTR(-ENOTCONN);
1283
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001284 if (sdulen)
1285 hlen += 2;
1286
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001287 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1288 hlen += 2;
1289
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001290 count = min_t(unsigned int, (conn->mtu - hlen), len);
1291 skb = bt_skb_send_alloc(sk, count + hlen,
1292 msg->msg_flags & MSG_DONTWAIT, &err);
1293 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001294 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295
1296 /* Create L2CAP header */
1297 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1298 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1299 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1300 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001301 if (sdulen)
1302 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001303
1304 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1305 if (unlikely(err < 0)) {
1306 kfree_skb(skb);
1307 return ERR_PTR(err);
1308 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001309
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001310 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1311 put_unaligned_le16(0, skb_put(skb, 2));
1312
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001313 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001314 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315}
1316
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001317int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001318{
1319 struct l2cap_pinfo *pi = l2cap_pi(sk);
1320 struct sk_buff *skb;
1321 struct sk_buff_head sar_queue;
1322 u16 control;
1323 size_t size = 0;
1324
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001325 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001326 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001327 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001328 if (IS_ERR(skb))
1329 return PTR_ERR(skb);
1330
1331 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001332 len -= pi->remote_mps;
1333 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001334
1335 while (len > 0) {
1336 size_t buflen;
1337
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001338 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001339 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001340 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001341 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001342 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001343 buflen = len;
1344 }
1345
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001346 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 if (IS_ERR(skb)) {
1348 skb_queue_purge(&sar_queue);
1349 return PTR_ERR(skb);
1350 }
1351
1352 __skb_queue_tail(&sar_queue, skb);
1353 len -= buflen;
1354 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001355 }
1356 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1357 if (sk->sk_send_head == NULL)
1358 sk->sk_send_head = sar_queue.next;
1359
1360 return size;
1361}
1362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363static void l2cap_chan_ready(struct sock *sk)
1364{
1365 struct sock *parent = bt_sk(sk)->parent;
1366
1367 BT_DBG("sk %p, parent %p", sk, parent);
1368
1369 l2cap_pi(sk)->conf_state = 0;
1370 l2cap_sock_clear_timer(sk);
1371
1372 if (!parent) {
1373 /* Outgoing channel.
1374 * Wake up socket sleeping on connect.
1375 */
1376 sk->sk_state = BT_CONNECTED;
1377 sk->sk_state_change(sk);
1378 } else {
1379 /* Incoming channel.
1380 * Wake up socket sleeping on accept.
1381 */
1382 parent->sk_data_ready(parent, 0);
1383 }
1384}
1385
1386/* Copy frame to all raw sockets on that connection */
1387static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1388{
1389 struct l2cap_chan_list *l = &conn->chan_list;
1390 struct sk_buff *nskb;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001391 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
1393 BT_DBG("conn %p", conn);
1394
1395 read_lock(&l->lock);
1396 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1397 if (sk->sk_type != SOCK_RAW)
1398 continue;
1399
1400 /* Don't send frame to the socket it came from */
1401 if (skb->sk == sk)
1402 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001403 nskb = skb_clone(skb, GFP_ATOMIC);
1404 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 continue;
1406
1407 if (sock_queue_rcv_skb(sk, nskb))
1408 kfree_skb(nskb);
1409 }
1410 read_unlock(&l->lock);
1411}
1412
1413/* ---- L2CAP signalling commands ---- */
1414static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1415 u8 code, u8 ident, u16 dlen, void *data)
1416{
1417 struct sk_buff *skb, **frag;
1418 struct l2cap_cmd_hdr *cmd;
1419 struct l2cap_hdr *lh;
1420 int len, count;
1421
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001422 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1423 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
1425 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1426 count = min_t(unsigned int, conn->mtu, len);
1427
1428 skb = bt_skb_alloc(count, GFP_ATOMIC);
1429 if (!skb)
1430 return NULL;
1431
1432 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001433 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001434
1435 if (conn->hcon->type == LE_LINK)
1436 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1437 else
1438 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1441 cmd->code = code;
1442 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001443 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 if (dlen) {
1446 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1447 memcpy(skb_put(skb, count), data, count);
1448 data += count;
1449 }
1450
1451 len -= skb->len;
1452
1453 /* Continuation fragments (no L2CAP header) */
1454 frag = &skb_shinfo(skb)->frag_list;
1455 while (len) {
1456 count = min_t(unsigned int, conn->mtu, len);
1457
1458 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1459 if (!*frag)
1460 goto fail;
1461
1462 memcpy(skb_put(*frag, count), data, count);
1463
1464 len -= count;
1465 data += count;
1466
1467 frag = &(*frag)->next;
1468 }
1469
1470 return skb;
1471
1472fail:
1473 kfree_skb(skb);
1474 return NULL;
1475}
1476
1477static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1478{
1479 struct l2cap_conf_opt *opt = *ptr;
1480 int len;
1481
1482 len = L2CAP_CONF_OPT_SIZE + opt->len;
1483 *ptr += len;
1484
1485 *type = opt->type;
1486 *olen = opt->len;
1487
1488 switch (opt->len) {
1489 case 1:
1490 *val = *((u8 *) opt->val);
1491 break;
1492
1493 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001494 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 break;
1496
1497 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001498 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 break;
1500
1501 default:
1502 *val = (unsigned long) opt->val;
1503 break;
1504 }
1505
1506 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1507 return len;
1508}
1509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1511{
1512 struct l2cap_conf_opt *opt = *ptr;
1513
1514 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1515
1516 opt->type = type;
1517 opt->len = len;
1518
1519 switch (len) {
1520 case 1:
1521 *((u8 *) opt->val) = val;
1522 break;
1523
1524 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001525 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 break;
1527
1528 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001529 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 break;
1531
1532 default:
1533 memcpy(opt->val, (void *) val, len);
1534 break;
1535 }
1536
1537 *ptr += L2CAP_CONF_OPT_SIZE + len;
1538}
1539
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001540static void l2cap_ack_timeout(unsigned long arg)
1541{
1542 struct sock *sk = (void *) arg;
1543
1544 bh_lock_sock(sk);
1545 l2cap_send_ack(l2cap_pi(sk));
1546 bh_unlock_sock(sk);
1547}
1548
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001549static inline void l2cap_ertm_init(struct sock *sk)
1550{
1551 l2cap_pi(sk)->expected_ack_seq = 0;
1552 l2cap_pi(sk)->unacked_frames = 0;
1553 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001554 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001555 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001556
1557 setup_timer(&l2cap_pi(sk)->retrans_timer,
1558 l2cap_retrans_timeout, (unsigned long) sk);
1559 setup_timer(&l2cap_pi(sk)->monitor_timer,
1560 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001561 setup_timer(&l2cap_pi(sk)->ack_timer,
1562 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001563
1564 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001565 __skb_queue_head_init(BUSY_QUEUE(sk));
1566
1567 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001568
1569 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001570}
1571
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001572static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1573{
1574 switch (mode) {
1575 case L2CAP_MODE_STREAMING:
1576 case L2CAP_MODE_ERTM:
1577 if (l2cap_mode_supported(mode, remote_feat_mask))
1578 return mode;
1579 /* fall through */
1580 default:
1581 return L2CAP_MODE_BASIC;
1582 }
1583}
1584
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001585int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586{
1587 struct l2cap_pinfo *pi = l2cap_pi(sk);
1588 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001589 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 void *ptr = req->data;
1591
1592 BT_DBG("sk %p", sk);
1593
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001594 if (pi->num_conf_req || pi->num_conf_rsp)
1595 goto done;
1596
1597 switch (pi->mode) {
1598 case L2CAP_MODE_STREAMING:
1599 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001600 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001601 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001602
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001603 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001604 default:
1605 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1606 break;
1607 }
1608
1609done:
Gustavo F. Padovan79906812011-01-24 16:01:43 -02001610 if (pi->imtu != L2CAP_DEFAULT_MTU)
1611 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1612
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001613 switch (pi->mode) {
1614 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001615 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1616 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1617 break;
1618
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001619 rfc.mode = L2CAP_MODE_BASIC;
1620 rfc.txwin_size = 0;
1621 rfc.max_transmit = 0;
1622 rfc.retrans_timeout = 0;
1623 rfc.monitor_timeout = 0;
1624 rfc.max_pdu_size = 0;
1625
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001626 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1627 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001628 break;
1629
1630 case L2CAP_MODE_ERTM:
1631 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001632 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001633 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001634 rfc.retrans_timeout = 0;
1635 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001636 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001637 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001638 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001639
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001640 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1641 (unsigned long) &rfc);
1642
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001643 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1644 break;
1645
1646 if (pi->fcs == L2CAP_FCS_NONE ||
1647 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1648 pi->fcs = L2CAP_FCS_NONE;
1649 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1650 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001651 break;
1652
1653 case L2CAP_MODE_STREAMING:
1654 rfc.mode = L2CAP_MODE_STREAMING;
1655 rfc.txwin_size = 0;
1656 rfc.max_transmit = 0;
1657 rfc.retrans_timeout = 0;
1658 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001659 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001660 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001661 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001662
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001663 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1664 (unsigned long) &rfc);
1665
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001666 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1667 break;
1668
1669 if (pi->fcs == L2CAP_FCS_NONE ||
1670 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1671 pi->fcs = L2CAP_FCS_NONE;
1672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1673 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001674 break;
1675 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001677 req->dcid = cpu_to_le16(pi->dcid);
1678 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
1680 return ptr - data;
1681}
1682
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001683static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
1685 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001686 struct l2cap_conf_rsp *rsp = data;
1687 void *ptr = rsp->data;
1688 void *req = pi->conf_req;
1689 int len = pi->conf_len;
1690 int type, hint, olen;
1691 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001692 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001693 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001694 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001696 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001697
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001698 while (len >= L2CAP_CONF_OPT_SIZE) {
1699 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001701 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001702 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001703
1704 switch (type) {
1705 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001706 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001707 break;
1708
1709 case L2CAP_CONF_FLUSH_TO:
1710 pi->flush_to = val;
1711 break;
1712
1713 case L2CAP_CONF_QOS:
1714 break;
1715
Marcel Holtmann6464f352007-10-20 13:39:51 +02001716 case L2CAP_CONF_RFC:
1717 if (olen == sizeof(rfc))
1718 memcpy(&rfc, (void *) val, olen);
1719 break;
1720
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001721 case L2CAP_CONF_FCS:
1722 if (val == L2CAP_FCS_NONE)
1723 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1724
1725 break;
1726
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001727 default:
1728 if (hint)
1729 break;
1730
1731 result = L2CAP_CONF_UNKNOWN;
1732 *((u8 *) ptr++) = type;
1733 break;
1734 }
1735 }
1736
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001737 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001738 goto done;
1739
1740 switch (pi->mode) {
1741 case L2CAP_MODE_STREAMING:
1742 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001743 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1744 pi->mode = l2cap_select_mode(rfc.mode,
1745 pi->conn->feat_mask);
1746 break;
1747 }
1748
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001749 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001750 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001751
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001752 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001753 }
1754
1755done:
1756 if (pi->mode != rfc.mode) {
1757 result = L2CAP_CONF_UNACCEPT;
1758 rfc.mode = pi->mode;
1759
1760 if (pi->num_conf_rsp == 1)
1761 return -ECONNREFUSED;
1762
1763 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1764 sizeof(rfc), (unsigned long) &rfc);
1765 }
1766
1767
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001768 if (result == L2CAP_CONF_SUCCESS) {
1769 /* Configure output options and let the other side know
1770 * which ones we don't like. */
1771
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001772 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1773 result = L2CAP_CONF_UNACCEPT;
1774 else {
1775 pi->omtu = mtu;
1776 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1777 }
1778 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001779
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 switch (rfc.mode) {
1781 case L2CAP_MODE_BASIC:
1782 pi->fcs = L2CAP_FCS_NONE;
1783 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1784 break;
1785
1786 case L2CAP_MODE_ERTM:
1787 pi->remote_tx_win = rfc.txwin_size;
1788 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001789
1790 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1791 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001792
1793 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001794
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001795 rfc.retrans_timeout =
1796 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1797 rfc.monitor_timeout =
1798 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001799
1800 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001801
1802 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1803 sizeof(rfc), (unsigned long) &rfc);
1804
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001805 break;
1806
1807 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001808 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1809 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001810
1811 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001812
1813 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001814
1815 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1816 sizeof(rfc), (unsigned long) &rfc);
1817
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001818 break;
1819
1820 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001821 result = L2CAP_CONF_UNACCEPT;
1822
1823 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001824 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001825 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001826
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001827 if (result == L2CAP_CONF_SUCCESS)
1828 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1829 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001830 rsp->scid = cpu_to_le16(pi->dcid);
1831 rsp->result = cpu_to_le16(result);
1832 rsp->flags = cpu_to_le16(0x0000);
1833
1834 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835}
1836
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001837static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1838{
1839 struct l2cap_pinfo *pi = l2cap_pi(sk);
1840 struct l2cap_conf_req *req = data;
1841 void *ptr = req->data;
1842 int type, olen;
1843 unsigned long val;
1844 struct l2cap_conf_rfc rfc;
1845
1846 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1847
1848 while (len >= L2CAP_CONF_OPT_SIZE) {
1849 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1850
1851 switch (type) {
1852 case L2CAP_CONF_MTU:
1853 if (val < L2CAP_DEFAULT_MIN_MTU) {
1854 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001855 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001856 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001857 pi->imtu = val;
1858 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001859 break;
1860
1861 case L2CAP_CONF_FLUSH_TO:
1862 pi->flush_to = val;
1863 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1864 2, pi->flush_to);
1865 break;
1866
1867 case L2CAP_CONF_RFC:
1868 if (olen == sizeof(rfc))
1869 memcpy(&rfc, (void *)val, olen);
1870
1871 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1872 rfc.mode != pi->mode)
1873 return -ECONNREFUSED;
1874
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001875 pi->fcs = 0;
1876
1877 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1878 sizeof(rfc), (unsigned long) &rfc);
1879 break;
1880 }
1881 }
1882
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001883 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1884 return -ECONNREFUSED;
1885
1886 pi->mode = rfc.mode;
1887
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001888 if (*result == L2CAP_CONF_SUCCESS) {
1889 switch (rfc.mode) {
1890 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001891 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1892 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001893 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001894 break;
1895 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001896 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001897 }
1898 }
1899
1900 req->dcid = cpu_to_le16(pi->dcid);
1901 req->flags = cpu_to_le16(0x0000);
1902
1903 return ptr - data;
1904}
1905
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001906static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907{
1908 struct l2cap_conf_rsp *rsp = data;
1909 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001911 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001913 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001914 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001915 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 return ptr - data;
1918}
1919
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001920static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1921{
1922 struct l2cap_pinfo *pi = l2cap_pi(sk);
1923 int type, olen;
1924 unsigned long val;
1925 struct l2cap_conf_rfc rfc;
1926
1927 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1928
1929 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1930 return;
1931
1932 while (len >= L2CAP_CONF_OPT_SIZE) {
1933 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1934
1935 switch (type) {
1936 case L2CAP_CONF_RFC:
1937 if (olen == sizeof(rfc))
1938 memcpy(&rfc, (void *)val, olen);
1939 goto done;
1940 }
1941 }
1942
1943done:
1944 switch (rfc.mode) {
1945 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001946 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1947 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001948 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1949 break;
1950 case L2CAP_MODE_STREAMING:
1951 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1952 }
1953}
1954
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001955static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1956{
1957 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1958
1959 if (rej->reason != 0x0000)
1960 return 0;
1961
1962 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1963 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001964 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001965
1966 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001967 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001968
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001969 l2cap_conn_start(conn);
1970 }
1971
1972 return 0;
1973}
1974
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1976{
1977 struct l2cap_chan_list *list = &conn->chan_list;
1978 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1979 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001980 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001981 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
1983 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001984 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
1987
1988 /* Check if we have socket listening on psm */
1989 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
1990 if (!parent) {
1991 result = L2CAP_CR_BAD_PSM;
1992 goto sendresp;
1993 }
1994
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001995 bh_lock_sock(parent);
1996
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001997 /* Check if the ACL is secure enough (if not SDP) */
1998 if (psm != cpu_to_le16(0x0001) &&
1999 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002000 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002001 result = L2CAP_CR_SEC_BLOCK;
2002 goto response;
2003 }
2004
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 result = L2CAP_CR_NO_MEM;
2006
2007 /* Check for backlog size */
2008 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002009 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 goto response;
2011 }
2012
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002013 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 if (!sk)
2015 goto response;
2016
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002017 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
2019 /* Check if we already have channel with that dcid */
2020 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002021 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 sock_set_flag(sk, SOCK_ZAPPED);
2023 l2cap_sock_kill(sk);
2024 goto response;
2025 }
2026
2027 hci_conn_hold(conn->hcon);
2028
2029 l2cap_sock_init(sk, parent);
2030 bacpy(&bt_sk(sk)->src, conn->src);
2031 bacpy(&bt_sk(sk)->dst, conn->dst);
2032 l2cap_pi(sk)->psm = psm;
2033 l2cap_pi(sk)->dcid = scid;
2034
2035 __l2cap_chan_add(conn, sk, parent);
2036 dcid = l2cap_pi(sk)->scid;
2037
2038 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2039
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 l2cap_pi(sk)->ident = cmd->ident;
2041
Marcel Holtmann984947d2009-02-06 23:35:19 +01002042 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002043 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002044 if (bt_sk(sk)->defer_setup) {
2045 sk->sk_state = BT_CONNECT2;
2046 result = L2CAP_CR_PEND;
2047 status = L2CAP_CS_AUTHOR_PEND;
2048 parent->sk_data_ready(parent, 0);
2049 } else {
2050 sk->sk_state = BT_CONFIG;
2051 result = L2CAP_CR_SUCCESS;
2052 status = L2CAP_CS_NO_INFO;
2053 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002054 } else {
2055 sk->sk_state = BT_CONNECT2;
2056 result = L2CAP_CR_PEND;
2057 status = L2CAP_CS_AUTHEN_PEND;
2058 }
2059 } else {
2060 sk->sk_state = BT_CONNECT2;
2061 result = L2CAP_CR_PEND;
2062 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 }
2064
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002065 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
2067response:
2068 bh_unlock_sock(parent);
2069
2070sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002071 rsp.scid = cpu_to_le16(scid);
2072 rsp.dcid = cpu_to_le16(dcid);
2073 rsp.result = cpu_to_le16(result);
2074 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002076
2077 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2078 struct l2cap_info_req info;
2079 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2080
2081 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2082 conn->info_ident = l2cap_get_ident(conn);
2083
2084 mod_timer(&conn->info_timer, jiffies +
2085 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2086
2087 l2cap_send_cmd(conn, conn->info_ident,
2088 L2CAP_INFO_REQ, sizeof(info), &info);
2089 }
2090
Nathan Holsteind793fe82010-10-15 11:54:02 -04002091 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002092 result == L2CAP_CR_SUCCESS) {
2093 u8 buf[128];
2094 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2095 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2096 l2cap_build_conf_req(sk, buf), buf);
2097 l2cap_pi(sk)->num_conf_req++;
2098 }
2099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 return 0;
2101}
2102
2103static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2104{
2105 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2106 u16 scid, dcid, result, status;
2107 struct sock *sk;
2108 u8 req[128];
2109
2110 scid = __le16_to_cpu(rsp->scid);
2111 dcid = __le16_to_cpu(rsp->dcid);
2112 result = __le16_to_cpu(rsp->result);
2113 status = __le16_to_cpu(rsp->status);
2114
2115 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2116
2117 if (scid) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002118 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2119 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002120 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 } else {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002122 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2123 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002124 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
2127 switch (result) {
2128 case L2CAP_CR_SUCCESS:
2129 sk->sk_state = BT_CONFIG;
2130 l2cap_pi(sk)->ident = 0;
2131 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002132 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2133
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002134 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2135 break;
2136
2137 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2140 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002141 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 break;
2143
2144 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002145 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 break;
2147
2148 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002149 /* don't delete l2cap channel if sk is owned by user */
2150 if (sock_owned_by_user(sk)) {
2151 sk->sk_state = BT_DISCONN;
2152 l2cap_sock_clear_timer(sk);
2153 l2cap_sock_set_timer(sk, HZ / 5);
2154 break;
2155 }
2156
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 l2cap_chan_del(sk, ECONNREFUSED);
2158 break;
2159 }
2160
2161 bh_unlock_sock(sk);
2162 return 0;
2163}
2164
Mat Martineau8c462b62010-08-24 15:35:42 -07002165static inline void set_default_fcs(struct l2cap_pinfo *pi)
2166{
2167 /* FCS is enabled only in ERTM or streaming mode, if one or both
2168 * sides request it.
2169 */
2170 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2171 pi->fcs = L2CAP_FCS_NONE;
2172 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2173 pi->fcs = L2CAP_FCS_CRC16;
2174}
2175
Al Viro88219a02007-07-29 00:17:25 -07002176static 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 -07002177{
2178 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2179 u16 dcid, flags;
2180 u8 rsp[64];
2181 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002182 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
2184 dcid = __le16_to_cpu(req->dcid);
2185 flags = __le16_to_cpu(req->flags);
2186
2187 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2188
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002189 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2190 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 return -ENOENT;
2192
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002193 if (sk->sk_state != BT_CONFIG) {
2194 struct l2cap_cmd_rej rej;
2195
2196 rej.reason = cpu_to_le16(0x0002);
2197 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2198 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002199 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002200 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002201
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002202 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002203 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002204 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2205 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2206 l2cap_build_conf_rsp(sk, rsp,
2207 L2CAP_CONF_REJECT, flags), rsp);
2208 goto unlock;
2209 }
2210
2211 /* Store config. */
2212 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2213 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
2215 if (flags & 0x0001) {
2216 /* Incomplete config. Send empty response. */
2217 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002218 l2cap_build_conf_rsp(sk, rsp,
2219 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 goto unlock;
2221 }
2222
2223 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002224 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002225 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002226 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002230 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002231 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002232
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002233 /* Reset config buffer. */
2234 l2cap_pi(sk)->conf_len = 0;
2235
Marcel Holtmann876d9482007-10-20 13:35:42 +02002236 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2237 goto unlock;
2238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002240 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002241
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002243
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002244 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002245 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002246 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002247 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2248 l2cap_ertm_init(sk);
2249
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002251 goto unlock;
2252 }
2253
2254 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002255 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002256 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002258 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002259 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 }
2261
2262unlock:
2263 bh_unlock_sock(sk);
2264 return 0;
2265}
2266
2267static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2268{
2269 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2270 u16 scid, flags, result;
2271 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002272 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
2274 scid = __le16_to_cpu(rsp->scid);
2275 flags = __le16_to_cpu(rsp->flags);
2276 result = __le16_to_cpu(rsp->result);
2277
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002278 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2279 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002281 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2282 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 return 0;
2284
2285 switch (result) {
2286 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002287 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 break;
2289
2290 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002291 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002292 char req[64];
2293
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002294 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002295 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002296 goto done;
2297 }
2298
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002299 /* throw out any old stored conf requests */
2300 result = L2CAP_CONF_SUCCESS;
2301 len = l2cap_parse_conf_rsp(sk, rsp->data,
2302 len, req, &result);
2303 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002304 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002305 goto done;
2306 }
2307
2308 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2309 L2CAP_CONF_REQ, len, req);
2310 l2cap_pi(sk)->num_conf_req++;
2311 if (result != L2CAP_CONF_SUCCESS)
2312 goto done;
2313 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 }
2315
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002316 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002317 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002319 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 goto done;
2321 }
2322
2323 if (flags & 0x01)
2324 goto done;
2325
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2327
2328 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002329 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002330
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002332 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002333 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002334 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002335 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2336 l2cap_ertm_init(sk);
2337
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 l2cap_chan_ready(sk);
2339 }
2340
2341done:
2342 bh_unlock_sock(sk);
2343 return 0;
2344}
2345
2346static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2347{
2348 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2349 struct l2cap_disconn_rsp rsp;
2350 u16 dcid, scid;
2351 struct sock *sk;
2352
2353 scid = __le16_to_cpu(req->scid);
2354 dcid = __le16_to_cpu(req->dcid);
2355
2356 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2357
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002358 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2359 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 return 0;
2361
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002362 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2363 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2365
2366 sk->sk_shutdown = SHUTDOWN_MASK;
2367
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002368 /* don't delete l2cap channel if sk is owned by user */
2369 if (sock_owned_by_user(sk)) {
2370 sk->sk_state = BT_DISCONN;
2371 l2cap_sock_clear_timer(sk);
2372 l2cap_sock_set_timer(sk, HZ / 5);
2373 bh_unlock_sock(sk);
2374 return 0;
2375 }
2376
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 l2cap_chan_del(sk, ECONNRESET);
2378 bh_unlock_sock(sk);
2379
2380 l2cap_sock_kill(sk);
2381 return 0;
2382}
2383
2384static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2385{
2386 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2387 u16 dcid, scid;
2388 struct sock *sk;
2389
2390 scid = __le16_to_cpu(rsp->scid);
2391 dcid = __le16_to_cpu(rsp->dcid);
2392
2393 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2394
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002395 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2396 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 return 0;
2398
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002399 /* don't delete l2cap channel if sk is owned by user */
2400 if (sock_owned_by_user(sk)) {
2401 sk->sk_state = BT_DISCONN;
2402 l2cap_sock_clear_timer(sk);
2403 l2cap_sock_set_timer(sk, HZ / 5);
2404 bh_unlock_sock(sk);
2405 return 0;
2406 }
2407
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 l2cap_chan_del(sk, 0);
2409 bh_unlock_sock(sk);
2410
2411 l2cap_sock_kill(sk);
2412 return 0;
2413}
2414
2415static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2416{
2417 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 u16 type;
2419
2420 type = __le16_to_cpu(req->type);
2421
2422 BT_DBG("type 0x%4.4x", type);
2423
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002424 if (type == L2CAP_IT_FEAT_MASK) {
2425 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002426 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002427 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2428 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2429 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002430 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002431 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2432 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002433 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002434 l2cap_send_cmd(conn, cmd->ident,
2435 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002436 } else if (type == L2CAP_IT_FIXED_CHAN) {
2437 u8 buf[12];
2438 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2439 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2440 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2441 memcpy(buf + 4, l2cap_fixed_chan, 8);
2442 l2cap_send_cmd(conn, cmd->ident,
2443 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002444 } else {
2445 struct l2cap_info_rsp rsp;
2446 rsp.type = cpu_to_le16(type);
2447 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2448 l2cap_send_cmd(conn, cmd->ident,
2449 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
2452 return 0;
2453}
2454
2455static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2456{
2457 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2458 u16 type, result;
2459
2460 type = __le16_to_cpu(rsp->type);
2461 result = __le16_to_cpu(rsp->result);
2462
2463 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2464
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002465 del_timer(&conn->info_timer);
2466
Ville Tervoadb08ed2010-08-04 09:43:33 +03002467 if (result != L2CAP_IR_SUCCESS) {
2468 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2469 conn->info_ident = 0;
2470
2471 l2cap_conn_start(conn);
2472
2473 return 0;
2474 }
2475
Marcel Holtmann984947d2009-02-06 23:35:19 +01002476 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002477 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002478
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002479 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002480 struct l2cap_info_req req;
2481 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2482
2483 conn->info_ident = l2cap_get_ident(conn);
2484
2485 l2cap_send_cmd(conn, conn->info_ident,
2486 L2CAP_INFO_REQ, sizeof(req), &req);
2487 } else {
2488 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2489 conn->info_ident = 0;
2490
2491 l2cap_conn_start(conn);
2492 }
2493 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002494 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002495 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002496
2497 l2cap_conn_start(conn);
2498 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002499
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 return 0;
2501}
2502
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002503static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002504 u16 to_multiplier)
2505{
2506 u16 max_latency;
2507
2508 if (min > max || min < 6 || max > 3200)
2509 return -EINVAL;
2510
2511 if (to_multiplier < 10 || to_multiplier > 3200)
2512 return -EINVAL;
2513
2514 if (max >= to_multiplier * 8)
2515 return -EINVAL;
2516
2517 max_latency = (to_multiplier * 8 / max) - 1;
2518 if (latency > 499 || latency > max_latency)
2519 return -EINVAL;
2520
2521 return 0;
2522}
2523
2524static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2525 struct l2cap_cmd_hdr *cmd, u8 *data)
2526{
2527 struct hci_conn *hcon = conn->hcon;
2528 struct l2cap_conn_param_update_req *req;
2529 struct l2cap_conn_param_update_rsp rsp;
2530 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002531 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002532
2533 if (!(hcon->link_mode & HCI_LM_MASTER))
2534 return -EINVAL;
2535
2536 cmd_len = __le16_to_cpu(cmd->len);
2537 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2538 return -EPROTO;
2539
2540 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002541 min = __le16_to_cpu(req->min);
2542 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002543 latency = __le16_to_cpu(req->latency);
2544 to_multiplier = __le16_to_cpu(req->to_multiplier);
2545
2546 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2547 min, max, latency, to_multiplier);
2548
2549 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002550
2551 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2552 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002553 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2554 else
2555 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2556
2557 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2558 sizeof(rsp), &rsp);
2559
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002560 if (!err)
2561 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2562
Claudio Takahaside731152011-02-11 19:28:55 -02002563 return 0;
2564}
2565
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002566static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2567 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2568{
2569 int err = 0;
2570
2571 switch (cmd->code) {
2572 case L2CAP_COMMAND_REJ:
2573 l2cap_command_rej(conn, cmd, data);
2574 break;
2575
2576 case L2CAP_CONN_REQ:
2577 err = l2cap_connect_req(conn, cmd, data);
2578 break;
2579
2580 case L2CAP_CONN_RSP:
2581 err = l2cap_connect_rsp(conn, cmd, data);
2582 break;
2583
2584 case L2CAP_CONF_REQ:
2585 err = l2cap_config_req(conn, cmd, cmd_len, data);
2586 break;
2587
2588 case L2CAP_CONF_RSP:
2589 err = l2cap_config_rsp(conn, cmd, data);
2590 break;
2591
2592 case L2CAP_DISCONN_REQ:
2593 err = l2cap_disconnect_req(conn, cmd, data);
2594 break;
2595
2596 case L2CAP_DISCONN_RSP:
2597 err = l2cap_disconnect_rsp(conn, cmd, data);
2598 break;
2599
2600 case L2CAP_ECHO_REQ:
2601 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2602 break;
2603
2604 case L2CAP_ECHO_RSP:
2605 break;
2606
2607 case L2CAP_INFO_REQ:
2608 err = l2cap_information_req(conn, cmd, data);
2609 break;
2610
2611 case L2CAP_INFO_RSP:
2612 err = l2cap_information_rsp(conn, cmd, data);
2613 break;
2614
2615 default:
2616 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2617 err = -EINVAL;
2618 break;
2619 }
2620
2621 return err;
2622}
2623
2624static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2625 struct l2cap_cmd_hdr *cmd, u8 *data)
2626{
2627 switch (cmd->code) {
2628 case L2CAP_COMMAND_REJ:
2629 return 0;
2630
2631 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002632 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002633
2634 case L2CAP_CONN_PARAM_UPDATE_RSP:
2635 return 0;
2636
2637 default:
2638 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2639 return -EINVAL;
2640 }
2641}
2642
2643static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2644 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645{
2646 u8 *data = skb->data;
2647 int len = skb->len;
2648 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002649 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
2651 l2cap_raw_recv(conn, skb);
2652
2653 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002654 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2656 data += L2CAP_CMD_HDR_SIZE;
2657 len -= L2CAP_CMD_HDR_SIZE;
2658
Al Viro88219a02007-07-29 00:17:25 -07002659 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660
Al Viro88219a02007-07-29 00:17:25 -07002661 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 -07002662
Al Viro88219a02007-07-29 00:17:25 -07002663 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 BT_DBG("corrupted command");
2665 break;
2666 }
2667
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002668 if (conn->hcon->type == LE_LINK)
2669 err = l2cap_le_sig_cmd(conn, &cmd, data);
2670 else
2671 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
2673 if (err) {
2674 struct l2cap_cmd_rej rej;
2675 BT_DBG("error %d", err);
2676
2677 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002678 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2680 }
2681
Al Viro88219a02007-07-29 00:17:25 -07002682 data += cmd_len;
2683 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 }
2685
2686 kfree_skb(skb);
2687}
2688
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002689static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2690{
2691 u16 our_fcs, rcv_fcs;
2692 int hdr_size = L2CAP_HDR_SIZE + 2;
2693
2694 if (pi->fcs == L2CAP_FCS_CRC16) {
2695 skb_trim(skb, skb->len - 2);
2696 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2697 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2698
2699 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002700 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002701 }
2702 return 0;
2703}
2704
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002705static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2706{
2707 struct l2cap_pinfo *pi = l2cap_pi(sk);
2708 u16 control = 0;
2709
2710 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002711
2712 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2713
2714 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002715 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002716 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002717 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002718 }
2719
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002720 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2721 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002722
2723 l2cap_ertm_send(sk);
2724
2725 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2726 pi->frames_sent == 0) {
2727 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002728 l2cap_send_sframe(pi, control);
2729 }
2730}
2731
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002732static 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 -03002733{
2734 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002735 struct l2cap_pinfo *pi = l2cap_pi(sk);
2736 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002737
2738 bt_cb(skb)->tx_seq = tx_seq;
2739 bt_cb(skb)->sar = sar;
2740
2741 next_skb = skb_peek(SREJ_QUEUE(sk));
2742 if (!next_skb) {
2743 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002744 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002745 }
2746
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002747 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2748 if (tx_seq_offset < 0)
2749 tx_seq_offset += 64;
2750
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002751 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002752 if (bt_cb(next_skb)->tx_seq == tx_seq)
2753 return -EINVAL;
2754
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002755 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2756 pi->buffer_seq) % 64;
2757 if (next_tx_seq_offset < 0)
2758 next_tx_seq_offset += 64;
2759
2760 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002761 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002762 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002763 }
2764
2765 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2766 break;
2767
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002768 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002769
2770 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002771
2772 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002773}
2774
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002775static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2776{
2777 struct l2cap_pinfo *pi = l2cap_pi(sk);
2778 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002779 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002780
2781 switch (control & L2CAP_CTRL_SAR) {
2782 case L2CAP_SDU_UNSEGMENTED:
2783 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2784 goto drop;
2785
2786 err = sock_queue_rcv_skb(sk, skb);
2787 if (!err)
2788 return err;
2789
2790 break;
2791
2792 case L2CAP_SDU_START:
2793 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2794 goto drop;
2795
2796 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002797
2798 if (pi->sdu_len > pi->imtu)
2799 goto disconnect;
2800
2801 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002802 if (!pi->sdu)
2803 return -ENOMEM;
2804
2805 /* pull sdu_len bytes only after alloc, because of Local Busy
2806 * condition we have to be sure that this will be executed
2807 * only once, i.e., when alloc does not fail */
2808 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002809
2810 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2811
2812 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2813 pi->partial_sdu_len = skb->len;
2814 break;
2815
2816 case L2CAP_SDU_CONTINUE:
2817 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2818 goto disconnect;
2819
2820 if (!pi->sdu)
2821 goto disconnect;
2822
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002823 pi->partial_sdu_len += skb->len;
2824 if (pi->partial_sdu_len > pi->sdu_len)
2825 goto drop;
2826
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002827 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2828
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002829 break;
2830
2831 case L2CAP_SDU_END:
2832 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2833 goto disconnect;
2834
2835 if (!pi->sdu)
2836 goto disconnect;
2837
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002838 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002839 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002840
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002841 if (pi->partial_sdu_len > pi->imtu)
2842 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002843
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002844 if (pi->partial_sdu_len != pi->sdu_len)
2845 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002846
2847 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002848 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002849
2850 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002851 if (!_skb) {
2852 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2853 return -ENOMEM;
2854 }
2855
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002856 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002857 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002858 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002859 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2860 return err;
2861 }
2862
2863 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2864 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002865
2866 kfree_skb(pi->sdu);
2867 break;
2868 }
2869
2870 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002871 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002872
2873drop:
2874 kfree_skb(pi->sdu);
2875 pi->sdu = NULL;
2876
2877disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002878 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002879 kfree_skb(skb);
2880 return 0;
2881}
2882
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002883static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002884{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002885 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002886 struct sk_buff *skb;
2887 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002888 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002889
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002890 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2891 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2892 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2893 if (err < 0) {
2894 skb_queue_head(BUSY_QUEUE(sk), skb);
2895 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002896 }
2897
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002898 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002899 }
2900
2901 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2902 goto done;
2903
2904 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2905 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2906 l2cap_send_sframe(pi, control);
2907 l2cap_pi(sk)->retry_count = 1;
2908
2909 del_timer(&pi->retrans_timer);
2910 __mod_monitor_timer();
2911
2912 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2913
2914done:
2915 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2916 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2917
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002918 BT_DBG("sk %p, Exit local busy", sk);
2919
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002920 return 0;
2921}
2922
2923static void l2cap_busy_work(struct work_struct *work)
2924{
2925 DECLARE_WAITQUEUE(wait, current);
2926 struct l2cap_pinfo *pi =
2927 container_of(work, struct l2cap_pinfo, busy_work);
2928 struct sock *sk = (struct sock *)pi;
2929 int n_tries = 0, timeo = HZ/5, err;
2930 struct sk_buff *skb;
2931
2932 lock_sock(sk);
2933
2934 add_wait_queue(sk_sleep(sk), &wait);
2935 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2936 set_current_state(TASK_INTERRUPTIBLE);
2937
2938 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2939 err = -EBUSY;
2940 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2941 break;
2942 }
2943
2944 if (!timeo)
2945 timeo = HZ/5;
2946
2947 if (signal_pending(current)) {
2948 err = sock_intr_errno(timeo);
2949 break;
2950 }
2951
2952 release_sock(sk);
2953 timeo = schedule_timeout(timeo);
2954 lock_sock(sk);
2955
2956 err = sock_error(sk);
2957 if (err)
2958 break;
2959
2960 if (l2cap_try_push_rx_skb(sk) == 0)
2961 break;
2962 }
2963
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002964 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002965 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002966
2967 release_sock(sk);
2968}
2969
2970static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2971{
2972 struct l2cap_pinfo *pi = l2cap_pi(sk);
2973 int sctrl, err;
2974
2975 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2976 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2977 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002978 return l2cap_try_push_rx_skb(sk);
2979
2980
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002981 }
2982
2983 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2984 if (err >= 0) {
2985 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2986 return err;
2987 }
2988
2989 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002990 BT_DBG("sk %p, Enter local busy", sk);
2991
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002992 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
2993 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2994 __skb_queue_tail(BUSY_QUEUE(sk), skb);
2995
2996 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2997 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
2998 l2cap_send_sframe(pi, sctrl);
2999
3000 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3001
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003002 del_timer(&pi->ack_timer);
3003
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003004 queue_work(_busy_wq, &pi->busy_work);
3005
3006 return err;
3007}
3008
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003009static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003010{
3011 struct l2cap_pinfo *pi = l2cap_pi(sk);
3012 struct sk_buff *_skb;
3013 int err = -EINVAL;
3014
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003015 /*
3016 * TODO: We have to notify the userland if some data is lost with the
3017 * Streaming Mode.
3018 */
3019
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003020 switch (control & L2CAP_CTRL_SAR) {
3021 case L2CAP_SDU_UNSEGMENTED:
3022 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3023 kfree_skb(pi->sdu);
3024 break;
3025 }
3026
3027 err = sock_queue_rcv_skb(sk, skb);
3028 if (!err)
3029 return 0;
3030
3031 break;
3032
3033 case L2CAP_SDU_START:
3034 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3035 kfree_skb(pi->sdu);
3036 break;
3037 }
3038
3039 pi->sdu_len = get_unaligned_le16(skb->data);
3040 skb_pull(skb, 2);
3041
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003042 if (pi->sdu_len > pi->imtu) {
3043 err = -EMSGSIZE;
3044 break;
3045 }
3046
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003047 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3048 if (!pi->sdu) {
3049 err = -ENOMEM;
3050 break;
3051 }
3052
3053 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3054
3055 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3056 pi->partial_sdu_len = skb->len;
3057 err = 0;
3058 break;
3059
3060 case L2CAP_SDU_CONTINUE:
3061 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3062 break;
3063
3064 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3065
3066 pi->partial_sdu_len += skb->len;
3067 if (pi->partial_sdu_len > pi->sdu_len)
3068 kfree_skb(pi->sdu);
3069 else
3070 err = 0;
3071
3072 break;
3073
3074 case L2CAP_SDU_END:
3075 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3076 break;
3077
3078 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3079
3080 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3081 pi->partial_sdu_len += skb->len;
3082
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003083 if (pi->partial_sdu_len > pi->imtu)
3084 goto drop;
3085
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003086 if (pi->partial_sdu_len == pi->sdu_len) {
3087 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3088 err = sock_queue_rcv_skb(sk, _skb);
3089 if (err < 0)
3090 kfree_skb(_skb);
3091 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003092 err = 0;
3093
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003094drop:
3095 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003096 break;
3097 }
3098
3099 kfree_skb(skb);
3100 return err;
3101}
3102
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003103static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3104{
3105 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003106 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003107
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003108 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003109 if (bt_cb(skb)->tx_seq != tx_seq)
3110 break;
3111
3112 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003113 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003114 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003115 l2cap_pi(sk)->buffer_seq_srej =
3116 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003117 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003118 }
3119}
3120
3121static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3122{
3123 struct l2cap_pinfo *pi = l2cap_pi(sk);
3124 struct srej_list *l, *tmp;
3125 u16 control;
3126
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003127 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003128 if (l->tx_seq == tx_seq) {
3129 list_del(&l->list);
3130 kfree(l);
3131 return;
3132 }
3133 control = L2CAP_SUPER_SELECT_REJECT;
3134 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3135 l2cap_send_sframe(pi, control);
3136 list_del(&l->list);
3137 list_add_tail(&l->list, SREJ_LIST(sk));
3138 }
3139}
3140
3141static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3142{
3143 struct l2cap_pinfo *pi = l2cap_pi(sk);
3144 struct srej_list *new;
3145 u16 control;
3146
3147 while (tx_seq != pi->expected_tx_seq) {
3148 control = L2CAP_SUPER_SELECT_REJECT;
3149 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3150 l2cap_send_sframe(pi, control);
3151
3152 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003153 new->tx_seq = pi->expected_tx_seq;
3154 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003155 list_add_tail(&new->list, SREJ_LIST(sk));
3156 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003157 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003158}
3159
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003160static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3161{
3162 struct l2cap_pinfo *pi = l2cap_pi(sk);
3163 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003164 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003165 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003166 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003167 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003168 int err = 0;
3169
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003170 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3171 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003172
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003173 if (L2CAP_CTRL_FINAL & rx_control &&
3174 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003175 del_timer(&pi->monitor_timer);
3176 if (pi->unacked_frames > 0)
3177 __mod_retrans_timer();
3178 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3179 }
3180
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003181 pi->expected_ack_seq = req_seq;
3182 l2cap_drop_acked_frames(sk);
3183
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003184 if (tx_seq == pi->expected_tx_seq)
3185 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003186
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003187 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3188 if (tx_seq_offset < 0)
3189 tx_seq_offset += 64;
3190
3191 /* invalid tx_seq */
3192 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003193 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003194 goto drop;
3195 }
3196
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003197 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3198 goto drop;
3199
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003200 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3201 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003202
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003203 first = list_first_entry(SREJ_LIST(sk),
3204 struct srej_list, list);
3205 if (tx_seq == first->tx_seq) {
3206 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3207 l2cap_check_srej_gap(sk, tx_seq);
3208
3209 list_del(&first->list);
3210 kfree(first);
3211
3212 if (list_empty(SREJ_LIST(sk))) {
3213 pi->buffer_seq = pi->buffer_seq_srej;
3214 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003215 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003216 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003217 }
3218 } else {
3219 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003220
3221 /* duplicated tx_seq */
3222 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3223 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224
3225 list_for_each_entry(l, SREJ_LIST(sk), list) {
3226 if (l->tx_seq == tx_seq) {
3227 l2cap_resend_srejframe(sk, tx_seq);
3228 return 0;
3229 }
3230 }
3231 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003232 }
3233 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003234 expected_tx_seq_offset =
3235 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3236 if (expected_tx_seq_offset < 0)
3237 expected_tx_seq_offset += 64;
3238
3239 /* duplicated tx_seq */
3240 if (tx_seq_offset < expected_tx_seq_offset)
3241 goto drop;
3242
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003243 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003244
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003245 BT_DBG("sk %p, Enter SREJ", sk);
3246
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003247 INIT_LIST_HEAD(SREJ_LIST(sk));
3248 pi->buffer_seq_srej = pi->buffer_seq;
3249
3250 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003251 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003252 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3253
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003254 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3255
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003256 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003257
3258 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003259 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003260 return 0;
3261
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003262expected:
3263 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3264
3265 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003266 bt_cb(skb)->tx_seq = tx_seq;
3267 bt_cb(skb)->sar = sar;
3268 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003269 return 0;
3270 }
3271
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003272 err = l2cap_push_rx_skb(sk, skb, rx_control);
3273 if (err < 0)
3274 return 0;
3275
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003276 if (rx_control & L2CAP_CTRL_FINAL) {
3277 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3278 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003279 else
3280 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003281 }
3282
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003283 __mod_ack_timer();
3284
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003285 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3286 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003287 l2cap_send_ack(pi);
3288
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003289 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003290
3291drop:
3292 kfree_skb(skb);
3293 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003294}
3295
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003296static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003297{
3298 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003299
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003300 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3301 rx_control);
3302
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003303 pi->expected_ack_seq = __get_reqseq(rx_control);
3304 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003305
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003306 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003307 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003308 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3309 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3310 (pi->unacked_frames > 0))
3311 __mod_retrans_timer();
3312
3313 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3314 l2cap_send_srejtail(sk);
3315 } else {
3316 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003317 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003318
3319 } else if (rx_control & L2CAP_CTRL_FINAL) {
3320 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003321
3322 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3323 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003324 else
3325 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003326
3327 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003328 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3329 (pi->unacked_frames > 0))
3330 __mod_retrans_timer();
3331
3332 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003333 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003334 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003335 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003336 l2cap_ertm_send(sk);
3337 }
3338}
3339
3340static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3341{
3342 struct l2cap_pinfo *pi = l2cap_pi(sk);
3343 u8 tx_seq = __get_reqseq(rx_control);
3344
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003345 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3346
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003347 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3348
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003349 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003350 l2cap_drop_acked_frames(sk);
3351
3352 if (rx_control & L2CAP_CTRL_FINAL) {
3353 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3354 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003355 else
3356 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003357 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003358 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003359
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003360 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003361 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003362 }
3363}
3364static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3365{
3366 struct l2cap_pinfo *pi = l2cap_pi(sk);
3367 u8 tx_seq = __get_reqseq(rx_control);
3368
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003369 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3370
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003371 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3372
3373 if (rx_control & L2CAP_CTRL_POLL) {
3374 pi->expected_ack_seq = tx_seq;
3375 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003376
3377 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003378 l2cap_retransmit_one_frame(sk, tx_seq);
3379
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003380 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003381
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003382 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3383 pi->srej_save_reqseq = tx_seq;
3384 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3385 }
3386 } else if (rx_control & L2CAP_CTRL_FINAL) {
3387 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3388 pi->srej_save_reqseq == tx_seq)
3389 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3390 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003391 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003393 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3395 pi->srej_save_reqseq = tx_seq;
3396 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3397 }
3398 }
3399}
3400
3401static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3402{
3403 struct l2cap_pinfo *pi = l2cap_pi(sk);
3404 u8 tx_seq = __get_reqseq(rx_control);
3405
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003406 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3407
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003408 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3409 pi->expected_ack_seq = tx_seq;
3410 l2cap_drop_acked_frames(sk);
3411
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003412 if (rx_control & L2CAP_CTRL_POLL)
3413 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3414
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003415 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3416 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003417 if (rx_control & L2CAP_CTRL_POLL)
3418 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003419 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003421
3422 if (rx_control & L2CAP_CTRL_POLL)
3423 l2cap_send_srejtail(sk);
3424 else
3425 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003426}
3427
3428static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3429{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003430 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3431
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003432 if (L2CAP_CTRL_FINAL & rx_control &&
3433 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003434 del_timer(&l2cap_pi(sk)->monitor_timer);
3435 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003436 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003437 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003438 }
3439
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003440 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3441 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003442 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003443 break;
3444
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003445 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003447 break;
3448
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003449 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003450 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003451 break;
3452
3453 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003454 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003455 break;
3456 }
3457
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003458 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003459 return 0;
3460}
3461
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003462static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3463{
3464 struct l2cap_pinfo *pi = l2cap_pi(sk);
3465 u16 control;
3466 u8 req_seq;
3467 int len, next_tx_seq_offset, req_seq_offset;
3468
3469 control = get_unaligned_le16(skb->data);
3470 skb_pull(skb, 2);
3471 len = skb->len;
3472
3473 /*
3474 * We can just drop the corrupted I-frame here.
3475 * Receiver will miss it and start proper recovery
3476 * procedures and ask retransmission.
3477 */
3478 if (l2cap_check_fcs(pi, skb))
3479 goto drop;
3480
3481 if (__is_sar_start(control) && __is_iframe(control))
3482 len -= 2;
3483
3484 if (pi->fcs == L2CAP_FCS_CRC16)
3485 len -= 2;
3486
3487 if (len > pi->mps) {
3488 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3489 goto drop;
3490 }
3491
3492 req_seq = __get_reqseq(control);
3493 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3494 if (req_seq_offset < 0)
3495 req_seq_offset += 64;
3496
3497 next_tx_seq_offset =
3498 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3499 if (next_tx_seq_offset < 0)
3500 next_tx_seq_offset += 64;
3501
3502 /* check for invalid req-seq */
3503 if (req_seq_offset > next_tx_seq_offset) {
3504 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3505 goto drop;
3506 }
3507
3508 if (__is_iframe(control)) {
3509 if (len < 0) {
3510 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3511 goto drop;
3512 }
3513
3514 l2cap_data_channel_iframe(sk, control, skb);
3515 } else {
3516 if (len != 0) {
3517 BT_ERR("%d", len);
3518 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3519 goto drop;
3520 }
3521
3522 l2cap_data_channel_sframe(sk, control, skb);
3523 }
3524
3525 return 0;
3526
3527drop:
3528 kfree_skb(skb);
3529 return 0;
3530}
3531
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3533{
3534 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003535 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003536 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003537 u8 tx_seq;
3538 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
3540 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3541 if (!sk) {
3542 BT_DBG("unknown cid 0x%4.4x", cid);
3543 goto drop;
3544 }
3545
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003546 pi = l2cap_pi(sk);
3547
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 BT_DBG("sk %p, len %d", sk, skb->len);
3549
3550 if (sk->sk_state != BT_CONNECTED)
3551 goto drop;
3552
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003553 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003554 case L2CAP_MODE_BASIC:
3555 /* If socket recv buffers overflows we drop data here
3556 * which is *bad* because L2CAP has to be reliable.
3557 * But we don't have any other choice. L2CAP doesn't
3558 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003560 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003561 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003563 if (!sock_queue_rcv_skb(sk, skb))
3564 goto done;
3565 break;
3566
3567 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003568 if (!sock_owned_by_user(sk)) {
3569 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003570 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003571 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003572 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003573 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003574
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003575 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003576
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003577 case L2CAP_MODE_STREAMING:
3578 control = get_unaligned_le16(skb->data);
3579 skb_pull(skb, 2);
3580 len = skb->len;
3581
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003582 if (l2cap_check_fcs(pi, skb))
3583 goto drop;
3584
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003585 if (__is_sar_start(control))
3586 len -= 2;
3587
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003588 if (pi->fcs == L2CAP_FCS_CRC16)
3589 len -= 2;
3590
Nathan Holstein51893f82010-06-09 15:46:25 -04003591 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003592 goto drop;
3593
3594 tx_seq = __get_txseq(control);
3595
3596 if (pi->expected_tx_seq == tx_seq)
3597 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3598 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003599 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003600
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003601 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003602
3603 goto done;
3604
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003605 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003606 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003607 break;
3608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
3610drop:
3611 kfree_skb(skb);
3612
3613done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003614 if (sk)
3615 bh_unlock_sock(sk);
3616
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 return 0;
3618}
3619
Al Viro8e036fc2007-07-29 00:16:36 -07003620static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621{
3622 struct sock *sk;
3623
3624 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3625 if (!sk)
3626 goto drop;
3627
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003628 bh_lock_sock(sk);
3629
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 BT_DBG("sk %p, len %d", sk, skb->len);
3631
3632 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3633 goto drop;
3634
3635 if (l2cap_pi(sk)->imtu < skb->len)
3636 goto drop;
3637
3638 if (!sock_queue_rcv_skb(sk, skb))
3639 goto done;
3640
3641drop:
3642 kfree_skb(skb);
3643
3644done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003645 if (sk)
3646 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 return 0;
3648}
3649
3650static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3651{
3652 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003653 u16 cid, len;
3654 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
3656 skb_pull(skb, L2CAP_HDR_SIZE);
3657 cid = __le16_to_cpu(lh->cid);
3658 len = __le16_to_cpu(lh->len);
3659
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003660 if (len != skb->len) {
3661 kfree_skb(skb);
3662 return;
3663 }
3664
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3666
3667 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003668 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003669 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 l2cap_sig_channel(conn, skb);
3671 break;
3672
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003673 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003674 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 skb_pull(skb, 2);
3676 l2cap_conless_channel(conn, psm, skb);
3677 break;
3678
3679 default:
3680 l2cap_data_channel(conn, cid, skb);
3681 break;
3682 }
3683}
3684
3685/* ---- L2CAP interface with lower layer (HCI) ---- */
3686
3687static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3688{
3689 int exact = 0, lm1 = 0, lm2 = 0;
3690 register struct sock *sk;
3691 struct hlist_node *node;
3692
3693 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003694 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
3696 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3697
3698 /* Find listening sockets and check their link_mode */
3699 read_lock(&l2cap_sk_list.lock);
3700 sk_for_each(sk, node, &l2cap_sk_list.head) {
3701 if (sk->sk_state != BT_LISTEN)
3702 continue;
3703
3704 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003705 lm1 |= HCI_LM_ACCEPT;
3706 if (l2cap_pi(sk)->role_switch)
3707 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003709 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3710 lm2 |= HCI_LM_ACCEPT;
3711 if (l2cap_pi(sk)->role_switch)
3712 lm2 |= HCI_LM_MASTER;
3713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 }
3715 read_unlock(&l2cap_sk_list.lock);
3716
3717 return exact ? lm1 : lm2;
3718}
3719
3720static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3721{
Marcel Holtmann01394182006-07-03 10:02:46 +02003722 struct l2cap_conn *conn;
3723
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3725
Ville Tervoacd7d372011-02-10 22:38:49 -03003726 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003727 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728
3729 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 conn = l2cap_conn_add(hcon, status);
3731 if (conn)
3732 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003733 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 l2cap_conn_del(hcon, bt_err(status));
3735
3736 return 0;
3737}
3738
Marcel Holtmann2950f212009-02-12 14:02:50 +01003739static int l2cap_disconn_ind(struct hci_conn *hcon)
3740{
3741 struct l2cap_conn *conn = hcon->l2cap_data;
3742
3743 BT_DBG("hcon %p", hcon);
3744
3745 if (hcon->type != ACL_LINK || !conn)
3746 return 0x13;
3747
3748 return conn->disc_reason;
3749}
3750
3751static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752{
3753 BT_DBG("hcon %p reason %d", hcon, reason);
3754
Ville Tervoacd7d372011-02-10 22:38:49 -03003755 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003756 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757
3758 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003759
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 return 0;
3761}
3762
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003763static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3764{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003765 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003766 return;
3767
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003768 if (encrypt == 0x00) {
3769 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3770 l2cap_sock_clear_timer(sk);
3771 l2cap_sock_set_timer(sk, HZ * 5);
3772 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3773 __l2cap_sock_close(sk, ECONNREFUSED);
3774 } else {
3775 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3776 l2cap_sock_clear_timer(sk);
3777 }
3778}
3779
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003780static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781{
3782 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003783 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785
Marcel Holtmann01394182006-07-03 10:02:46 +02003786 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003788
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 l = &conn->chan_list;
3790
3791 BT_DBG("conn %p", conn);
3792
3793 read_lock(&l->lock);
3794
3795 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3796 bh_lock_sock(sk);
3797
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003798 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3799 bh_unlock_sock(sk);
3800 continue;
3801 }
3802
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003803 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003804 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003805 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003806 bh_unlock_sock(sk);
3807 continue;
3808 }
3809
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003810 if (sk->sk_state == BT_CONNECT) {
3811 if (!status) {
3812 struct l2cap_conn_req req;
3813 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3814 req.psm = l2cap_pi(sk)->psm;
3815
3816 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003817 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003818
3819 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3820 L2CAP_CONN_REQ, sizeof(req), &req);
3821 } else {
3822 l2cap_sock_clear_timer(sk);
3823 l2cap_sock_set_timer(sk, HZ / 10);
3824 }
3825 } else if (sk->sk_state == BT_CONNECT2) {
3826 struct l2cap_conn_rsp rsp;
3827 __u16 result;
3828
3829 if (!status) {
3830 sk->sk_state = BT_CONFIG;
3831 result = L2CAP_CR_SUCCESS;
3832 } else {
3833 sk->sk_state = BT_DISCONN;
3834 l2cap_sock_set_timer(sk, HZ / 10);
3835 result = L2CAP_CR_SEC_BLOCK;
3836 }
3837
3838 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3839 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3840 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003841 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003842 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3843 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 }
3845
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 bh_unlock_sock(sk);
3847 }
3848
3849 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003850
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 return 0;
3852}
3853
3854static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3855{
3856 struct l2cap_conn *conn = hcon->l2cap_data;
3857
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003858 if (!conn)
3859 conn = l2cap_conn_add(hcon, 0);
3860
3861 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 goto drop;
3863
3864 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3865
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003866 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003868 struct sock *sk;
3869 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 int len;
3871
3872 if (conn->rx_len) {
3873 BT_ERR("Unexpected start frame (len %d)", skb->len);
3874 kfree_skb(conn->rx_skb);
3875 conn->rx_skb = NULL;
3876 conn->rx_len = 0;
3877 l2cap_conn_unreliable(conn, ECOMM);
3878 }
3879
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003880 /* Start fragment always begin with Basic L2CAP header */
3881 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 BT_ERR("Frame is too short (len %d)", skb->len);
3883 l2cap_conn_unreliable(conn, ECOMM);
3884 goto drop;
3885 }
3886
3887 hdr = (struct l2cap_hdr *) skb->data;
3888 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003889 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
3891 if (len == skb->len) {
3892 /* Complete frame received */
3893 l2cap_recv_frame(conn, skb);
3894 return 0;
3895 }
3896
3897 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3898
3899 if (skb->len > len) {
3900 BT_ERR("Frame is too long (len %d, expected len %d)",
3901 skb->len, len);
3902 l2cap_conn_unreliable(conn, ECOMM);
3903 goto drop;
3904 }
3905
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003906 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3907
3908 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3909 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3910 len, l2cap_pi(sk)->imtu);
3911 bh_unlock_sock(sk);
3912 l2cap_conn_unreliable(conn, ECOMM);
3913 goto drop;
3914 }
3915
3916 if (sk)
3917 bh_unlock_sock(sk);
3918
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003920 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3921 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 goto drop;
3923
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003924 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003925 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 conn->rx_len = len - skb->len;
3927 } else {
3928 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3929
3930 if (!conn->rx_len) {
3931 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3932 l2cap_conn_unreliable(conn, ECOMM);
3933 goto drop;
3934 }
3935
3936 if (skb->len > conn->rx_len) {
3937 BT_ERR("Fragment is too long (len %d, expected %d)",
3938 skb->len, conn->rx_len);
3939 kfree_skb(conn->rx_skb);
3940 conn->rx_skb = NULL;
3941 conn->rx_len = 0;
3942 l2cap_conn_unreliable(conn, ECOMM);
3943 goto drop;
3944 }
3945
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003946 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003947 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 conn->rx_len -= skb->len;
3949
3950 if (!conn->rx_len) {
3951 /* Complete frame received */
3952 l2cap_recv_frame(conn, conn->rx_skb);
3953 conn->rx_skb = NULL;
3954 }
3955 }
3956
3957drop:
3958 kfree_skb(skb);
3959 return 0;
3960}
3961
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003962static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963{
3964 struct sock *sk;
3965 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
3967 read_lock_bh(&l2cap_sk_list.lock);
3968
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003969 sk_for_each(sk, node, &l2cap_sk_list.head) {
3970 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003972 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003973 batostr(&bt_sk(sk)->src),
3974 batostr(&bt_sk(sk)->dst),
3975 sk->sk_state, __le16_to_cpu(pi->psm),
3976 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003977 pi->imtu, pi->omtu, pi->sec_level,
3978 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003982
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003983 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984}
3985
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003986static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3987{
3988 return single_open(file, l2cap_debugfs_show, inode->i_private);
3989}
3990
3991static const struct file_operations l2cap_debugfs_fops = {
3992 .open = l2cap_debugfs_open,
3993 .read = seq_read,
3994 .llseek = seq_lseek,
3995 .release = single_release,
3996};
3997
3998static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000static struct hci_proto l2cap_hci_proto = {
4001 .name = "L2CAP",
4002 .id = HCI_PROTO_L2CAP,
4003 .connect_ind = l2cap_connect_ind,
4004 .connect_cfm = l2cap_connect_cfm,
4005 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004006 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004007 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 .recv_acldata = l2cap_recv_acldata
4009};
4010
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004011int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012{
4013 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004014
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004015 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 if (err < 0)
4017 return err;
4018
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004019 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004020 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004021 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 goto error;
4023 }
4024
4025 err = hci_register_proto(&l2cap_hci_proto);
4026 if (err < 0) {
4027 BT_ERR("L2CAP protocol registration failed");
4028 bt_sock_unregister(BTPROTO_L2CAP);
4029 goto error;
4030 }
4031
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004032 if (bt_debugfs) {
4033 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4034 bt_debugfs, NULL, &l2cap_debugfs_fops);
4035 if (!l2cap_debugfs)
4036 BT_ERR("Failed to create L2CAP debug file");
4037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 return 0;
4040
4041error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004042 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004043 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 return err;
4045}
4046
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004047void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004049 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004051 flush_workqueue(_busy_wq);
4052 destroy_workqueue(_busy_wq);
4053
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4055 BT_ERR("L2CAP protocol unregistration failed");
4056
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004057 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058}
4059
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004060module_param(disable_ertm, bool, 0644);
4061MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");