blob: 2c8dd4494c63966ffd0e5df4f66546139dea2f81 [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);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001054 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001055
1056 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1057 control |= L2CAP_CTRL_FINAL;
1058 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1059 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001060
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001061 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1062 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001063
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001064 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1065
1066 if (pi->fcs == L2CAP_FCS_CRC16) {
1067 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1068 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1069 }
1070
1071 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001072}
1073
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001074int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001075{
1076 struct sk_buff *skb, *tx_skb;
1077 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001078 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001079 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001080
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001081 if (sk->sk_state != BT_CONNECTED)
1082 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001083
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001084 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001085
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001086 if (pi->remote_max_tx &&
1087 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001088 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001089 break;
1090 }
1091
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001092 tx_skb = skb_clone(skb, GFP_ATOMIC);
1093
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001094 bt_cb(skb)->retries++;
1095
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001096 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001097 control &= L2CAP_CTRL_SAR;
1098
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001099 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1100 control |= L2CAP_CTRL_FINAL;
1101 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1102 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001103 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001104 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1105 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1106
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001107
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001108 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001109 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1110 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1111 }
1112
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001113 l2cap_do_send(sk, tx_skb);
1114
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001115 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116
1117 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1118 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1119
Suraj Sumangala52cb1c02011-03-09 14:44:05 +05301120 if (bt_cb(skb)->retries == 1)
1121 pi->unacked_frames++;
1122
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001123 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001124
1125 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1126 sk->sk_send_head = NULL;
1127 else
1128 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001129
1130 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001131 }
1132
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001133 return nsent;
1134}
1135
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001136static int l2cap_retransmit_frames(struct sock *sk)
1137{
1138 struct l2cap_pinfo *pi = l2cap_pi(sk);
1139 int ret;
1140
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001141 if (!skb_queue_empty(TX_QUEUE(sk)))
1142 sk->sk_send_head = TX_QUEUE(sk)->next;
1143
1144 pi->next_tx_seq = pi->expected_ack_seq;
1145 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001146 return ret;
1147}
1148
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001149static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001150{
1151 struct sock *sk = (struct sock *)pi;
1152 u16 control = 0;
1153
1154 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1155
1156 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1157 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001158 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001159 l2cap_send_sframe(pi, control);
1160 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001161 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001163 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001164 return;
1165
1166 control |= L2CAP_SUPER_RCV_READY;
1167 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001168}
1169
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001170static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001171{
1172 struct srej_list *tail;
1173 u16 control;
1174
1175 control = L2CAP_SUPER_SELECT_REJECT;
1176 control |= L2CAP_CTRL_FINAL;
1177
1178 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1179 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1180
1181 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001182}
1183
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001184static 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 -07001185{
1186 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001187 struct sk_buff **frag;
1188 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001190 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001191 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193 sent += count;
1194 len -= count;
1195
1196 /* Continuation fragments (no L2CAP header) */
1197 frag = &skb_shinfo(skb)->frag_list;
1198 while (len) {
1199 count = min_t(unsigned int, conn->mtu, len);
1200
1201 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1202 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001203 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1205 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
1207 sent += count;
1208 len -= count;
1209
1210 frag = &(*frag)->next;
1211 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001214}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001216struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217{
1218 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1219 struct sk_buff *skb;
1220 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1221 struct l2cap_hdr *lh;
1222
1223 BT_DBG("sk %p len %d", sk, (int)len);
1224
1225 count = min_t(unsigned int, (conn->mtu - hlen), len);
1226 skb = bt_skb_send_alloc(sk, count + hlen,
1227 msg->msg_flags & MSG_DONTWAIT, &err);
1228 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001229 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230
1231 /* Create L2CAP header */
1232 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1233 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1234 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1235 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1236
1237 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1238 if (unlikely(err < 0)) {
1239 kfree_skb(skb);
1240 return ERR_PTR(err);
1241 }
1242 return skb;
1243}
1244
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001245struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246{
1247 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1248 struct sk_buff *skb;
1249 int err, count, hlen = L2CAP_HDR_SIZE;
1250 struct l2cap_hdr *lh;
1251
1252 BT_DBG("sk %p len %d", sk, (int)len);
1253
1254 count = min_t(unsigned int, (conn->mtu - hlen), len);
1255 skb = bt_skb_send_alloc(sk, count + hlen,
1256 msg->msg_flags & MSG_DONTWAIT, &err);
1257 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001258 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001259
1260 /* Create L2CAP header */
1261 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1262 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1263 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1264
1265 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1266 if (unlikely(err < 0)) {
1267 kfree_skb(skb);
1268 return ERR_PTR(err);
1269 }
1270 return skb;
1271}
1272
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001273struct 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 -03001274{
1275 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1276 struct sk_buff *skb;
1277 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1278 struct l2cap_hdr *lh;
1279
1280 BT_DBG("sk %p len %d", sk, (int)len);
1281
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001282 if (!conn)
1283 return ERR_PTR(-ENOTCONN);
1284
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001285 if (sdulen)
1286 hlen += 2;
1287
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001288 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1289 hlen += 2;
1290
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001291 count = min_t(unsigned int, (conn->mtu - hlen), len);
1292 skb = bt_skb_send_alloc(sk, count + hlen,
1293 msg->msg_flags & MSG_DONTWAIT, &err);
1294 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001295 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001296
1297 /* Create L2CAP header */
1298 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1299 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1300 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1301 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001302 if (sdulen)
1303 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001304
1305 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1306 if (unlikely(err < 0)) {
1307 kfree_skb(skb);
1308 return ERR_PTR(err);
1309 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001310
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001311 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1312 put_unaligned_le16(0, skb_put(skb, 2));
1313
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001314 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001315 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316}
1317
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001318int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001319{
1320 struct l2cap_pinfo *pi = l2cap_pi(sk);
1321 struct sk_buff *skb;
1322 struct sk_buff_head sar_queue;
1323 u16 control;
1324 size_t size = 0;
1325
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001326 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001327 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001328 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001329 if (IS_ERR(skb))
1330 return PTR_ERR(skb);
1331
1332 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001333 len -= pi->remote_mps;
1334 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001335
1336 while (len > 0) {
1337 size_t buflen;
1338
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001339 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001340 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001341 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001342 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001343 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001344 buflen = len;
1345 }
1346
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001347 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001348 if (IS_ERR(skb)) {
1349 skb_queue_purge(&sar_queue);
1350 return PTR_ERR(skb);
1351 }
1352
1353 __skb_queue_tail(&sar_queue, skb);
1354 len -= buflen;
1355 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001356 }
1357 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1358 if (sk->sk_send_head == NULL)
1359 sk->sk_send_head = sar_queue.next;
1360
1361 return size;
1362}
1363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364static void l2cap_chan_ready(struct sock *sk)
1365{
1366 struct sock *parent = bt_sk(sk)->parent;
1367
1368 BT_DBG("sk %p, parent %p", sk, parent);
1369
1370 l2cap_pi(sk)->conf_state = 0;
1371 l2cap_sock_clear_timer(sk);
1372
1373 if (!parent) {
1374 /* Outgoing channel.
1375 * Wake up socket sleeping on connect.
1376 */
1377 sk->sk_state = BT_CONNECTED;
1378 sk->sk_state_change(sk);
1379 } else {
1380 /* Incoming channel.
1381 * Wake up socket sleeping on accept.
1382 */
1383 parent->sk_data_ready(parent, 0);
1384 }
1385}
1386
1387/* Copy frame to all raw sockets on that connection */
1388static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1389{
1390 struct l2cap_chan_list *l = &conn->chan_list;
1391 struct sk_buff *nskb;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001392 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
1394 BT_DBG("conn %p", conn);
1395
1396 read_lock(&l->lock);
1397 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1398 if (sk->sk_type != SOCK_RAW)
1399 continue;
1400
1401 /* Don't send frame to the socket it came from */
1402 if (skb->sk == sk)
1403 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001404 nskb = skb_clone(skb, GFP_ATOMIC);
1405 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 continue;
1407
1408 if (sock_queue_rcv_skb(sk, nskb))
1409 kfree_skb(nskb);
1410 }
1411 read_unlock(&l->lock);
1412}
1413
1414/* ---- L2CAP signalling commands ---- */
1415static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1416 u8 code, u8 ident, u16 dlen, void *data)
1417{
1418 struct sk_buff *skb, **frag;
1419 struct l2cap_cmd_hdr *cmd;
1420 struct l2cap_hdr *lh;
1421 int len, count;
1422
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001423 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1424 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1427 count = min_t(unsigned int, conn->mtu, len);
1428
1429 skb = bt_skb_alloc(count, GFP_ATOMIC);
1430 if (!skb)
1431 return NULL;
1432
1433 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001434 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001435
1436 if (conn->hcon->type == LE_LINK)
1437 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1438 else
1439 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
1441 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1442 cmd->code = code;
1443 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001444 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
1446 if (dlen) {
1447 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1448 memcpy(skb_put(skb, count), data, count);
1449 data += count;
1450 }
1451
1452 len -= skb->len;
1453
1454 /* Continuation fragments (no L2CAP header) */
1455 frag = &skb_shinfo(skb)->frag_list;
1456 while (len) {
1457 count = min_t(unsigned int, conn->mtu, len);
1458
1459 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1460 if (!*frag)
1461 goto fail;
1462
1463 memcpy(skb_put(*frag, count), data, count);
1464
1465 len -= count;
1466 data += count;
1467
1468 frag = &(*frag)->next;
1469 }
1470
1471 return skb;
1472
1473fail:
1474 kfree_skb(skb);
1475 return NULL;
1476}
1477
1478static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1479{
1480 struct l2cap_conf_opt *opt = *ptr;
1481 int len;
1482
1483 len = L2CAP_CONF_OPT_SIZE + opt->len;
1484 *ptr += len;
1485
1486 *type = opt->type;
1487 *olen = opt->len;
1488
1489 switch (opt->len) {
1490 case 1:
1491 *val = *((u8 *) opt->val);
1492 break;
1493
1494 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001495 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 break;
1497
1498 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001499 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 break;
1501
1502 default:
1503 *val = (unsigned long) opt->val;
1504 break;
1505 }
1506
1507 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1508 return len;
1509}
1510
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1512{
1513 struct l2cap_conf_opt *opt = *ptr;
1514
1515 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1516
1517 opt->type = type;
1518 opt->len = len;
1519
1520 switch (len) {
1521 case 1:
1522 *((u8 *) opt->val) = val;
1523 break;
1524
1525 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001526 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 break;
1528
1529 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001530 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 break;
1532
1533 default:
1534 memcpy(opt->val, (void *) val, len);
1535 break;
1536 }
1537
1538 *ptr += L2CAP_CONF_OPT_SIZE + len;
1539}
1540
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001541static void l2cap_ack_timeout(unsigned long arg)
1542{
1543 struct sock *sk = (void *) arg;
1544
1545 bh_lock_sock(sk);
1546 l2cap_send_ack(l2cap_pi(sk));
1547 bh_unlock_sock(sk);
1548}
1549
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001550static inline void l2cap_ertm_init(struct sock *sk)
1551{
1552 l2cap_pi(sk)->expected_ack_seq = 0;
1553 l2cap_pi(sk)->unacked_frames = 0;
1554 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001555 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001556 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001557
1558 setup_timer(&l2cap_pi(sk)->retrans_timer,
1559 l2cap_retrans_timeout, (unsigned long) sk);
1560 setup_timer(&l2cap_pi(sk)->monitor_timer,
1561 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001562 setup_timer(&l2cap_pi(sk)->ack_timer,
1563 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001564
1565 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001566 __skb_queue_head_init(BUSY_QUEUE(sk));
1567
1568 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001569
1570 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001571}
1572
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001573static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1574{
1575 switch (mode) {
1576 case L2CAP_MODE_STREAMING:
1577 case L2CAP_MODE_ERTM:
1578 if (l2cap_mode_supported(mode, remote_feat_mask))
1579 return mode;
1580 /* fall through */
1581 default:
1582 return L2CAP_MODE_BASIC;
1583 }
1584}
1585
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001586int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587{
1588 struct l2cap_pinfo *pi = l2cap_pi(sk);
1589 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001590 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 void *ptr = req->data;
1592
1593 BT_DBG("sk %p", sk);
1594
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001595 if (pi->num_conf_req || pi->num_conf_rsp)
1596 goto done;
1597
1598 switch (pi->mode) {
1599 case L2CAP_MODE_STREAMING:
1600 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001601 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001602 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001603
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001604 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001605 default:
1606 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1607 break;
1608 }
1609
1610done:
Gustavo F. Padovan79906812011-01-24 16:01:43 -02001611 if (pi->imtu != L2CAP_DEFAULT_MTU)
1612 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1613
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001614 switch (pi->mode) {
1615 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001616 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1617 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1618 break;
1619
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001620 rfc.mode = L2CAP_MODE_BASIC;
1621 rfc.txwin_size = 0;
1622 rfc.max_transmit = 0;
1623 rfc.retrans_timeout = 0;
1624 rfc.monitor_timeout = 0;
1625 rfc.max_pdu_size = 0;
1626
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001627 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1628 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001629 break;
1630
1631 case L2CAP_MODE_ERTM:
1632 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001633 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001634 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001635 rfc.retrans_timeout = 0;
1636 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001637 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001638 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001639 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001640
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001641 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1642 (unsigned long) &rfc);
1643
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001644 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1645 break;
1646
1647 if (pi->fcs == L2CAP_FCS_NONE ||
1648 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1649 pi->fcs = L2CAP_FCS_NONE;
1650 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1651 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001652 break;
1653
1654 case L2CAP_MODE_STREAMING:
1655 rfc.mode = L2CAP_MODE_STREAMING;
1656 rfc.txwin_size = 0;
1657 rfc.max_transmit = 0;
1658 rfc.retrans_timeout = 0;
1659 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001660 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001661 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001662 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001663
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001664 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1665 (unsigned long) &rfc);
1666
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001667 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1668 break;
1669
1670 if (pi->fcs == L2CAP_FCS_NONE ||
1671 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1672 pi->fcs = L2CAP_FCS_NONE;
1673 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1674 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001675 break;
1676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001678 req->dcid = cpu_to_le16(pi->dcid);
1679 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 return ptr - data;
1682}
1683
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001684static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685{
1686 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001687 struct l2cap_conf_rsp *rsp = data;
1688 void *ptr = rsp->data;
1689 void *req = pi->conf_req;
1690 int len = pi->conf_len;
1691 int type, hint, olen;
1692 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001693 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001694 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001695 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001697 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001698
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001699 while (len >= L2CAP_CONF_OPT_SIZE) {
1700 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001702 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001703 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001704
1705 switch (type) {
1706 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001707 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001708 break;
1709
1710 case L2CAP_CONF_FLUSH_TO:
1711 pi->flush_to = val;
1712 break;
1713
1714 case L2CAP_CONF_QOS:
1715 break;
1716
Marcel Holtmann6464f352007-10-20 13:39:51 +02001717 case L2CAP_CONF_RFC:
1718 if (olen == sizeof(rfc))
1719 memcpy(&rfc, (void *) val, olen);
1720 break;
1721
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001722 case L2CAP_CONF_FCS:
1723 if (val == L2CAP_FCS_NONE)
1724 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1725
1726 break;
1727
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001728 default:
1729 if (hint)
1730 break;
1731
1732 result = L2CAP_CONF_UNKNOWN;
1733 *((u8 *) ptr++) = type;
1734 break;
1735 }
1736 }
1737
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001738 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001739 goto done;
1740
1741 switch (pi->mode) {
1742 case L2CAP_MODE_STREAMING:
1743 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001744 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1745 pi->mode = l2cap_select_mode(rfc.mode,
1746 pi->conn->feat_mask);
1747 break;
1748 }
1749
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001750 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001751 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001752
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001753 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001754 }
1755
1756done:
1757 if (pi->mode != rfc.mode) {
1758 result = L2CAP_CONF_UNACCEPT;
1759 rfc.mode = pi->mode;
1760
1761 if (pi->num_conf_rsp == 1)
1762 return -ECONNREFUSED;
1763
1764 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1765 sizeof(rfc), (unsigned long) &rfc);
1766 }
1767
1768
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001769 if (result == L2CAP_CONF_SUCCESS) {
1770 /* Configure output options and let the other side know
1771 * which ones we don't like. */
1772
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1774 result = L2CAP_CONF_UNACCEPT;
1775 else {
1776 pi->omtu = mtu;
1777 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1778 }
1779 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001780
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001781 switch (rfc.mode) {
1782 case L2CAP_MODE_BASIC:
1783 pi->fcs = L2CAP_FCS_NONE;
1784 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1785 break;
1786
1787 case L2CAP_MODE_ERTM:
1788 pi->remote_tx_win = rfc.txwin_size;
1789 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001790
1791 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1792 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001793
1794 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001795
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001796 rfc.retrans_timeout =
1797 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1798 rfc.monitor_timeout =
1799 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800
1801 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001802
1803 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1804 sizeof(rfc), (unsigned long) &rfc);
1805
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001806 break;
1807
1808 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001809 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1810 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001811
1812 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001813
1814 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001815
1816 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1817 sizeof(rfc), (unsigned long) &rfc);
1818
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001819 break;
1820
1821 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001822 result = L2CAP_CONF_UNACCEPT;
1823
1824 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001825 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001826 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001827
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001828 if (result == L2CAP_CONF_SUCCESS)
1829 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1830 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001831 rsp->scid = cpu_to_le16(pi->dcid);
1832 rsp->result = cpu_to_le16(result);
1833 rsp->flags = cpu_to_le16(0x0000);
1834
1835 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836}
1837
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001838static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1839{
1840 struct l2cap_pinfo *pi = l2cap_pi(sk);
1841 struct l2cap_conf_req *req = data;
1842 void *ptr = req->data;
1843 int type, olen;
1844 unsigned long val;
1845 struct l2cap_conf_rfc rfc;
1846
1847 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1848
1849 while (len >= L2CAP_CONF_OPT_SIZE) {
1850 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1851
1852 switch (type) {
1853 case L2CAP_CONF_MTU:
1854 if (val < L2CAP_DEFAULT_MIN_MTU) {
1855 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001856 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001857 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001858 pi->imtu = val;
1859 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001860 break;
1861
1862 case L2CAP_CONF_FLUSH_TO:
1863 pi->flush_to = val;
1864 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1865 2, pi->flush_to);
1866 break;
1867
1868 case L2CAP_CONF_RFC:
1869 if (olen == sizeof(rfc))
1870 memcpy(&rfc, (void *)val, olen);
1871
1872 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1873 rfc.mode != pi->mode)
1874 return -ECONNREFUSED;
1875
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001876 pi->fcs = 0;
1877
1878 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1879 sizeof(rfc), (unsigned long) &rfc);
1880 break;
1881 }
1882 }
1883
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001884 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1885 return -ECONNREFUSED;
1886
1887 pi->mode = rfc.mode;
1888
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001889 if (*result == L2CAP_CONF_SUCCESS) {
1890 switch (rfc.mode) {
1891 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001892 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1893 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001894 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001895 break;
1896 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001897 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001898 }
1899 }
1900
1901 req->dcid = cpu_to_le16(pi->dcid);
1902 req->flags = cpu_to_le16(0x0000);
1903
1904 return ptr - data;
1905}
1906
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001907static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908{
1909 struct l2cap_conf_rsp *rsp = data;
1910 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001912 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001914 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001915 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001916 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
1918 return ptr - data;
1919}
1920
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001921static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1922{
1923 struct l2cap_pinfo *pi = l2cap_pi(sk);
1924 int type, olen;
1925 unsigned long val;
1926 struct l2cap_conf_rfc rfc;
1927
1928 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1929
1930 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1931 return;
1932
1933 while (len >= L2CAP_CONF_OPT_SIZE) {
1934 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1935
1936 switch (type) {
1937 case L2CAP_CONF_RFC:
1938 if (olen == sizeof(rfc))
1939 memcpy(&rfc, (void *)val, olen);
1940 goto done;
1941 }
1942 }
1943
1944done:
1945 switch (rfc.mode) {
1946 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001947 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1948 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001949 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1950 break;
1951 case L2CAP_MODE_STREAMING:
1952 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1953 }
1954}
1955
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001956static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1957{
1958 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1959
1960 if (rej->reason != 0x0000)
1961 return 0;
1962
1963 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1964 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001965 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001966
1967 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001968 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001969
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001970 l2cap_conn_start(conn);
1971 }
1972
1973 return 0;
1974}
1975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1977{
1978 struct l2cap_chan_list *list = &conn->chan_list;
1979 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1980 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001981 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001982 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
1984 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001985 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
1987 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
1988
1989 /* Check if we have socket listening on psm */
1990 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
1991 if (!parent) {
1992 result = L2CAP_CR_BAD_PSM;
1993 goto sendresp;
1994 }
1995
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001996 bh_lock_sock(parent);
1997
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001998 /* Check if the ACL is secure enough (if not SDP) */
1999 if (psm != cpu_to_le16(0x0001) &&
2000 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002001 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002002 result = L2CAP_CR_SEC_BLOCK;
2003 goto response;
2004 }
2005
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 result = L2CAP_CR_NO_MEM;
2007
2008 /* Check for backlog size */
2009 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002010 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 goto response;
2012 }
2013
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002014 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 if (!sk)
2016 goto response;
2017
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002018 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
2020 /* Check if we already have channel with that dcid */
2021 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002022 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 sock_set_flag(sk, SOCK_ZAPPED);
2024 l2cap_sock_kill(sk);
2025 goto response;
2026 }
2027
2028 hci_conn_hold(conn->hcon);
2029
2030 l2cap_sock_init(sk, parent);
2031 bacpy(&bt_sk(sk)->src, conn->src);
2032 bacpy(&bt_sk(sk)->dst, conn->dst);
2033 l2cap_pi(sk)->psm = psm;
2034 l2cap_pi(sk)->dcid = scid;
2035
2036 __l2cap_chan_add(conn, sk, parent);
2037 dcid = l2cap_pi(sk)->scid;
2038
2039 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2040
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 l2cap_pi(sk)->ident = cmd->ident;
2042
Marcel Holtmann984947d2009-02-06 23:35:19 +01002043 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002044 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002045 if (bt_sk(sk)->defer_setup) {
2046 sk->sk_state = BT_CONNECT2;
2047 result = L2CAP_CR_PEND;
2048 status = L2CAP_CS_AUTHOR_PEND;
2049 parent->sk_data_ready(parent, 0);
2050 } else {
2051 sk->sk_state = BT_CONFIG;
2052 result = L2CAP_CR_SUCCESS;
2053 status = L2CAP_CS_NO_INFO;
2054 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002055 } else {
2056 sk->sk_state = BT_CONNECT2;
2057 result = L2CAP_CR_PEND;
2058 status = L2CAP_CS_AUTHEN_PEND;
2059 }
2060 } else {
2061 sk->sk_state = BT_CONNECT2;
2062 result = L2CAP_CR_PEND;
2063 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 }
2065
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002066 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
2068response:
2069 bh_unlock_sock(parent);
2070
2071sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002072 rsp.scid = cpu_to_le16(scid);
2073 rsp.dcid = cpu_to_le16(dcid);
2074 rsp.result = cpu_to_le16(result);
2075 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002077
2078 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2079 struct l2cap_info_req info;
2080 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2081
2082 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2083 conn->info_ident = l2cap_get_ident(conn);
2084
2085 mod_timer(&conn->info_timer, jiffies +
2086 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2087
2088 l2cap_send_cmd(conn, conn->info_ident,
2089 L2CAP_INFO_REQ, sizeof(info), &info);
2090 }
2091
Nathan Holsteind793fe82010-10-15 11:54:02 -04002092 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002093 result == L2CAP_CR_SUCCESS) {
2094 u8 buf[128];
2095 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2096 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2097 l2cap_build_conf_req(sk, buf), buf);
2098 l2cap_pi(sk)->num_conf_req++;
2099 }
2100
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 return 0;
2102}
2103
2104static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2105{
2106 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2107 u16 scid, dcid, result, status;
2108 struct sock *sk;
2109 u8 req[128];
2110
2111 scid = __le16_to_cpu(rsp->scid);
2112 dcid = __le16_to_cpu(rsp->dcid);
2113 result = __le16_to_cpu(rsp->result);
2114 status = __le16_to_cpu(rsp->status);
2115
2116 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2117
2118 if (scid) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002119 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2120 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002121 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 } else {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002123 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2124 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002125 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 }
2127
2128 switch (result) {
2129 case L2CAP_CR_SUCCESS:
2130 sk->sk_state = BT_CONFIG;
2131 l2cap_pi(sk)->ident = 0;
2132 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002133 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2134
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002135 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2136 break;
2137
2138 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2139
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2141 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002142 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 break;
2144
2145 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002146 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 break;
2148
2149 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002150 /* don't delete l2cap channel if sk is owned by user */
2151 if (sock_owned_by_user(sk)) {
2152 sk->sk_state = BT_DISCONN;
2153 l2cap_sock_clear_timer(sk);
2154 l2cap_sock_set_timer(sk, HZ / 5);
2155 break;
2156 }
2157
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 l2cap_chan_del(sk, ECONNREFUSED);
2159 break;
2160 }
2161
2162 bh_unlock_sock(sk);
2163 return 0;
2164}
2165
Mat Martineau8c462b62010-08-24 15:35:42 -07002166static inline void set_default_fcs(struct l2cap_pinfo *pi)
2167{
2168 /* FCS is enabled only in ERTM or streaming mode, if one or both
2169 * sides request it.
2170 */
2171 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2172 pi->fcs = L2CAP_FCS_NONE;
2173 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2174 pi->fcs = L2CAP_FCS_CRC16;
2175}
2176
Al Viro88219a02007-07-29 00:17:25 -07002177static 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 -07002178{
2179 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2180 u16 dcid, flags;
2181 u8 rsp[64];
2182 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002183 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184
2185 dcid = __le16_to_cpu(req->dcid);
2186 flags = __le16_to_cpu(req->flags);
2187
2188 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2189
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002190 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2191 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 return -ENOENT;
2193
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002194 if (sk->sk_state != BT_CONFIG) {
2195 struct l2cap_cmd_rej rej;
2196
2197 rej.reason = cpu_to_le16(0x0002);
2198 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2199 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002200 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002201 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002202
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002203 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002204 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002205 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2206 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2207 l2cap_build_conf_rsp(sk, rsp,
2208 L2CAP_CONF_REJECT, flags), rsp);
2209 goto unlock;
2210 }
2211
2212 /* Store config. */
2213 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2214 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
2216 if (flags & 0x0001) {
2217 /* Incomplete config. Send empty response. */
2218 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002219 l2cap_build_conf_rsp(sk, rsp,
2220 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 goto unlock;
2222 }
2223
2224 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002225 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002226 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002227 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002231 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002232 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002233
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002234 /* Reset config buffer. */
2235 l2cap_pi(sk)->conf_len = 0;
2236
Marcel Holtmann876d9482007-10-20 13:35:42 +02002237 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2238 goto unlock;
2239
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002241 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002242
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002244
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002245 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002246 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002247 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002248 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2249 l2cap_ertm_init(sk);
2250
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002252 goto unlock;
2253 }
2254
2255 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002256 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002257 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002259 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002260 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 }
2262
2263unlock:
2264 bh_unlock_sock(sk);
2265 return 0;
2266}
2267
2268static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2269{
2270 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2271 u16 scid, flags, result;
2272 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002273 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
2275 scid = __le16_to_cpu(rsp->scid);
2276 flags = __le16_to_cpu(rsp->flags);
2277 result = __le16_to_cpu(rsp->result);
2278
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002279 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2280 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002282 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2283 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 return 0;
2285
2286 switch (result) {
2287 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002288 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 break;
2290
2291 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002292 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002293 char req[64];
2294
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002295 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002296 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002297 goto done;
2298 }
2299
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002300 /* throw out any old stored conf requests */
2301 result = L2CAP_CONF_SUCCESS;
2302 len = l2cap_parse_conf_rsp(sk, rsp->data,
2303 len, req, &result);
2304 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002305 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002306 goto done;
2307 }
2308
2309 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2310 L2CAP_CONF_REQ, len, req);
2311 l2cap_pi(sk)->num_conf_req++;
2312 if (result != L2CAP_CONF_SUCCESS)
2313 goto done;
2314 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 }
2316
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002317 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002318 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002320 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 goto done;
2322 }
2323
2324 if (flags & 0x01)
2325 goto done;
2326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2328
2329 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002330 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002331
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002333 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002334 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002335 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002336 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2337 l2cap_ertm_init(sk);
2338
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 l2cap_chan_ready(sk);
2340 }
2341
2342done:
2343 bh_unlock_sock(sk);
2344 return 0;
2345}
2346
2347static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2348{
2349 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2350 struct l2cap_disconn_rsp rsp;
2351 u16 dcid, scid;
2352 struct sock *sk;
2353
2354 scid = __le16_to_cpu(req->scid);
2355 dcid = __le16_to_cpu(req->dcid);
2356
2357 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2358
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002359 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2360 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 return 0;
2362
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002363 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2364 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2366
2367 sk->sk_shutdown = SHUTDOWN_MASK;
2368
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002369 /* don't delete l2cap channel if sk is owned by user */
2370 if (sock_owned_by_user(sk)) {
2371 sk->sk_state = BT_DISCONN;
2372 l2cap_sock_clear_timer(sk);
2373 l2cap_sock_set_timer(sk, HZ / 5);
2374 bh_unlock_sock(sk);
2375 return 0;
2376 }
2377
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 l2cap_chan_del(sk, ECONNRESET);
2379 bh_unlock_sock(sk);
2380
2381 l2cap_sock_kill(sk);
2382 return 0;
2383}
2384
2385static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2386{
2387 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2388 u16 dcid, scid;
2389 struct sock *sk;
2390
2391 scid = __le16_to_cpu(rsp->scid);
2392 dcid = __le16_to_cpu(rsp->dcid);
2393
2394 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2395
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002396 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2397 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 return 0;
2399
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002400 /* don't delete l2cap channel if sk is owned by user */
2401 if (sock_owned_by_user(sk)) {
2402 sk->sk_state = BT_DISCONN;
2403 l2cap_sock_clear_timer(sk);
2404 l2cap_sock_set_timer(sk, HZ / 5);
2405 bh_unlock_sock(sk);
2406 return 0;
2407 }
2408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 l2cap_chan_del(sk, 0);
2410 bh_unlock_sock(sk);
2411
2412 l2cap_sock_kill(sk);
2413 return 0;
2414}
2415
2416static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2417{
2418 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 u16 type;
2420
2421 type = __le16_to_cpu(req->type);
2422
2423 BT_DBG("type 0x%4.4x", type);
2424
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002425 if (type == L2CAP_IT_FEAT_MASK) {
2426 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002427 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002428 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2429 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2430 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002431 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002432 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2433 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002434 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002435 l2cap_send_cmd(conn, cmd->ident,
2436 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002437 } else if (type == L2CAP_IT_FIXED_CHAN) {
2438 u8 buf[12];
2439 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2440 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2441 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2442 memcpy(buf + 4, l2cap_fixed_chan, 8);
2443 l2cap_send_cmd(conn, cmd->ident,
2444 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002445 } else {
2446 struct l2cap_info_rsp rsp;
2447 rsp.type = cpu_to_le16(type);
2448 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2449 l2cap_send_cmd(conn, cmd->ident,
2450 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
2453 return 0;
2454}
2455
2456static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2457{
2458 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2459 u16 type, result;
2460
2461 type = __le16_to_cpu(rsp->type);
2462 result = __le16_to_cpu(rsp->result);
2463
2464 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2465
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002466 del_timer(&conn->info_timer);
2467
Ville Tervoadb08ed2010-08-04 09:43:33 +03002468 if (result != L2CAP_IR_SUCCESS) {
2469 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2470 conn->info_ident = 0;
2471
2472 l2cap_conn_start(conn);
2473
2474 return 0;
2475 }
2476
Marcel Holtmann984947d2009-02-06 23:35:19 +01002477 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002478 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002479
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002480 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002481 struct l2cap_info_req req;
2482 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2483
2484 conn->info_ident = l2cap_get_ident(conn);
2485
2486 l2cap_send_cmd(conn, conn->info_ident,
2487 L2CAP_INFO_REQ, sizeof(req), &req);
2488 } else {
2489 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2490 conn->info_ident = 0;
2491
2492 l2cap_conn_start(conn);
2493 }
2494 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002495 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002496 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002497
2498 l2cap_conn_start(conn);
2499 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002500
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 return 0;
2502}
2503
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002504static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002505 u16 to_multiplier)
2506{
2507 u16 max_latency;
2508
2509 if (min > max || min < 6 || max > 3200)
2510 return -EINVAL;
2511
2512 if (to_multiplier < 10 || to_multiplier > 3200)
2513 return -EINVAL;
2514
2515 if (max >= to_multiplier * 8)
2516 return -EINVAL;
2517
2518 max_latency = (to_multiplier * 8 / max) - 1;
2519 if (latency > 499 || latency > max_latency)
2520 return -EINVAL;
2521
2522 return 0;
2523}
2524
2525static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2526 struct l2cap_cmd_hdr *cmd, u8 *data)
2527{
2528 struct hci_conn *hcon = conn->hcon;
2529 struct l2cap_conn_param_update_req *req;
2530 struct l2cap_conn_param_update_rsp rsp;
2531 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002532 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002533
2534 if (!(hcon->link_mode & HCI_LM_MASTER))
2535 return -EINVAL;
2536
2537 cmd_len = __le16_to_cpu(cmd->len);
2538 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2539 return -EPROTO;
2540
2541 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002542 min = __le16_to_cpu(req->min);
2543 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002544 latency = __le16_to_cpu(req->latency);
2545 to_multiplier = __le16_to_cpu(req->to_multiplier);
2546
2547 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2548 min, max, latency, to_multiplier);
2549
2550 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002551
2552 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2553 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002554 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2555 else
2556 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2557
2558 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2559 sizeof(rsp), &rsp);
2560
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002561 if (!err)
2562 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2563
Claudio Takahaside731152011-02-11 19:28:55 -02002564 return 0;
2565}
2566
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002567static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2568 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2569{
2570 int err = 0;
2571
2572 switch (cmd->code) {
2573 case L2CAP_COMMAND_REJ:
2574 l2cap_command_rej(conn, cmd, data);
2575 break;
2576
2577 case L2CAP_CONN_REQ:
2578 err = l2cap_connect_req(conn, cmd, data);
2579 break;
2580
2581 case L2CAP_CONN_RSP:
2582 err = l2cap_connect_rsp(conn, cmd, data);
2583 break;
2584
2585 case L2CAP_CONF_REQ:
2586 err = l2cap_config_req(conn, cmd, cmd_len, data);
2587 break;
2588
2589 case L2CAP_CONF_RSP:
2590 err = l2cap_config_rsp(conn, cmd, data);
2591 break;
2592
2593 case L2CAP_DISCONN_REQ:
2594 err = l2cap_disconnect_req(conn, cmd, data);
2595 break;
2596
2597 case L2CAP_DISCONN_RSP:
2598 err = l2cap_disconnect_rsp(conn, cmd, data);
2599 break;
2600
2601 case L2CAP_ECHO_REQ:
2602 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2603 break;
2604
2605 case L2CAP_ECHO_RSP:
2606 break;
2607
2608 case L2CAP_INFO_REQ:
2609 err = l2cap_information_req(conn, cmd, data);
2610 break;
2611
2612 case L2CAP_INFO_RSP:
2613 err = l2cap_information_rsp(conn, cmd, data);
2614 break;
2615
2616 default:
2617 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2618 err = -EINVAL;
2619 break;
2620 }
2621
2622 return err;
2623}
2624
2625static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2626 struct l2cap_cmd_hdr *cmd, u8 *data)
2627{
2628 switch (cmd->code) {
2629 case L2CAP_COMMAND_REJ:
2630 return 0;
2631
2632 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002633 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002634
2635 case L2CAP_CONN_PARAM_UPDATE_RSP:
2636 return 0;
2637
2638 default:
2639 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2640 return -EINVAL;
2641 }
2642}
2643
2644static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2645 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
2647 u8 *data = skb->data;
2648 int len = skb->len;
2649 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002650 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
2652 l2cap_raw_recv(conn, skb);
2653
2654 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002655 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2657 data += L2CAP_CMD_HDR_SIZE;
2658 len -= L2CAP_CMD_HDR_SIZE;
2659
Al Viro88219a02007-07-29 00:17:25 -07002660 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Al Viro88219a02007-07-29 00:17:25 -07002662 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 -07002663
Al Viro88219a02007-07-29 00:17:25 -07002664 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 BT_DBG("corrupted command");
2666 break;
2667 }
2668
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002669 if (conn->hcon->type == LE_LINK)
2670 err = l2cap_le_sig_cmd(conn, &cmd, data);
2671 else
2672 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
2674 if (err) {
2675 struct l2cap_cmd_rej rej;
2676 BT_DBG("error %d", err);
2677
2678 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002679 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2681 }
2682
Al Viro88219a02007-07-29 00:17:25 -07002683 data += cmd_len;
2684 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 }
2686
2687 kfree_skb(skb);
2688}
2689
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002690static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2691{
2692 u16 our_fcs, rcv_fcs;
2693 int hdr_size = L2CAP_HDR_SIZE + 2;
2694
2695 if (pi->fcs == L2CAP_FCS_CRC16) {
2696 skb_trim(skb, skb->len - 2);
2697 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2698 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2699
2700 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002701 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002702 }
2703 return 0;
2704}
2705
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002706static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2707{
2708 struct l2cap_pinfo *pi = l2cap_pi(sk);
2709 u16 control = 0;
2710
2711 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002712
2713 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2714
2715 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002716 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002717 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002718 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002719 }
2720
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002721 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2722 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002723
2724 l2cap_ertm_send(sk);
2725
2726 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2727 pi->frames_sent == 0) {
2728 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002729 l2cap_send_sframe(pi, control);
2730 }
2731}
2732
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002733static 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 -03002734{
2735 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002736 struct l2cap_pinfo *pi = l2cap_pi(sk);
2737 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002738
2739 bt_cb(skb)->tx_seq = tx_seq;
2740 bt_cb(skb)->sar = sar;
2741
2742 next_skb = skb_peek(SREJ_QUEUE(sk));
2743 if (!next_skb) {
2744 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002745 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002746 }
2747
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002748 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2749 if (tx_seq_offset < 0)
2750 tx_seq_offset += 64;
2751
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002752 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002753 if (bt_cb(next_skb)->tx_seq == tx_seq)
2754 return -EINVAL;
2755
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002756 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2757 pi->buffer_seq) % 64;
2758 if (next_tx_seq_offset < 0)
2759 next_tx_seq_offset += 64;
2760
2761 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002762 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002763 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002764 }
2765
2766 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2767 break;
2768
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002769 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002770
2771 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002772
2773 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002774}
2775
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002776static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2777{
2778 struct l2cap_pinfo *pi = l2cap_pi(sk);
2779 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002780 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002781
2782 switch (control & L2CAP_CTRL_SAR) {
2783 case L2CAP_SDU_UNSEGMENTED:
2784 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2785 goto drop;
2786
2787 err = sock_queue_rcv_skb(sk, skb);
2788 if (!err)
2789 return err;
2790
2791 break;
2792
2793 case L2CAP_SDU_START:
2794 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2795 goto drop;
2796
2797 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002798
2799 if (pi->sdu_len > pi->imtu)
2800 goto disconnect;
2801
2802 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002803 if (!pi->sdu)
2804 return -ENOMEM;
2805
2806 /* pull sdu_len bytes only after alloc, because of Local Busy
2807 * condition we have to be sure that this will be executed
2808 * only once, i.e., when alloc does not fail */
2809 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002810
2811 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2812
2813 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2814 pi->partial_sdu_len = skb->len;
2815 break;
2816
2817 case L2CAP_SDU_CONTINUE:
2818 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2819 goto disconnect;
2820
2821 if (!pi->sdu)
2822 goto disconnect;
2823
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002824 pi->partial_sdu_len += skb->len;
2825 if (pi->partial_sdu_len > pi->sdu_len)
2826 goto drop;
2827
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002828 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2829
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002830 break;
2831
2832 case L2CAP_SDU_END:
2833 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2834 goto disconnect;
2835
2836 if (!pi->sdu)
2837 goto disconnect;
2838
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002839 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002840 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002841
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002842 if (pi->partial_sdu_len > pi->imtu)
2843 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002844
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002845 if (pi->partial_sdu_len != pi->sdu_len)
2846 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002847
2848 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002849 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002850
2851 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002852 if (!_skb) {
2853 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2854 return -ENOMEM;
2855 }
2856
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002857 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002858 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002860 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2861 return err;
2862 }
2863
2864 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2865 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002866
2867 kfree_skb(pi->sdu);
2868 break;
2869 }
2870
2871 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002872 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002873
2874drop:
2875 kfree_skb(pi->sdu);
2876 pi->sdu = NULL;
2877
2878disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002879 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002880 kfree_skb(skb);
2881 return 0;
2882}
2883
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002884static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002885{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002886 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002887 struct sk_buff *skb;
2888 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002889 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002890
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002891 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2892 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2893 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2894 if (err < 0) {
2895 skb_queue_head(BUSY_QUEUE(sk), skb);
2896 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002897 }
2898
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002899 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002900 }
2901
2902 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2903 goto done;
2904
2905 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2906 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2907 l2cap_send_sframe(pi, control);
2908 l2cap_pi(sk)->retry_count = 1;
2909
2910 del_timer(&pi->retrans_timer);
2911 __mod_monitor_timer();
2912
2913 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2914
2915done:
2916 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2917 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2918
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002919 BT_DBG("sk %p, Exit local busy", sk);
2920
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002921 return 0;
2922}
2923
2924static void l2cap_busy_work(struct work_struct *work)
2925{
2926 DECLARE_WAITQUEUE(wait, current);
2927 struct l2cap_pinfo *pi =
2928 container_of(work, struct l2cap_pinfo, busy_work);
2929 struct sock *sk = (struct sock *)pi;
2930 int n_tries = 0, timeo = HZ/5, err;
2931 struct sk_buff *skb;
2932
2933 lock_sock(sk);
2934
2935 add_wait_queue(sk_sleep(sk), &wait);
2936 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2937 set_current_state(TASK_INTERRUPTIBLE);
2938
2939 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2940 err = -EBUSY;
2941 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2942 break;
2943 }
2944
2945 if (!timeo)
2946 timeo = HZ/5;
2947
2948 if (signal_pending(current)) {
2949 err = sock_intr_errno(timeo);
2950 break;
2951 }
2952
2953 release_sock(sk);
2954 timeo = schedule_timeout(timeo);
2955 lock_sock(sk);
2956
2957 err = sock_error(sk);
2958 if (err)
2959 break;
2960
2961 if (l2cap_try_push_rx_skb(sk) == 0)
2962 break;
2963 }
2964
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002965 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002966 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967
2968 release_sock(sk);
2969}
2970
2971static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2972{
2973 struct l2cap_pinfo *pi = l2cap_pi(sk);
2974 int sctrl, err;
2975
2976 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2977 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2978 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002979 return l2cap_try_push_rx_skb(sk);
2980
2981
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
2983
2984 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2985 if (err >= 0) {
2986 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2987 return err;
2988 }
2989
2990 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002991 BT_DBG("sk %p, Enter local busy", sk);
2992
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
2994 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2995 __skb_queue_tail(BUSY_QUEUE(sk), skb);
2996
2997 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2998 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
2999 l2cap_send_sframe(pi, sctrl);
3000
3001 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3002
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003003 del_timer(&pi->ack_timer);
3004
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003005 queue_work(_busy_wq, &pi->busy_work);
3006
3007 return err;
3008}
3009
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003010static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003011{
3012 struct l2cap_pinfo *pi = l2cap_pi(sk);
3013 struct sk_buff *_skb;
3014 int err = -EINVAL;
3015
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003016 /*
3017 * TODO: We have to notify the userland if some data is lost with the
3018 * Streaming Mode.
3019 */
3020
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003021 switch (control & L2CAP_CTRL_SAR) {
3022 case L2CAP_SDU_UNSEGMENTED:
3023 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3024 kfree_skb(pi->sdu);
3025 break;
3026 }
3027
3028 err = sock_queue_rcv_skb(sk, skb);
3029 if (!err)
3030 return 0;
3031
3032 break;
3033
3034 case L2CAP_SDU_START:
3035 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3036 kfree_skb(pi->sdu);
3037 break;
3038 }
3039
3040 pi->sdu_len = get_unaligned_le16(skb->data);
3041 skb_pull(skb, 2);
3042
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003043 if (pi->sdu_len > pi->imtu) {
3044 err = -EMSGSIZE;
3045 break;
3046 }
3047
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003048 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3049 if (!pi->sdu) {
3050 err = -ENOMEM;
3051 break;
3052 }
3053
3054 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3055
3056 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3057 pi->partial_sdu_len = skb->len;
3058 err = 0;
3059 break;
3060
3061 case L2CAP_SDU_CONTINUE:
3062 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3063 break;
3064
3065 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3066
3067 pi->partial_sdu_len += skb->len;
3068 if (pi->partial_sdu_len > pi->sdu_len)
3069 kfree_skb(pi->sdu);
3070 else
3071 err = 0;
3072
3073 break;
3074
3075 case L2CAP_SDU_END:
3076 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3077 break;
3078
3079 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3080
3081 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3082 pi->partial_sdu_len += skb->len;
3083
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003084 if (pi->partial_sdu_len > pi->imtu)
3085 goto drop;
3086
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003087 if (pi->partial_sdu_len == pi->sdu_len) {
3088 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3089 err = sock_queue_rcv_skb(sk, _skb);
3090 if (err < 0)
3091 kfree_skb(_skb);
3092 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003093 err = 0;
3094
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003095drop:
3096 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097 break;
3098 }
3099
3100 kfree_skb(skb);
3101 return err;
3102}
3103
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003104static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3105{
3106 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003107 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003108
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003109 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003110 if (bt_cb(skb)->tx_seq != tx_seq)
3111 break;
3112
3113 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003114 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003115 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003116 l2cap_pi(sk)->buffer_seq_srej =
3117 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003118 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003119 }
3120}
3121
3122static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3123{
3124 struct l2cap_pinfo *pi = l2cap_pi(sk);
3125 struct srej_list *l, *tmp;
3126 u16 control;
3127
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003128 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003129 if (l->tx_seq == tx_seq) {
3130 list_del(&l->list);
3131 kfree(l);
3132 return;
3133 }
3134 control = L2CAP_SUPER_SELECT_REJECT;
3135 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3136 l2cap_send_sframe(pi, control);
3137 list_del(&l->list);
3138 list_add_tail(&l->list, SREJ_LIST(sk));
3139 }
3140}
3141
3142static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3143{
3144 struct l2cap_pinfo *pi = l2cap_pi(sk);
3145 struct srej_list *new;
3146 u16 control;
3147
3148 while (tx_seq != pi->expected_tx_seq) {
3149 control = L2CAP_SUPER_SELECT_REJECT;
3150 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3151 l2cap_send_sframe(pi, control);
3152
3153 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003154 new->tx_seq = pi->expected_tx_seq;
3155 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003156 list_add_tail(&new->list, SREJ_LIST(sk));
3157 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003158 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003159}
3160
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003161static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3162{
3163 struct l2cap_pinfo *pi = l2cap_pi(sk);
3164 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003165 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003166 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003167 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003168 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003169 int err = 0;
3170
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003171 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3172 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003173
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003174 if (L2CAP_CTRL_FINAL & rx_control &&
3175 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003176 del_timer(&pi->monitor_timer);
3177 if (pi->unacked_frames > 0)
3178 __mod_retrans_timer();
3179 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3180 }
3181
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003182 pi->expected_ack_seq = req_seq;
3183 l2cap_drop_acked_frames(sk);
3184
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003185 if (tx_seq == pi->expected_tx_seq)
3186 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003187
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003188 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3189 if (tx_seq_offset < 0)
3190 tx_seq_offset += 64;
3191
3192 /* invalid tx_seq */
3193 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003194 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003195 goto drop;
3196 }
3197
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003198 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3199 goto drop;
3200
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003201 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3202 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003203
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204 first = list_first_entry(SREJ_LIST(sk),
3205 struct srej_list, list);
3206 if (tx_seq == first->tx_seq) {
3207 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3208 l2cap_check_srej_gap(sk, tx_seq);
3209
3210 list_del(&first->list);
3211 kfree(first);
3212
3213 if (list_empty(SREJ_LIST(sk))) {
3214 pi->buffer_seq = pi->buffer_seq_srej;
3215 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003216 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003217 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003218 }
3219 } else {
3220 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003221
3222 /* duplicated tx_seq */
3223 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3224 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225
3226 list_for_each_entry(l, SREJ_LIST(sk), list) {
3227 if (l->tx_seq == tx_seq) {
3228 l2cap_resend_srejframe(sk, tx_seq);
3229 return 0;
3230 }
3231 }
3232 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003233 }
3234 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003235 expected_tx_seq_offset =
3236 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3237 if (expected_tx_seq_offset < 0)
3238 expected_tx_seq_offset += 64;
3239
3240 /* duplicated tx_seq */
3241 if (tx_seq_offset < expected_tx_seq_offset)
3242 goto drop;
3243
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003244 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003245
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003246 BT_DBG("sk %p, Enter SREJ", sk);
3247
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003248 INIT_LIST_HEAD(SREJ_LIST(sk));
3249 pi->buffer_seq_srej = pi->buffer_seq;
3250
3251 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003253 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3254
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003255 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3256
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003257 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003258
3259 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003260 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003261 return 0;
3262
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003263expected:
3264 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3265
3266 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003267 bt_cb(skb)->tx_seq = tx_seq;
3268 bt_cb(skb)->sar = sar;
3269 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003270 return 0;
3271 }
3272
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003273 err = l2cap_push_rx_skb(sk, skb, rx_control);
3274 if (err < 0)
3275 return 0;
3276
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003277 if (rx_control & L2CAP_CTRL_FINAL) {
3278 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3279 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003280 else
3281 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003282 }
3283
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003284 __mod_ack_timer();
3285
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003286 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3287 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003288 l2cap_send_ack(pi);
3289
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003290 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003291
3292drop:
3293 kfree_skb(skb);
3294 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003295}
3296
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003297static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003298{
3299 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003300
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003301 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3302 rx_control);
3303
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003304 pi->expected_ack_seq = __get_reqseq(rx_control);
3305 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003306
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003307 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003308 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003309 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3310 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3311 (pi->unacked_frames > 0))
3312 __mod_retrans_timer();
3313
3314 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3315 l2cap_send_srejtail(sk);
3316 } else {
3317 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003318 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003319
3320 } else if (rx_control & L2CAP_CTRL_FINAL) {
3321 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003322
3323 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3324 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003325 else
3326 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003327
3328 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003329 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3330 (pi->unacked_frames > 0))
3331 __mod_retrans_timer();
3332
3333 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003334 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003335 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003336 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003337 l2cap_ertm_send(sk);
3338 }
3339}
3340
3341static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3342{
3343 struct l2cap_pinfo *pi = l2cap_pi(sk);
3344 u8 tx_seq = __get_reqseq(rx_control);
3345
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003346 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3347
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003348 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3349
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003350 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003351 l2cap_drop_acked_frames(sk);
3352
3353 if (rx_control & L2CAP_CTRL_FINAL) {
3354 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3355 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003356 else
3357 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003358 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003359 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003360
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003361 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003362 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003363 }
3364}
3365static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3366{
3367 struct l2cap_pinfo *pi = l2cap_pi(sk);
3368 u8 tx_seq = __get_reqseq(rx_control);
3369
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003370 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3371
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003372 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3373
3374 if (rx_control & L2CAP_CTRL_POLL) {
3375 pi->expected_ack_seq = tx_seq;
3376 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003377
3378 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003379 l2cap_retransmit_one_frame(sk, tx_seq);
3380
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003381 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003382
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003383 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3384 pi->srej_save_reqseq = tx_seq;
3385 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3386 }
3387 } else if (rx_control & L2CAP_CTRL_FINAL) {
3388 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3389 pi->srej_save_reqseq == tx_seq)
3390 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3391 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003392 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003393 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003394 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003395 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3396 pi->srej_save_reqseq = tx_seq;
3397 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3398 }
3399 }
3400}
3401
3402static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3403{
3404 struct l2cap_pinfo *pi = l2cap_pi(sk);
3405 u8 tx_seq = __get_reqseq(rx_control);
3406
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003407 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3408
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3410 pi->expected_ack_seq = tx_seq;
3411 l2cap_drop_acked_frames(sk);
3412
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003413 if (rx_control & L2CAP_CTRL_POLL)
3414 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3415
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003416 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3417 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003418 if (rx_control & L2CAP_CTRL_POLL)
3419 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003420 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003421 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003422
3423 if (rx_control & L2CAP_CTRL_POLL)
3424 l2cap_send_srejtail(sk);
3425 else
3426 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003427}
3428
3429static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3430{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003431 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3432
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003433 if (L2CAP_CTRL_FINAL & rx_control &&
3434 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435 del_timer(&l2cap_pi(sk)->monitor_timer);
3436 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003437 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003439 }
3440
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003441 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3442 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003444 break;
3445
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003446 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003447 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003448 break;
3449
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003450 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003451 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003452 break;
3453
3454 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003455 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003456 break;
3457 }
3458
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003459 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003460 return 0;
3461}
3462
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003463static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3464{
3465 struct l2cap_pinfo *pi = l2cap_pi(sk);
3466 u16 control;
3467 u8 req_seq;
3468 int len, next_tx_seq_offset, req_seq_offset;
3469
3470 control = get_unaligned_le16(skb->data);
3471 skb_pull(skb, 2);
3472 len = skb->len;
3473
3474 /*
3475 * We can just drop the corrupted I-frame here.
3476 * Receiver will miss it and start proper recovery
3477 * procedures and ask retransmission.
3478 */
3479 if (l2cap_check_fcs(pi, skb))
3480 goto drop;
3481
3482 if (__is_sar_start(control) && __is_iframe(control))
3483 len -= 2;
3484
3485 if (pi->fcs == L2CAP_FCS_CRC16)
3486 len -= 2;
3487
3488 if (len > pi->mps) {
3489 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3490 goto drop;
3491 }
3492
3493 req_seq = __get_reqseq(control);
3494 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3495 if (req_seq_offset < 0)
3496 req_seq_offset += 64;
3497
3498 next_tx_seq_offset =
3499 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3500 if (next_tx_seq_offset < 0)
3501 next_tx_seq_offset += 64;
3502
3503 /* check for invalid req-seq */
3504 if (req_seq_offset > next_tx_seq_offset) {
3505 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3506 goto drop;
3507 }
3508
3509 if (__is_iframe(control)) {
3510 if (len < 0) {
3511 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3512 goto drop;
3513 }
3514
3515 l2cap_data_channel_iframe(sk, control, skb);
3516 } else {
3517 if (len != 0) {
3518 BT_ERR("%d", len);
3519 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3520 goto drop;
3521 }
3522
3523 l2cap_data_channel_sframe(sk, control, skb);
3524 }
3525
3526 return 0;
3527
3528drop:
3529 kfree_skb(skb);
3530 return 0;
3531}
3532
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3534{
3535 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003536 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003537 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003538 u8 tx_seq;
3539 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
3541 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3542 if (!sk) {
3543 BT_DBG("unknown cid 0x%4.4x", cid);
3544 goto drop;
3545 }
3546
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003547 pi = l2cap_pi(sk);
3548
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 BT_DBG("sk %p, len %d", sk, skb->len);
3550
3551 if (sk->sk_state != BT_CONNECTED)
3552 goto drop;
3553
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003554 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003555 case L2CAP_MODE_BASIC:
3556 /* If socket recv buffers overflows we drop data here
3557 * which is *bad* because L2CAP has to be reliable.
3558 * But we don't have any other choice. L2CAP doesn't
3559 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003561 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003562 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003564 if (!sock_queue_rcv_skb(sk, skb))
3565 goto done;
3566 break;
3567
3568 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003569 if (!sock_owned_by_user(sk)) {
3570 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003571 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003572 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003573 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003574 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003575
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003576 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003577
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003578 case L2CAP_MODE_STREAMING:
3579 control = get_unaligned_le16(skb->data);
3580 skb_pull(skb, 2);
3581 len = skb->len;
3582
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003583 if (l2cap_check_fcs(pi, skb))
3584 goto drop;
3585
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003586 if (__is_sar_start(control))
3587 len -= 2;
3588
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003589 if (pi->fcs == L2CAP_FCS_CRC16)
3590 len -= 2;
3591
Nathan Holstein51893f82010-06-09 15:46:25 -04003592 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003593 goto drop;
3594
3595 tx_seq = __get_txseq(control);
3596
3597 if (pi->expected_tx_seq == tx_seq)
3598 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3599 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003600 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003601
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003602 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003603
3604 goto done;
3605
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003606 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003607 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003608 break;
3609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610
3611drop:
3612 kfree_skb(skb);
3613
3614done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003615 if (sk)
3616 bh_unlock_sock(sk);
3617
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 return 0;
3619}
3620
Al Viro8e036fc2007-07-29 00:16:36 -07003621static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622{
3623 struct sock *sk;
3624
3625 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3626 if (!sk)
3627 goto drop;
3628
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003629 bh_lock_sock(sk);
3630
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 BT_DBG("sk %p, len %d", sk, skb->len);
3632
3633 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3634 goto drop;
3635
3636 if (l2cap_pi(sk)->imtu < skb->len)
3637 goto drop;
3638
3639 if (!sock_queue_rcv_skb(sk, skb))
3640 goto done;
3641
3642drop:
3643 kfree_skb(skb);
3644
3645done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003646 if (sk)
3647 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 return 0;
3649}
3650
3651static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3652{
3653 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003654 u16 cid, len;
3655 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
3657 skb_pull(skb, L2CAP_HDR_SIZE);
3658 cid = __le16_to_cpu(lh->cid);
3659 len = __le16_to_cpu(lh->len);
3660
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003661 if (len != skb->len) {
3662 kfree_skb(skb);
3663 return;
3664 }
3665
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3667
3668 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003669 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003670 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 l2cap_sig_channel(conn, skb);
3672 break;
3673
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003674 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003675 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676 skb_pull(skb, 2);
3677 l2cap_conless_channel(conn, psm, skb);
3678 break;
3679
3680 default:
3681 l2cap_data_channel(conn, cid, skb);
3682 break;
3683 }
3684}
3685
3686/* ---- L2CAP interface with lower layer (HCI) ---- */
3687
3688static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3689{
3690 int exact = 0, lm1 = 0, lm2 = 0;
3691 register struct sock *sk;
3692 struct hlist_node *node;
3693
3694 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003695 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
3697 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3698
3699 /* Find listening sockets and check their link_mode */
3700 read_lock(&l2cap_sk_list.lock);
3701 sk_for_each(sk, node, &l2cap_sk_list.head) {
3702 if (sk->sk_state != BT_LISTEN)
3703 continue;
3704
3705 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003706 lm1 |= HCI_LM_ACCEPT;
3707 if (l2cap_pi(sk)->role_switch)
3708 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003710 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3711 lm2 |= HCI_LM_ACCEPT;
3712 if (l2cap_pi(sk)->role_switch)
3713 lm2 |= HCI_LM_MASTER;
3714 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 }
3716 read_unlock(&l2cap_sk_list.lock);
3717
3718 return exact ? lm1 : lm2;
3719}
3720
3721static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3722{
Marcel Holtmann01394182006-07-03 10:02:46 +02003723 struct l2cap_conn *conn;
3724
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3726
Ville Tervoacd7d372011-02-10 22:38:49 -03003727 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003728 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
3730 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 conn = l2cap_conn_add(hcon, status);
3732 if (conn)
3733 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003734 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 l2cap_conn_del(hcon, bt_err(status));
3736
3737 return 0;
3738}
3739
Marcel Holtmann2950f212009-02-12 14:02:50 +01003740static int l2cap_disconn_ind(struct hci_conn *hcon)
3741{
3742 struct l2cap_conn *conn = hcon->l2cap_data;
3743
3744 BT_DBG("hcon %p", hcon);
3745
3746 if (hcon->type != ACL_LINK || !conn)
3747 return 0x13;
3748
3749 return conn->disc_reason;
3750}
3751
3752static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753{
3754 BT_DBG("hcon %p reason %d", hcon, reason);
3755
Ville Tervoacd7d372011-02-10 22:38:49 -03003756 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003757 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758
3759 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003760
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 return 0;
3762}
3763
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003764static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3765{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003766 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003767 return;
3768
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003769 if (encrypt == 0x00) {
3770 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3771 l2cap_sock_clear_timer(sk);
3772 l2cap_sock_set_timer(sk, HZ * 5);
3773 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3774 __l2cap_sock_close(sk, ECONNREFUSED);
3775 } else {
3776 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3777 l2cap_sock_clear_timer(sk);
3778 }
3779}
3780
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003781static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782{
3783 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003784 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786
Marcel Holtmann01394182006-07-03 10:02:46 +02003787 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003789
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 l = &conn->chan_list;
3791
3792 BT_DBG("conn %p", conn);
3793
3794 read_lock(&l->lock);
3795
3796 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3797 bh_lock_sock(sk);
3798
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003799 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3800 bh_unlock_sock(sk);
3801 continue;
3802 }
3803
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003804 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003805 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003806 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003807 bh_unlock_sock(sk);
3808 continue;
3809 }
3810
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003811 if (sk->sk_state == BT_CONNECT) {
3812 if (!status) {
3813 struct l2cap_conn_req req;
3814 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3815 req.psm = l2cap_pi(sk)->psm;
3816
3817 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003818 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003819
3820 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3821 L2CAP_CONN_REQ, sizeof(req), &req);
3822 } else {
3823 l2cap_sock_clear_timer(sk);
3824 l2cap_sock_set_timer(sk, HZ / 10);
3825 }
3826 } else if (sk->sk_state == BT_CONNECT2) {
3827 struct l2cap_conn_rsp rsp;
3828 __u16 result;
3829
3830 if (!status) {
3831 sk->sk_state = BT_CONFIG;
3832 result = L2CAP_CR_SUCCESS;
3833 } else {
3834 sk->sk_state = BT_DISCONN;
3835 l2cap_sock_set_timer(sk, HZ / 10);
3836 result = L2CAP_CR_SEC_BLOCK;
3837 }
3838
3839 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3840 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3841 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003842 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003843 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3844 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 }
3846
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 bh_unlock_sock(sk);
3848 }
3849
3850 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003851
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 return 0;
3853}
3854
3855static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3856{
3857 struct l2cap_conn *conn = hcon->l2cap_data;
3858
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003859 if (!conn)
3860 conn = l2cap_conn_add(hcon, 0);
3861
3862 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 goto drop;
3864
3865 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3866
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003867 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003869 struct sock *sk;
3870 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 int len;
3872
3873 if (conn->rx_len) {
3874 BT_ERR("Unexpected start frame (len %d)", skb->len);
3875 kfree_skb(conn->rx_skb);
3876 conn->rx_skb = NULL;
3877 conn->rx_len = 0;
3878 l2cap_conn_unreliable(conn, ECOMM);
3879 }
3880
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003881 /* Start fragment always begin with Basic L2CAP header */
3882 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 BT_ERR("Frame is too short (len %d)", skb->len);
3884 l2cap_conn_unreliable(conn, ECOMM);
3885 goto drop;
3886 }
3887
3888 hdr = (struct l2cap_hdr *) skb->data;
3889 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003890 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
3892 if (len == skb->len) {
3893 /* Complete frame received */
3894 l2cap_recv_frame(conn, skb);
3895 return 0;
3896 }
3897
3898 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3899
3900 if (skb->len > len) {
3901 BT_ERR("Frame is too long (len %d, expected len %d)",
3902 skb->len, len);
3903 l2cap_conn_unreliable(conn, ECOMM);
3904 goto drop;
3905 }
3906
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003907 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3908
3909 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3910 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3911 len, l2cap_pi(sk)->imtu);
3912 bh_unlock_sock(sk);
3913 l2cap_conn_unreliable(conn, ECOMM);
3914 goto drop;
3915 }
3916
3917 if (sk)
3918 bh_unlock_sock(sk);
3919
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003921 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3922 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 goto drop;
3924
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003925 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003926 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 conn->rx_len = len - skb->len;
3928 } else {
3929 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3930
3931 if (!conn->rx_len) {
3932 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3933 l2cap_conn_unreliable(conn, ECOMM);
3934 goto drop;
3935 }
3936
3937 if (skb->len > conn->rx_len) {
3938 BT_ERR("Fragment is too long (len %d, expected %d)",
3939 skb->len, conn->rx_len);
3940 kfree_skb(conn->rx_skb);
3941 conn->rx_skb = NULL;
3942 conn->rx_len = 0;
3943 l2cap_conn_unreliable(conn, ECOMM);
3944 goto drop;
3945 }
3946
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003947 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003948 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 conn->rx_len -= skb->len;
3950
3951 if (!conn->rx_len) {
3952 /* Complete frame received */
3953 l2cap_recv_frame(conn, conn->rx_skb);
3954 conn->rx_skb = NULL;
3955 }
3956 }
3957
3958drop:
3959 kfree_skb(skb);
3960 return 0;
3961}
3962
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003963static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964{
3965 struct sock *sk;
3966 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
3968 read_lock_bh(&l2cap_sk_list.lock);
3969
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003970 sk_for_each(sk, node, &l2cap_sk_list.head) {
3971 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003973 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 +01003974 batostr(&bt_sk(sk)->src),
3975 batostr(&bt_sk(sk)->dst),
3976 sk->sk_state, __le16_to_cpu(pi->psm),
3977 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003978 pi->imtu, pi->omtu, pi->sec_level,
3979 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003983
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003984 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985}
3986
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003987static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3988{
3989 return single_open(file, l2cap_debugfs_show, inode->i_private);
3990}
3991
3992static const struct file_operations l2cap_debugfs_fops = {
3993 .open = l2cap_debugfs_open,
3994 .read = seq_read,
3995 .llseek = seq_lseek,
3996 .release = single_release,
3997};
3998
3999static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001static struct hci_proto l2cap_hci_proto = {
4002 .name = "L2CAP",
4003 .id = HCI_PROTO_L2CAP,
4004 .connect_ind = l2cap_connect_ind,
4005 .connect_cfm = l2cap_connect_cfm,
4006 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004007 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004008 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 .recv_acldata = l2cap_recv_acldata
4010};
4011
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004012int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013{
4014 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004015
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004016 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 if (err < 0)
4018 return err;
4019
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004020 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004021 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004022 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 goto error;
4024 }
4025
4026 err = hci_register_proto(&l2cap_hci_proto);
4027 if (err < 0) {
4028 BT_ERR("L2CAP protocol registration failed");
4029 bt_sock_unregister(BTPROTO_L2CAP);
4030 goto error;
4031 }
4032
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004033 if (bt_debugfs) {
4034 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4035 bt_debugfs, NULL, &l2cap_debugfs_fops);
4036 if (!l2cap_debugfs)
4037 BT_ERR("Failed to create L2CAP debug file");
4038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040 return 0;
4041
4042error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004043 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004044 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 return err;
4046}
4047
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004048void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004050 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004052 flush_workqueue(_busy_wq);
4053 destroy_workqueue(_busy_wq);
4054
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4056 BT_ERR("L2CAP protocol unregistration failed");
4057
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004058 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059}
4060
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004061module_param(disable_ertm, bool, 0644);
4062MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");