blob: dd726bdd6e0201b7eb327ce4182a5a66132e51ac [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. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. 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);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030083 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030084 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030086 return NULL;
87
Marcel Holtmann01394182006-07-03 10:02:46 +020088}
89
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030090static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
94 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030095 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020097 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020099}
100
101/* Find channel with given SCID.
102 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300103static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200104{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300105 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106
107 read_lock(&conn->chan_lock);
108 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300109 if (c)
110 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300111 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113}
114
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200116{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300117 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118
119 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300120 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124}
125
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200127{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300128 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129
130 read_lock(&conn->chan_lock);
131 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300132 if (c)
133 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300135 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200136}
137
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300138static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200139{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300140 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200141
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300143 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200144 return cid;
145 }
146
147 return 0;
148}
149
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300150struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200151{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200153
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
155 if (!chan)
156 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200157
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300158 chan->sk = sk;
159
160 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200161}
162
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300163static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200164{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200166
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300167 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300168 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200169
Marcel Holtmann2950f212009-02-12 14:02:50 +0100170 conn->disc_reason = 0x13;
171
Marcel Holtmann01394182006-07-03 10:02:46 +0200172 l2cap_pi(sk)->conn = conn;
173
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300174 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300175 if (conn->hcon->type == LE_LINK) {
176 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300177 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300178 chan->scid = L2CAP_CID_LE_DATA;
179 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300180 } else {
181 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300182 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300183 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300184 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200185 } else if (sk->sk_type == SOCK_DGRAM) {
186 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300187 chan->scid = L2CAP_CID_CONN_LESS;
188 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300189 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200190 } else {
191 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300192 chan->scid = L2CAP_CID_SIGNALING;
193 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300194 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200195 }
196
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300197 sock_hold(sk);
198
199 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200200}
201
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900202/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200203 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300204void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200205{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200207 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
208 struct sock *parent = bt_sk(sk)->parent;
209
210 l2cap_sock_clear_timer(sk);
211
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300212 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200213
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900214 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300215 /* Delete from channel list */
216 write_lock_bh(&conn->chan_lock);
217 list_del(&chan->list);
218 write_unlock_bh(&conn->chan_lock);
219 __sock_put(sk);
220
Marcel Holtmann01394182006-07-03 10:02:46 +0200221 l2cap_pi(sk)->conn = NULL;
222 hci_conn_put(conn->hcon);
223 }
224
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200225 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200226 sock_set_flag(sk, SOCK_ZAPPED);
227
228 if (err)
229 sk->sk_err = err;
230
231 if (parent) {
232 bt_accept_unlink(sk);
233 parent->sk_data_ready(parent, 0);
234 } else
235 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300236
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300237 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
238 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300239 goto free;
240
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300241 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300242
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300243 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300244 struct srej_list *l, *tmp;
245
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300246 del_timer(&chan->retrans_timer);
247 del_timer(&chan->monitor_timer);
248 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300249
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300250 skb_queue_purge(&chan->srej_q);
251 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300252
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300253 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254 list_del(&l->list);
255 kfree(l);
256 }
257 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300258
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300259free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200261}
262
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300263static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530264{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300265 struct sock *sk = chan->sk;
266
Johan Hedberg8556edd32011-01-19 12:06:50 +0530267 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300268 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530269 case BT_SECURITY_HIGH:
270 return HCI_AT_DEDICATED_BONDING_MITM;
271 case BT_SECURITY_MEDIUM:
272 return HCI_AT_DEDICATED_BONDING;
273 default:
274 return HCI_AT_NO_BONDING;
275 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300276 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300277 if (chan->sec_level == BT_SECURITY_LOW)
278 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530279
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300280 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530281 return HCI_AT_NO_BONDING_MITM;
282 else
283 return HCI_AT_NO_BONDING;
284 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300285 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530286 case BT_SECURITY_HIGH:
287 return HCI_AT_GENERAL_BONDING_MITM;
288 case BT_SECURITY_MEDIUM:
289 return HCI_AT_GENERAL_BONDING;
290 default:
291 return HCI_AT_NO_BONDING;
292 }
293 }
294}
295
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300297static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300299 struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300302 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100303
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300304 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200305}
306
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200307u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200308{
309 u8 id;
310
311 /* Get next available identificator.
312 * 1 - 128 are used by kernel.
313 * 129 - 199 are reserved.
314 * 200 - 254 are used by utilities like l2ping, etc.
315 */
316
317 spin_lock_bh(&conn->lock);
318
319 if (++conn->tx_ident > 128)
320 conn->tx_ident = 1;
321
322 id = conn->tx_ident;
323
324 spin_unlock_bh(&conn->lock);
325
326 return id;
327}
328
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200329void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200330{
331 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200332 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200333
334 BT_DBG("code 0x%2.2x", code);
335
336 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300337 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200338
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200339 if (lmp_no_flush_capable(conn->hcon->hdev))
340 flags = ACL_START_NO_FLUSH;
341 else
342 flags = ACL_START;
343
344 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200345}
346
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300347static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300348{
349 struct sk_buff *skb;
350 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300351 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300352 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300353 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300354 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200355 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300357 if (sk->sk_state != BT_CONNECTED)
358 return;
359
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300360 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300362
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300363 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300364
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300365 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300366 control |= L2CAP_CTRL_FRAME_TYPE;
367
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300368 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300369 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300370 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300371 }
372
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300373 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300374 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300375 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300376 }
377
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300378 skb = bt_skb_alloc(count, GFP_ATOMIC);
379 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300380 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300381
382 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300383 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300384 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385 put_unaligned_le16(control, skb_put(skb, 2));
386
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300387 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 u16 fcs = crc16(0, (u8 *)lh, count - 2);
389 put_unaligned_le16(fcs, skb_put(skb, 2));
390 }
391
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200392 if (lmp_no_flush_capable(conn->hcon->hdev))
393 flags = ACL_START_NO_FLUSH;
394 else
395 flags = ACL_START;
396
397 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300398}
399
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300400static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300401{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300402 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300403 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300404 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300405 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300406 control |= L2CAP_SUPER_RCV_READY;
407
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300408 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300410 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300411}
412
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300413static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300414{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300415 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300416}
417
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300418static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200419{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300420 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200421 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
422
423 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100424 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
425 return;
426
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300427 if (l2cap_check_security(chan) &&
428 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200429 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300430 req.scid = cpu_to_le16(chan->scid);
431 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300433 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300434 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300436 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
437 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439 } else {
440 struct l2cap_info_req req;
441 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
442
443 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
444 conn->info_ident = l2cap_get_ident(conn);
445
446 mod_timer(&conn->info_timer, jiffies +
447 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
448
449 l2cap_send_cmd(conn, conn->info_ident,
450 L2CAP_INFO_REQ, sizeof(req), &req);
451 }
452}
453
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300454static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
455{
456 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300457 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
459
460 switch (mode) {
461 case L2CAP_MODE_ERTM:
462 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
463 case L2CAP_MODE_STREAMING:
464 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
465 default:
466 return 0x00;
467 }
468}
469
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300470void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 struct l2cap_disconn_req req;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 if (!conn)
476 return;
477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 sk = chan->sk;
479
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300480 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300481 del_timer(&chan->retrans_timer);
482 del_timer(&chan->monitor_timer);
483 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300484 }
485
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300486 req.dcid = cpu_to_le16(chan->dcid);
487 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 l2cap_send_cmd(conn, l2cap_get_ident(conn),
489 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300490
491 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300492 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300493}
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496static void l2cap_conn_start(struct l2cap_conn *conn)
497{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300498 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499
500 BT_DBG("conn %p", conn);
501
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300502 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300504 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300505 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300506
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200507 bh_lock_sock(sk);
508
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300509 if (sk->sk_type != SOCK_SEQPACKET &&
510 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200511 bh_unlock_sock(sk);
512 continue;
513 }
514
515 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300516 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300517
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300518 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300519 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 bh_unlock_sock(sk);
521 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200522 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300523
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300524 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300526 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300527 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300528 /* __l2cap_sock_close() calls list_del(chan)
529 * so release the lock */
530 read_unlock_bh(&conn->chan_lock);
531 __l2cap_sock_close(sk, ECONNRESET);
532 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300533 bh_unlock_sock(sk);
534 continue;
535 }
536
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300537 req.scid = cpu_to_le16(chan->scid);
538 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300539
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300540 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300541 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300542
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300543 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
544 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300545
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200546 } else if (sk->sk_state == BT_CONNECT2) {
547 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300548 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300549 rsp.scid = cpu_to_le16(chan->dcid);
550 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200551
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300552 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100553 if (bt_sk(sk)->defer_setup) {
554 struct sock *parent = bt_sk(sk)->parent;
555 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
556 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
557 parent->sk_data_ready(parent, 0);
558
559 } else {
560 sk->sk_state = BT_CONFIG;
561 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
562 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
563 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200564 } else {
565 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
566 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
567 }
568
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300569 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
570 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300571
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300572 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573 rsp.result != L2CAP_CR_SUCCESS) {
574 bh_unlock_sock(sk);
575 continue;
576 }
577
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300578 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300579 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300580 l2cap_build_conf_req(chan, buf), buf);
581 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200582 }
583
584 bh_unlock_sock(sk);
585 }
586
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300587 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200588}
589
Ville Tervob62f3282011-02-10 22:38:50 -0300590/* Find socket with cid and source bdaddr.
591 * Returns closest match, locked.
592 */
593static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
594{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300595 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300596 struct hlist_node *node;
597
598 read_lock(&l2cap_sk_list.lock);
599
600 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300601 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
602
Ville Tervob62f3282011-02-10 22:38:50 -0300603 if (state && sk->sk_state != state)
604 continue;
605
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300606 if (chan->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300607 /* 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 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300616
Ville Tervob62f3282011-02-10 22:38:50 -0300617 read_unlock(&l2cap_sk_list.lock);
618
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300619 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300620}
621
622static void l2cap_le_conn_ready(struct l2cap_conn *conn)
623{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300624 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300625 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300626
627 BT_DBG("");
628
629 /* Check if we have socket listening on cid */
630 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
631 conn->src);
632 if (!parent)
633 return;
634
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300635 bh_lock_sock(parent);
636
Ville Tervob62f3282011-02-10 22:38:50 -0300637 /* 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
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300653 l2cap_pi(sk)->chan = chan;
654
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300655 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300656
657 hci_conn_hold(conn->hcon);
658
659 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300660
Ville Tervob62f3282011-02-10 22:38:50 -0300661 bacpy(&bt_sk(sk)->src, conn->src);
662 bacpy(&bt_sk(sk)->dst, conn->dst);
663
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300664 bt_accept_enqueue(parent, sk);
665
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300666 __l2cap_chan_add(conn, chan);
667
Ville Tervob62f3282011-02-10 22:38:50 -0300668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300707 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300727 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300833 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 if (state && sk->sk_state != state)
836 continue;
837
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300838 if (chan->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 /* Exact match. */
840 if (!bacmp(&bt_sk(sk)->src, src))
841 break;
842
843 /* Closest match */
844 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
845 sk1 = sk;
846 }
847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000850
851 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852}
853
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300854int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300856 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 bdaddr_t *src = &bt_sk(sk)->src;
858 bdaddr_t *dst = &bt_sk(sk)->dst;
859 struct l2cap_conn *conn;
860 struct hci_conn *hcon;
861 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200862 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200863 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100865 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300866 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300868 hdev = hci_get_route(dst, src);
869 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return -EHOSTUNREACH;
871
872 hci_dev_lock_bh(hdev);
873
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300874 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200875
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300876 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300878 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300879 else
880 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300881 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300882
Ville Tervo30e76272011-02-22 16:10:53 -0300883 if (IS_ERR(hcon)) {
884 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 conn = l2cap_conn_add(hcon, 0);
889 if (!conn) {
890 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300891 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 goto done;
893 }
894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 /* Update source addr of the socket */
896 bacpy(src, conn->src);
897
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300898 l2cap_chan_add(conn, chan);
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 sk->sk_state = BT_CONNECT;
901 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
902
903 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300904 if (sk->sk_type != SOCK_SEQPACKET &&
905 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300907 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +0530908 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200909 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300910 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 }
912
Ville Tervo30e76272011-02-22 16:10:53 -0300913 err = 0;
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915done:
916 hci_dev_unlock_bh(hdev);
917 hci_dev_put(hdev);
918 return err;
919}
920
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200921int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300922{
923 DECLARE_WAITQUEUE(wait, current);
924 int err = 0;
925 int timeo = HZ/5;
926
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200927 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300928 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929 set_current_state(TASK_INTERRUPTIBLE);
930
931 if (!timeo)
932 timeo = HZ/5;
933
934 if (signal_pending(current)) {
935 err = sock_intr_errno(timeo);
936 break;
937 }
938
939 release_sock(sk);
940 timeo = schedule_timeout(timeo);
941 lock_sock(sk);
942
943 err = sock_error(sk);
944 if (err)
945 break;
946 }
947 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200948 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300949 return err;
950}
951
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300952static void l2cap_monitor_timeout(unsigned long arg)
953{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300954 struct l2cap_chan *chan = (void *) arg;
955 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300956
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300957 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300958
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300959 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300960 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300961 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200962 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963 return;
964 }
965
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300966 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300967 __mod_monitor_timer();
968
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300969 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300970 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300971}
972
973static void l2cap_retrans_timeout(unsigned long arg)
974{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300975 struct l2cap_chan *chan = (void *) arg;
976 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300977
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300978 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300979
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300980 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300981 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300982 __mod_monitor_timer();
983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300984 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300985
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300986 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300987 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300988}
989
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300990static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300991{
992 struct sk_buff *skb;
993
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300994 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300995 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300996 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300997 break;
998
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300999 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001000 kfree_skb(skb);
1001
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001002 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001003 }
1004
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001005 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001006 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001007}
1008
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001009void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001011 struct sock *sk = chan->sk;
1012 struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001013 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001014
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001015 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001016
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001017 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001018 flags = ACL_START_NO_FLUSH;
1019 else
1020 flags = ACL_START;
1021
1022 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001023}
1024
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001025void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001026{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001027 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001028 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001030 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001032 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001033 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001035 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1037 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001038 }
1039
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001040 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001042 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001043 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001044}
1045
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001048 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001049 struct l2cap_pinfo *pi = l2cap_pi(sk);
1050 struct sk_buff *skb, *tx_skb;
1051 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001053 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001054 if (!skb)
1055 return;
1056
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001058 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001060
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001061 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001062 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001063
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001064 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001066 if (chan->remote_max_tx &&
1067 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001068 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001069 return;
1070 }
1071
1072 tx_skb = skb_clone(skb, GFP_ATOMIC);
1073 bt_cb(skb)->retries++;
1074 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001075 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001077 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001079 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001080 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001081
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001082 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001084
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001085 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1086
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001087 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001088 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1089 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1090 }
1091
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001092 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001093}
1094
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001095int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001096{
1097 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001098 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001099 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001100 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001101 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001102
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001103 if (sk->sk_state != BT_CONNECTED)
1104 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001105
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001106 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001107
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001108 if (chan->remote_max_tx &&
1109 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001110 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001111 break;
1112 }
1113
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001114 tx_skb = skb_clone(skb, GFP_ATOMIC);
1115
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001116 bt_cb(skb)->retries++;
1117
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001118 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001119 control &= L2CAP_CTRL_SAR;
1120
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001121 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001123 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001124 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001125 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1126 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001127 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1128
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001129
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001130 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001131 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1132 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1133 }
1134
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001135 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001136
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001137 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001138
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001139 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1140 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001141
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301142 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001143 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301144
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001145 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001146
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001147 if (skb_queue_is_last(&chan->tx_q, skb))
1148 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001149 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001150 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001151
1152 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001153 }
1154
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001155 return nsent;
1156}
1157
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001158static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001159{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001160 int ret;
1161
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001162 if (!skb_queue_empty(&chan->tx_q))
1163 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001164
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001165 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001166 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001167 return ret;
1168}
1169
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001170static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001171{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001172 u16 control = 0;
1173
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001174 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001178 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1179 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001180 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001182
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001183 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001184 return;
1185
1186 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001187 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001188}
1189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001190static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001191{
1192 struct srej_list *tail;
1193 u16 control;
1194
1195 control = L2CAP_SUPER_SELECT_REJECT;
1196 control |= L2CAP_CTRL_FINAL;
1197
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001198 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001199 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1200
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001201 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001202}
1203
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204static 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 -07001205{
1206 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207 struct sk_buff **frag;
1208 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001210 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001211 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 sent += count;
1214 len -= count;
1215
1216 /* Continuation fragments (no L2CAP header) */
1217 frag = &skb_shinfo(skb)->frag_list;
1218 while (len) {
1219 count = min_t(unsigned int, conn->mtu, len);
1220
1221 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1222 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001223 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001224 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1225 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227 sent += count;
1228 len -= count;
1229
1230 frag = &(*frag)->next;
1231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001234}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001236struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001237{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001238 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1240 struct sk_buff *skb;
1241 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1242 struct l2cap_hdr *lh;
1243
1244 BT_DBG("sk %p len %d", sk, (int)len);
1245
1246 count = min_t(unsigned int, (conn->mtu - hlen), len);
1247 skb = bt_skb_send_alloc(sk, count + hlen,
1248 msg->msg_flags & MSG_DONTWAIT, &err);
1249 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001250 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251
1252 /* Create L2CAP header */
1253 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001254 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001256 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001257
1258 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1259 if (unlikely(err < 0)) {
1260 kfree_skb(skb);
1261 return ERR_PTR(err);
1262 }
1263 return skb;
1264}
1265
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001266struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001267{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001268 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001269 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1270 struct sk_buff *skb;
1271 int err, count, hlen = L2CAP_HDR_SIZE;
1272 struct l2cap_hdr *lh;
1273
1274 BT_DBG("sk %p len %d", sk, (int)len);
1275
1276 count = min_t(unsigned int, (conn->mtu - hlen), len);
1277 skb = bt_skb_send_alloc(sk, count + hlen,
1278 msg->msg_flags & MSG_DONTWAIT, &err);
1279 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001280 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001281
1282 /* Create L2CAP header */
1283 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001284 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001285 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1286
1287 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1288 if (unlikely(err < 0)) {
1289 kfree_skb(skb);
1290 return ERR_PTR(err);
1291 }
1292 return skb;
1293}
1294
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001295struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001296{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001297 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1299 struct sk_buff *skb;
1300 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1301 struct l2cap_hdr *lh;
1302
1303 BT_DBG("sk %p len %d", sk, (int)len);
1304
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001305 if (!conn)
1306 return ERR_PTR(-ENOTCONN);
1307
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001308 if (sdulen)
1309 hlen += 2;
1310
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001311 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001312 hlen += 2;
1313
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001314 count = min_t(unsigned int, (conn->mtu - hlen), len);
1315 skb = bt_skb_send_alloc(sk, count + hlen,
1316 msg->msg_flags & MSG_DONTWAIT, &err);
1317 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001318 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001319
1320 /* Create L2CAP header */
1321 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001322 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001323 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1324 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001325 if (sdulen)
1326 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001327
1328 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1329 if (unlikely(err < 0)) {
1330 kfree_skb(skb);
1331 return ERR_PTR(err);
1332 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001333
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001334 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001335 put_unaligned_le16(0, skb_put(skb, 2));
1336
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001337 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001338 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001341int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001342{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001343 struct sk_buff *skb;
1344 struct sk_buff_head sar_queue;
1345 u16 control;
1346 size_t size = 0;
1347
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001348 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001350 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351 if (IS_ERR(skb))
1352 return PTR_ERR(skb);
1353
1354 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001355 len -= chan->remote_mps;
1356 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357
1358 while (len > 0) {
1359 size_t buflen;
1360
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001361 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001362 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001363 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001364 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001365 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 buflen = len;
1367 }
1368
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001369 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001370 if (IS_ERR(skb)) {
1371 skb_queue_purge(&sar_queue);
1372 return PTR_ERR(skb);
1373 }
1374
1375 __skb_queue_tail(&sar_queue, skb);
1376 len -= buflen;
1377 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001379 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1380 if (chan->tx_send_head == NULL)
1381 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001382
1383 return size;
1384}
1385
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386static void l2cap_chan_ready(struct sock *sk)
1387{
1388 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001389 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
1391 BT_DBG("sk %p, parent %p", sk, parent);
1392
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001393 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 l2cap_sock_clear_timer(sk);
1395
1396 if (!parent) {
1397 /* Outgoing channel.
1398 * Wake up socket sleeping on connect.
1399 */
1400 sk->sk_state = BT_CONNECTED;
1401 sk->sk_state_change(sk);
1402 } else {
1403 /* Incoming channel.
1404 * Wake up socket sleeping on accept.
1405 */
1406 parent->sk_data_ready(parent, 0);
1407 }
1408}
1409
1410/* Copy frame to all raw sockets on that connection */
1411static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1412{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001414 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 BT_DBG("conn %p", conn);
1417
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001418 read_lock(&conn->chan_lock);
1419 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001420 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 if (sk->sk_type != SOCK_RAW)
1422 continue;
1423
1424 /* Don't send frame to the socket it came from */
1425 if (skb->sk == sk)
1426 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001427 nskb = skb_clone(skb, GFP_ATOMIC);
1428 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 continue;
1430
1431 if (sock_queue_rcv_skb(sk, nskb))
1432 kfree_skb(nskb);
1433 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001434 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435}
1436
1437/* ---- L2CAP signalling commands ---- */
1438static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1439 u8 code, u8 ident, u16 dlen, void *data)
1440{
1441 struct sk_buff *skb, **frag;
1442 struct l2cap_cmd_hdr *cmd;
1443 struct l2cap_hdr *lh;
1444 int len, count;
1445
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001446 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1447 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1450 count = min_t(unsigned int, conn->mtu, len);
1451
1452 skb = bt_skb_alloc(count, GFP_ATOMIC);
1453 if (!skb)
1454 return NULL;
1455
1456 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001457 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001458
1459 if (conn->hcon->type == LE_LINK)
1460 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1461 else
1462 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1465 cmd->code = code;
1466 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001467 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469 if (dlen) {
1470 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1471 memcpy(skb_put(skb, count), data, count);
1472 data += count;
1473 }
1474
1475 len -= skb->len;
1476
1477 /* Continuation fragments (no L2CAP header) */
1478 frag = &skb_shinfo(skb)->frag_list;
1479 while (len) {
1480 count = min_t(unsigned int, conn->mtu, len);
1481
1482 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1483 if (!*frag)
1484 goto fail;
1485
1486 memcpy(skb_put(*frag, count), data, count);
1487
1488 len -= count;
1489 data += count;
1490
1491 frag = &(*frag)->next;
1492 }
1493
1494 return skb;
1495
1496fail:
1497 kfree_skb(skb);
1498 return NULL;
1499}
1500
1501static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1502{
1503 struct l2cap_conf_opt *opt = *ptr;
1504 int len;
1505
1506 len = L2CAP_CONF_OPT_SIZE + opt->len;
1507 *ptr += len;
1508
1509 *type = opt->type;
1510 *olen = opt->len;
1511
1512 switch (opt->len) {
1513 case 1:
1514 *val = *((u8 *) opt->val);
1515 break;
1516
1517 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001518 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 break;
1520
1521 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001522 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 break;
1524
1525 default:
1526 *val = (unsigned long) opt->val;
1527 break;
1528 }
1529
1530 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1531 return len;
1532}
1533
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1535{
1536 struct l2cap_conf_opt *opt = *ptr;
1537
1538 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1539
1540 opt->type = type;
1541 opt->len = len;
1542
1543 switch (len) {
1544 case 1:
1545 *((u8 *) opt->val) = val;
1546 break;
1547
1548 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001549 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 break;
1551
1552 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001553 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 break;
1555
1556 default:
1557 memcpy(opt->val, (void *) val, len);
1558 break;
1559 }
1560
1561 *ptr += L2CAP_CONF_OPT_SIZE + len;
1562}
1563
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001564static void l2cap_ack_timeout(unsigned long arg)
1565{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001566 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001567
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001568 bh_lock_sock(chan->sk);
1569 l2cap_send_ack(chan);
1570 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001571}
1572
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001574{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575 struct sock *sk = chan->sk;
1576
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001577 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001578 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001579 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001580 chan->num_acked = 0;
1581 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001582
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001583 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1584 (unsigned long) chan);
1585 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1586 (unsigned long) chan);
1587 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001588
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001589 skb_queue_head_init(&chan->srej_q);
1590 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001591
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001592 INIT_LIST_HEAD(&chan->srej_l);
1593
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001594 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001595
1596 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001597}
1598
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001599static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1600{
1601 switch (mode) {
1602 case L2CAP_MODE_STREAMING:
1603 case L2CAP_MODE_ERTM:
1604 if (l2cap_mode_supported(mode, remote_feat_mask))
1605 return mode;
1606 /* fall through */
1607 default:
1608 return L2CAP_MODE_BASIC;
1609 }
1610}
1611
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001612static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001614 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001616 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 void *ptr = req->data;
1618
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001619 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001621 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001622 goto done;
1623
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001624 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001625 case L2CAP_MODE_STREAMING:
1626 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001627 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001628 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001629
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001630 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001631 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001632 chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001633 break;
1634 }
1635
1636done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001637 if (chan->imtu != L2CAP_DEFAULT_MTU)
1638 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001639
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001640 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001641 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001642 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1643 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1644 break;
1645
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001646 rfc.mode = L2CAP_MODE_BASIC;
1647 rfc.txwin_size = 0;
1648 rfc.max_transmit = 0;
1649 rfc.retrans_timeout = 0;
1650 rfc.monitor_timeout = 0;
1651 rfc.max_pdu_size = 0;
1652
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001653 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1654 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001655 break;
1656
1657 case L2CAP_MODE_ERTM:
1658 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001659 rfc.txwin_size = chan->tx_win;
1660 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001661 rfc.retrans_timeout = 0;
1662 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001663 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001664 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001665 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001666
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001667 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1668 (unsigned long) &rfc);
1669
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001670 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1671 break;
1672
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001673 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001674 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001675 chan->fcs = L2CAP_FCS_NONE;
1676 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001677 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001678 break;
1679
1680 case L2CAP_MODE_STREAMING:
1681 rfc.mode = L2CAP_MODE_STREAMING;
1682 rfc.txwin_size = 0;
1683 rfc.max_transmit = 0;
1684 rfc.retrans_timeout = 0;
1685 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001686 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001687 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001688 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001689
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001690 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1691 (unsigned long) &rfc);
1692
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001693 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1694 break;
1695
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001696 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001697 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001698 chan->fcs = L2CAP_FCS_NONE;
1699 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001700 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001701 break;
1702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001704 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001705 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 return ptr - data;
1708}
1709
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001710static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001712 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001713 struct l2cap_conf_rsp *rsp = data;
1714 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001715 void *req = chan->conf_req;
1716 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001717 int type, hint, olen;
1718 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001719 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001720 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001721 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001723 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001724
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001725 while (len >= L2CAP_CONF_OPT_SIZE) {
1726 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001728 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001729 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001730
1731 switch (type) {
1732 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001733 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001734 break;
1735
1736 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001737 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001738 break;
1739
1740 case L2CAP_CONF_QOS:
1741 break;
1742
Marcel Holtmann6464f352007-10-20 13:39:51 +02001743 case L2CAP_CONF_RFC:
1744 if (olen == sizeof(rfc))
1745 memcpy(&rfc, (void *) val, olen);
1746 break;
1747
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001748 case L2CAP_CONF_FCS:
1749 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001750 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001751
1752 break;
1753
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001754 default:
1755 if (hint)
1756 break;
1757
1758 result = L2CAP_CONF_UNKNOWN;
1759 *((u8 *) ptr++) = type;
1760 break;
1761 }
1762 }
1763
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001764 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001765 goto done;
1766
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001767 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001768 case L2CAP_MODE_STREAMING:
1769 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001770 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001771 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001772 pi->conn->feat_mask);
1773 break;
1774 }
1775
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001776 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001777 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001778
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001779 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 }
1781
1782done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001783 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001785 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001786
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001787 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001788 return -ECONNREFUSED;
1789
1790 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1791 sizeof(rfc), (unsigned long) &rfc);
1792 }
1793
1794
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001795 if (result == L2CAP_CONF_SUCCESS) {
1796 /* Configure output options and let the other side know
1797 * which ones we don't like. */
1798
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001799 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1800 result = L2CAP_CONF_UNACCEPT;
1801 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001802 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001803 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001804 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001805 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001806
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001807 switch (rfc.mode) {
1808 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001809 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001810 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001811 break;
1812
1813 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001814 chan->remote_tx_win = rfc.txwin_size;
1815 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001816
1817 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1818 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001819
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001820 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001821
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001822 rfc.retrans_timeout =
1823 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1824 rfc.monitor_timeout =
1825 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001826
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001827 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001828
1829 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1830 sizeof(rfc), (unsigned long) &rfc);
1831
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001832 break;
1833
1834 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001835 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1836 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001837
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001838 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001839
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001840 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001841
1842 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1843 sizeof(rfc), (unsigned long) &rfc);
1844
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001845 break;
1846
1847 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001848 result = L2CAP_CONF_UNACCEPT;
1849
1850 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001851 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001852 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001853
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001854 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001855 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001856 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001857 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001858 rsp->result = cpu_to_le16(result);
1859 rsp->flags = cpu_to_le16(0x0000);
1860
1861 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862}
1863
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001864static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001866 struct l2cap_conf_req *req = data;
1867 void *ptr = req->data;
1868 int type, olen;
1869 unsigned long val;
1870 struct l2cap_conf_rfc rfc;
1871
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001872 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001873
1874 while (len >= L2CAP_CONF_OPT_SIZE) {
1875 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1876
1877 switch (type) {
1878 case L2CAP_CONF_MTU:
1879 if (val < L2CAP_DEFAULT_MIN_MTU) {
1880 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001881 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001882 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001883 chan->imtu = val;
1884 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885 break;
1886
1887 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001888 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001889 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001890 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001891 break;
1892
1893 case L2CAP_CONF_RFC:
1894 if (olen == sizeof(rfc))
1895 memcpy(&rfc, (void *)val, olen);
1896
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001897 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001898 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001899 return -ECONNREFUSED;
1900
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001901 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001902
1903 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1904 sizeof(rfc), (unsigned long) &rfc);
1905 break;
1906 }
1907 }
1908
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001909 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001910 return -ECONNREFUSED;
1911
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001912 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001913
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 if (*result == L2CAP_CONF_SUCCESS) {
1915 switch (rfc.mode) {
1916 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001917 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1918 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1919 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920 break;
1921 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001922 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 }
1924 }
1925
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001926 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001927 req->flags = cpu_to_le16(0x0000);
1928
1929 return ptr - data;
1930}
1931
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001932static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
1934 struct l2cap_conf_rsp *rsp = data;
1935 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001937 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001939 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001940 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001941 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
1943 return ptr - data;
1944}
1945
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001946void __l2cap_connect_rsp_defer(struct sock *sk)
1947{
1948 struct l2cap_conn_rsp rsp;
1949 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1950 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1951 u8 buf[128];
1952
1953 sk->sk_state = BT_CONFIG;
1954
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001955 rsp.scid = cpu_to_le16(chan->dcid);
1956 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001957 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1958 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1959 l2cap_send_cmd(conn, chan->ident,
1960 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1961
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001962 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001963 return;
1964
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001965 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001966 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1967 l2cap_build_conf_req(chan, buf), buf);
1968 chan->num_conf_req++;
1969}
1970
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001971static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001972{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001973 int type, olen;
1974 unsigned long val;
1975 struct l2cap_conf_rfc rfc;
1976
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001977 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001978
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001979 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001980 return;
1981
1982 while (len >= L2CAP_CONF_OPT_SIZE) {
1983 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1984
1985 switch (type) {
1986 case L2CAP_CONF_RFC:
1987 if (olen == sizeof(rfc))
1988 memcpy(&rfc, (void *)val, olen);
1989 goto done;
1990 }
1991 }
1992
1993done:
1994 switch (rfc.mode) {
1995 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001996 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1997 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1998 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001999 break;
2000 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002001 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002002 }
2003}
2004
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002005static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2006{
2007 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2008
2009 if (rej->reason != 0x0000)
2010 return 0;
2011
2012 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2013 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002014 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002015
2016 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002017 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002018
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002019 l2cap_conn_start(conn);
2020 }
2021
2022 return 0;
2023}
2024
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2026{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2028 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002029 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002030 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002031 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032
2033 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002034 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035
2036 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2037
2038 /* Check if we have socket listening on psm */
2039 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2040 if (!parent) {
2041 result = L2CAP_CR_BAD_PSM;
2042 goto sendresp;
2043 }
2044
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002045 bh_lock_sock(parent);
2046
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002047 /* Check if the ACL is secure enough (if not SDP) */
2048 if (psm != cpu_to_le16(0x0001) &&
2049 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002050 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002051 result = L2CAP_CR_SEC_BLOCK;
2052 goto response;
2053 }
2054
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 result = L2CAP_CR_NO_MEM;
2056
2057 /* Check for backlog size */
2058 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002059 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 goto response;
2061 }
2062
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002063 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 if (!sk)
2065 goto response;
2066
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002067 chan = l2cap_chan_alloc(sk);
2068 if (!chan) {
2069 l2cap_sock_kill(sk);
2070 goto response;
2071 }
2072
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002073 l2cap_pi(sk)->chan = chan;
2074
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002075 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
2077 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002078 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2079 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 sock_set_flag(sk, SOCK_ZAPPED);
2081 l2cap_sock_kill(sk);
2082 goto response;
2083 }
2084
2085 hci_conn_hold(conn->hcon);
2086
2087 l2cap_sock_init(sk, parent);
2088 bacpy(&bt_sk(sk)->src, conn->src);
2089 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002090 chan->psm = psm;
2091 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002093 bt_accept_enqueue(parent, sk);
2094
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002095 __l2cap_chan_add(conn, chan);
2096
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002097 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
2099 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2100
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002101 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102
Marcel Holtmann984947d2009-02-06 23:35:19 +01002103 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002104 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002105 if (bt_sk(sk)->defer_setup) {
2106 sk->sk_state = BT_CONNECT2;
2107 result = L2CAP_CR_PEND;
2108 status = L2CAP_CS_AUTHOR_PEND;
2109 parent->sk_data_ready(parent, 0);
2110 } else {
2111 sk->sk_state = BT_CONFIG;
2112 result = L2CAP_CR_SUCCESS;
2113 status = L2CAP_CS_NO_INFO;
2114 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002115 } else {
2116 sk->sk_state = BT_CONNECT2;
2117 result = L2CAP_CR_PEND;
2118 status = L2CAP_CS_AUTHEN_PEND;
2119 }
2120 } else {
2121 sk->sk_state = BT_CONNECT2;
2122 result = L2CAP_CR_PEND;
2123 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002126 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
2128response:
2129 bh_unlock_sock(parent);
2130
2131sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002132 rsp.scid = cpu_to_le16(scid);
2133 rsp.dcid = cpu_to_le16(dcid);
2134 rsp.result = cpu_to_le16(result);
2135 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002137
2138 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2139 struct l2cap_info_req info;
2140 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2141
2142 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2143 conn->info_ident = l2cap_get_ident(conn);
2144
2145 mod_timer(&conn->info_timer, jiffies +
2146 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2147
2148 l2cap_send_cmd(conn, conn->info_ident,
2149 L2CAP_INFO_REQ, sizeof(info), &info);
2150 }
2151
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002152 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002153 result == L2CAP_CR_SUCCESS) {
2154 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002155 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002156 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002157 l2cap_build_conf_req(chan, buf), buf);
2158 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002159 }
2160
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 return 0;
2162}
2163
2164static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2165{
2166 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2167 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002168 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 struct sock *sk;
2170 u8 req[128];
2171
2172 scid = __le16_to_cpu(rsp->scid);
2173 dcid = __le16_to_cpu(rsp->dcid);
2174 result = __le16_to_cpu(rsp->result);
2175 status = __le16_to_cpu(rsp->status);
2176
2177 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2178
2179 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002180 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002181 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002182 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002184 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002185 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002186 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 }
2188
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002189 sk = chan->sk;
2190
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 switch (result) {
2192 case L2CAP_CR_SUCCESS:
2193 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002194 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002195 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002196 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002197
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002198 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002199 break;
2200
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002201 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002202
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002204 l2cap_build_conf_req(chan, req), req);
2205 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 break;
2207
2208 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002209 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 break;
2211
2212 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002213 /* don't delete l2cap channel if sk is owned by user */
2214 if (sock_owned_by_user(sk)) {
2215 sk->sk_state = BT_DISCONN;
2216 l2cap_sock_clear_timer(sk);
2217 l2cap_sock_set_timer(sk, HZ / 5);
2218 break;
2219 }
2220
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002221 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 break;
2223 }
2224
2225 bh_unlock_sock(sk);
2226 return 0;
2227}
2228
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002229static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002230{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002231 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2232
Mat Martineau8c462b62010-08-24 15:35:42 -07002233 /* FCS is enabled only in ERTM or streaming mode, if one or both
2234 * sides request it.
2235 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002236 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002237 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002238 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002239 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002240}
2241
Al Viro88219a02007-07-29 00:17:25 -07002242static 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 -07002243{
2244 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2245 u16 dcid, flags;
2246 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002247 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002249 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
2251 dcid = __le16_to_cpu(req->dcid);
2252 flags = __le16_to_cpu(req->flags);
2253
2254 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2255
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002256 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002257 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 return -ENOENT;
2259
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002260 sk = chan->sk;
2261
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002262 if (sk->sk_state != BT_CONFIG) {
2263 struct l2cap_cmd_rej rej;
2264
2265 rej.reason = cpu_to_le16(0x0002);
2266 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2267 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002268 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002269 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002270
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002271 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002272 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002273 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002274 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002275 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002276 L2CAP_CONF_REJECT, flags), rsp);
2277 goto unlock;
2278 }
2279
2280 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002281 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2282 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283
2284 if (flags & 0x0001) {
2285 /* Incomplete config. Send empty response. */
2286 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002287 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002288 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 goto unlock;
2290 }
2291
2292 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002293 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002294 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002295 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002299 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002300 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002301
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002302 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002303 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002304
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002305 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002306 goto unlock;
2307
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002308 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002309 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002312
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002313 chan->next_tx_seq = 0;
2314 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002315 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002316 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002317 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002318
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002320 goto unlock;
2321 }
2322
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002323 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002324 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002325 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002327 l2cap_build_conf_req(chan, buf), buf);
2328 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 }
2330
2331unlock:
2332 bh_unlock_sock(sk);
2333 return 0;
2334}
2335
2336static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2337{
2338 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2339 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002340 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002342 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
2344 scid = __le16_to_cpu(rsp->scid);
2345 flags = __le16_to_cpu(rsp->flags);
2346 result = __le16_to_cpu(rsp->result);
2347
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002348 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2349 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002351 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002352 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 return 0;
2354
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002355 sk = chan->sk;
2356
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 switch (result) {
2358 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002359 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 break;
2361
2362 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002363 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002364 char req[64];
2365
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002366 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002367 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002368 goto done;
2369 }
2370
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371 /* throw out any old stored conf requests */
2372 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002373 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2374 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002375 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002376 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002377 goto done;
2378 }
2379
2380 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2381 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002382 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383 if (result != L2CAP_CONF_SUCCESS)
2384 goto done;
2385 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 }
2387
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002388 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002389 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002391 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 goto done;
2393 }
2394
2395 if (flags & 0x01)
2396 goto done;
2397
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002398 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002400 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002401 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002402
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002404 chan->next_tx_seq = 0;
2405 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002406 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002407 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002408 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002409
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 l2cap_chan_ready(sk);
2411 }
2412
2413done:
2414 bh_unlock_sock(sk);
2415 return 0;
2416}
2417
2418static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2419{
2420 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2421 struct l2cap_disconn_rsp rsp;
2422 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002423 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 struct sock *sk;
2425
2426 scid = __le16_to_cpu(req->scid);
2427 dcid = __le16_to_cpu(req->dcid);
2428
2429 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2430
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002431 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002432 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 return 0;
2434
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002435 sk = chan->sk;
2436
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002437 rsp.dcid = cpu_to_le16(chan->scid);
2438 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2440
2441 sk->sk_shutdown = SHUTDOWN_MASK;
2442
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002443 /* don't delete l2cap channel if sk is owned by user */
2444 if (sock_owned_by_user(sk)) {
2445 sk->sk_state = BT_DISCONN;
2446 l2cap_sock_clear_timer(sk);
2447 l2cap_sock_set_timer(sk, HZ / 5);
2448 bh_unlock_sock(sk);
2449 return 0;
2450 }
2451
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002452 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 bh_unlock_sock(sk);
2454
2455 l2cap_sock_kill(sk);
2456 return 0;
2457}
2458
2459static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2460{
2461 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2462 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 struct sock *sk;
2465
2466 scid = __le16_to_cpu(rsp->scid);
2467 dcid = __le16_to_cpu(rsp->dcid);
2468
2469 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2470
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002471 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002472 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 return 0;
2474
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002475 sk = chan->sk;
2476
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002477 /* don't delete l2cap channel if sk is owned by user */
2478 if (sock_owned_by_user(sk)) {
2479 sk->sk_state = BT_DISCONN;
2480 l2cap_sock_clear_timer(sk);
2481 l2cap_sock_set_timer(sk, HZ / 5);
2482 bh_unlock_sock(sk);
2483 return 0;
2484 }
2485
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002486 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 bh_unlock_sock(sk);
2488
2489 l2cap_sock_kill(sk);
2490 return 0;
2491}
2492
2493static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2494{
2495 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 u16 type;
2497
2498 type = __le16_to_cpu(req->type);
2499
2500 BT_DBG("type 0x%4.4x", type);
2501
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002502 if (type == L2CAP_IT_FEAT_MASK) {
2503 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002504 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002505 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2506 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2507 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002508 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002509 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2510 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002511 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002512 l2cap_send_cmd(conn, cmd->ident,
2513 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002514 } else if (type == L2CAP_IT_FIXED_CHAN) {
2515 u8 buf[12];
2516 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2517 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2518 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2519 memcpy(buf + 4, l2cap_fixed_chan, 8);
2520 l2cap_send_cmd(conn, cmd->ident,
2521 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002522 } else {
2523 struct l2cap_info_rsp rsp;
2524 rsp.type = cpu_to_le16(type);
2525 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2526 l2cap_send_cmd(conn, cmd->ident,
2527 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529
2530 return 0;
2531}
2532
2533static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2534{
2535 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2536 u16 type, result;
2537
2538 type = __le16_to_cpu(rsp->type);
2539 result = __le16_to_cpu(rsp->result);
2540
2541 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2542
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002543 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2544 if (cmd->ident != conn->info_ident ||
2545 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2546 return 0;
2547
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002548 del_timer(&conn->info_timer);
2549
Ville Tervoadb08ed2010-08-04 09:43:33 +03002550 if (result != L2CAP_IR_SUCCESS) {
2551 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2552 conn->info_ident = 0;
2553
2554 l2cap_conn_start(conn);
2555
2556 return 0;
2557 }
2558
Marcel Holtmann984947d2009-02-06 23:35:19 +01002559 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002560 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002561
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002562 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002563 struct l2cap_info_req req;
2564 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2565
2566 conn->info_ident = l2cap_get_ident(conn);
2567
2568 l2cap_send_cmd(conn, conn->info_ident,
2569 L2CAP_INFO_REQ, sizeof(req), &req);
2570 } else {
2571 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2572 conn->info_ident = 0;
2573
2574 l2cap_conn_start(conn);
2575 }
2576 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002577 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002578 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002579
2580 l2cap_conn_start(conn);
2581 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002582
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 return 0;
2584}
2585
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002586static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002587 u16 to_multiplier)
2588{
2589 u16 max_latency;
2590
2591 if (min > max || min < 6 || max > 3200)
2592 return -EINVAL;
2593
2594 if (to_multiplier < 10 || to_multiplier > 3200)
2595 return -EINVAL;
2596
2597 if (max >= to_multiplier * 8)
2598 return -EINVAL;
2599
2600 max_latency = (to_multiplier * 8 / max) - 1;
2601 if (latency > 499 || latency > max_latency)
2602 return -EINVAL;
2603
2604 return 0;
2605}
2606
2607static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2608 struct l2cap_cmd_hdr *cmd, u8 *data)
2609{
2610 struct hci_conn *hcon = conn->hcon;
2611 struct l2cap_conn_param_update_req *req;
2612 struct l2cap_conn_param_update_rsp rsp;
2613 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002614 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002615
2616 if (!(hcon->link_mode & HCI_LM_MASTER))
2617 return -EINVAL;
2618
2619 cmd_len = __le16_to_cpu(cmd->len);
2620 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2621 return -EPROTO;
2622
2623 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002624 min = __le16_to_cpu(req->min);
2625 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002626 latency = __le16_to_cpu(req->latency);
2627 to_multiplier = __le16_to_cpu(req->to_multiplier);
2628
2629 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2630 min, max, latency, to_multiplier);
2631
2632 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002633
2634 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2635 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002636 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2637 else
2638 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2639
2640 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2641 sizeof(rsp), &rsp);
2642
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002643 if (!err)
2644 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2645
Claudio Takahaside731152011-02-11 19:28:55 -02002646 return 0;
2647}
2648
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002649static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2650 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2651{
2652 int err = 0;
2653
2654 switch (cmd->code) {
2655 case L2CAP_COMMAND_REJ:
2656 l2cap_command_rej(conn, cmd, data);
2657 break;
2658
2659 case L2CAP_CONN_REQ:
2660 err = l2cap_connect_req(conn, cmd, data);
2661 break;
2662
2663 case L2CAP_CONN_RSP:
2664 err = l2cap_connect_rsp(conn, cmd, data);
2665 break;
2666
2667 case L2CAP_CONF_REQ:
2668 err = l2cap_config_req(conn, cmd, cmd_len, data);
2669 break;
2670
2671 case L2CAP_CONF_RSP:
2672 err = l2cap_config_rsp(conn, cmd, data);
2673 break;
2674
2675 case L2CAP_DISCONN_REQ:
2676 err = l2cap_disconnect_req(conn, cmd, data);
2677 break;
2678
2679 case L2CAP_DISCONN_RSP:
2680 err = l2cap_disconnect_rsp(conn, cmd, data);
2681 break;
2682
2683 case L2CAP_ECHO_REQ:
2684 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2685 break;
2686
2687 case L2CAP_ECHO_RSP:
2688 break;
2689
2690 case L2CAP_INFO_REQ:
2691 err = l2cap_information_req(conn, cmd, data);
2692 break;
2693
2694 case L2CAP_INFO_RSP:
2695 err = l2cap_information_rsp(conn, cmd, data);
2696 break;
2697
2698 default:
2699 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2700 err = -EINVAL;
2701 break;
2702 }
2703
2704 return err;
2705}
2706
2707static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2708 struct l2cap_cmd_hdr *cmd, u8 *data)
2709{
2710 switch (cmd->code) {
2711 case L2CAP_COMMAND_REJ:
2712 return 0;
2713
2714 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002715 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002716
2717 case L2CAP_CONN_PARAM_UPDATE_RSP:
2718 return 0;
2719
2720 default:
2721 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2722 return -EINVAL;
2723 }
2724}
2725
2726static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2727 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728{
2729 u8 *data = skb->data;
2730 int len = skb->len;
2731 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002732 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
2734 l2cap_raw_recv(conn, skb);
2735
2736 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002737 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2739 data += L2CAP_CMD_HDR_SIZE;
2740 len -= L2CAP_CMD_HDR_SIZE;
2741
Al Viro88219a02007-07-29 00:17:25 -07002742 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743
Al Viro88219a02007-07-29 00:17:25 -07002744 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 -07002745
Al Viro88219a02007-07-29 00:17:25 -07002746 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 BT_DBG("corrupted command");
2748 break;
2749 }
2750
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002751 if (conn->hcon->type == LE_LINK)
2752 err = l2cap_le_sig_cmd(conn, &cmd, data);
2753 else
2754 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
2756 if (err) {
2757 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002758
2759 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760
2761 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002762 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2764 }
2765
Al Viro88219a02007-07-29 00:17:25 -07002766 data += cmd_len;
2767 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 }
2769
2770 kfree_skb(skb);
2771}
2772
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002773static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002774{
2775 u16 our_fcs, rcv_fcs;
2776 int hdr_size = L2CAP_HDR_SIZE + 2;
2777
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002778 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002779 skb_trim(skb, skb->len - 2);
2780 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2781 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2782
2783 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002784 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002785 }
2786 return 0;
2787}
2788
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002789static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002790{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791 u16 control = 0;
2792
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002793 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002794
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002795 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002797 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002798 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002799 l2cap_send_sframe(chan, control);
2800 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002801 }
2802
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002803 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2804 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002805
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002806 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002807
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002808 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002809 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002810 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002811 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002812 }
2813}
2814
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002815static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002816{
2817 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002818 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002819
2820 bt_cb(skb)->tx_seq = tx_seq;
2821 bt_cb(skb)->sar = sar;
2822
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002823 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002824 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002825 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002826 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002827 }
2828
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002829 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002830 if (tx_seq_offset < 0)
2831 tx_seq_offset += 64;
2832
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002833 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002834 if (bt_cb(next_skb)->tx_seq == tx_seq)
2835 return -EINVAL;
2836
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002837 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002838 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002839 if (next_tx_seq_offset < 0)
2840 next_tx_seq_offset += 64;
2841
2842 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002843 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002844 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002845 }
2846
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002847 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002848 break;
2849
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002850 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002851
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002852 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002853
2854 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002855}
2856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002857static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002858{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002859 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002860 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002861 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002862
2863 switch (control & L2CAP_CTRL_SAR) {
2864 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002865 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002866 goto drop;
2867
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002868 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002869 if (!err)
2870 return err;
2871
2872 break;
2873
2874 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002875 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002876 goto drop;
2877
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002878 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002879
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002880 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002881 goto disconnect;
2882
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002883 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2884 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002885 return -ENOMEM;
2886
2887 /* pull sdu_len bytes only after alloc, because of Local Busy
2888 * condition we have to be sure that this will be executed
2889 * only once, i.e., when alloc does not fail */
2890 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002891
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002892 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002893
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002894 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002895 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002896 break;
2897
2898 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002899 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002900 goto disconnect;
2901
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002902 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002903 goto disconnect;
2904
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002905 chan->partial_sdu_len += skb->len;
2906 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002907 goto drop;
2908
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002909 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002910
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002911 break;
2912
2913 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002914 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002915 goto disconnect;
2916
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002917 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002918 goto disconnect;
2919
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002920 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002921 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002922
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002923 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002924 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002926 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002927 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002928
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002929 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002930 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002931
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002932 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002934 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002935 return -ENOMEM;
2936 }
2937
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002938 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002939 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002940 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002941 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002942 return err;
2943 }
2944
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002945 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2946 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002947
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002948 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002949 break;
2950 }
2951
2952 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002953 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002954
2955drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002956 kfree_skb(chan->sdu);
2957 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002958
2959disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002960 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002961 kfree_skb(skb);
2962 return 0;
2963}
2964
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002965static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002966{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967 struct sk_buff *skb;
2968 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002969 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002970
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002971 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002972 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002973 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002975 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002977 }
2978
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002979 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002980 }
2981
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002982 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002983 goto done;
2984
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002985 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002987 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002988 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002989
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002990 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991 __mod_monitor_timer();
2992
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002993 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002994
2995done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002996 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2997 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002998
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002999 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003000
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003001 return 0;
3002}
3003
3004static void l2cap_busy_work(struct work_struct *work)
3005{
3006 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003007 struct l2cap_chan *chan =
3008 container_of(work, struct l2cap_chan, busy_work);
3009 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003010 int n_tries = 0, timeo = HZ/5, err;
3011 struct sk_buff *skb;
3012
3013 lock_sock(sk);
3014
3015 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003016 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003017 set_current_state(TASK_INTERRUPTIBLE);
3018
3019 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3020 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003021 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003022 break;
3023 }
3024
3025 if (!timeo)
3026 timeo = HZ/5;
3027
3028 if (signal_pending(current)) {
3029 err = sock_intr_errno(timeo);
3030 break;
3031 }
3032
3033 release_sock(sk);
3034 timeo = schedule_timeout(timeo);
3035 lock_sock(sk);
3036
3037 err = sock_error(sk);
3038 if (err)
3039 break;
3040
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003041 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003042 break;
3043 }
3044
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003045 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003046 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003047
3048 release_sock(sk);
3049}
3050
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003051static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003053 int sctrl, err;
3054
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003055 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003057 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003059
3060
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061 }
3062
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003063 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003064 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003065 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003066 return err;
3067 }
3068
3069 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003070 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003071
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003072 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003073 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003074 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003075
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003076 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003079
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003081
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003082 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003083
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003084 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003085
3086 return err;
3087}
3088
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003089static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003090{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003091 struct sk_buff *_skb;
3092 int err = -EINVAL;
3093
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003094 /*
3095 * TODO: We have to notify the userland if some data is lost with the
3096 * Streaming Mode.
3097 */
3098
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 switch (control & L2CAP_CTRL_SAR) {
3100 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003101 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003102 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003103 break;
3104 }
3105
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003106 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 if (!err)
3108 return 0;
3109
3110 break;
3111
3112 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003113 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003114 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003115 break;
3116 }
3117
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003118 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003119 skb_pull(skb, 2);
3120
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003121 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003122 err = -EMSGSIZE;
3123 break;
3124 }
3125
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003126 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3127 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003128 err = -ENOMEM;
3129 break;
3130 }
3131
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003132 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003133
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003134 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003135 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003136 err = 0;
3137 break;
3138
3139 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003140 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141 break;
3142
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003145 chan->partial_sdu_len += skb->len;
3146 if (chan->partial_sdu_len > chan->sdu_len)
3147 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003148 else
3149 err = 0;
3150
3151 break;
3152
3153 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003154 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003155 break;
3156
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003157 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003158
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003159 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003162 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003163 goto drop;
3164
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 if (chan->partial_sdu_len == chan->sdu_len) {
3166 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003167 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003168 if (err < 0)
3169 kfree_skb(_skb);
3170 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 err = 0;
3172
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003173drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003174 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003175 break;
3176 }
3177
3178 kfree_skb(skb);
3179 return err;
3180}
3181
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003182static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003183{
3184 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003185 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003186
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003187 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003188 if (bt_cb(skb)->tx_seq != tx_seq)
3189 break;
3190
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003191 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003192 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003193 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003194 chan->buffer_seq_srej =
3195 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003196 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003197 }
3198}
3199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003200static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003201{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003202 struct srej_list *l, *tmp;
3203 u16 control;
3204
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003205 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 if (l->tx_seq == tx_seq) {
3207 list_del(&l->list);
3208 kfree(l);
3209 return;
3210 }
3211 control = L2CAP_SUPER_SELECT_REJECT;
3212 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003213 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003215 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216 }
3217}
3218
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003219static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003220{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003221 struct srej_list *new;
3222 u16 control;
3223
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003224 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003226 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003227 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003228
3229 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003230 new->tx_seq = chan->expected_tx_seq;
3231 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003232 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003235}
3236
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003238{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003239 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003240 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003241 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003242 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003243 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003244 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003245 int err = 0;
3246
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3248 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003249
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003250 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003252 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003253 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003254 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003255 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003256 }
3257
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003258 chan->expected_ack_seq = req_seq;
3259 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003260
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003261 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003262 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003263
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003264 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003265 if (tx_seq_offset < 0)
3266 tx_seq_offset += 64;
3267
3268 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003269 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003270 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003271 goto drop;
3272 }
3273
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003274 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003275 goto drop;
3276
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003277 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003278 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003279
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003280 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003281 struct srej_list, list);
3282 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003283 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003284 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003285
3286 list_del(&first->list);
3287 kfree(first);
3288
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003289 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003290 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003291 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3292 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003293 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003294 }
3295 } else {
3296 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003297
3298 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003299 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003300 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003302 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003303 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003304 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305 return 0;
3306 }
3307 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003308 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003309 }
3310 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003311 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003312 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003313 if (expected_tx_seq_offset < 0)
3314 expected_tx_seq_offset += 64;
3315
3316 /* duplicated tx_seq */
3317 if (tx_seq_offset < expected_tx_seq_offset)
3318 goto drop;
3319
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003320 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003321
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003322 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003323
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003324 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003325 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003326
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003327 __skb_queue_head_init(&chan->srej_q);
3328 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003329 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003334
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003335 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003336 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003337 return 0;
3338
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003340 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003343 bt_cb(skb)->tx_seq = tx_seq;
3344 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003345 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003346 return 0;
3347 }
3348
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003349 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003350 if (err < 0)
3351 return 0;
3352
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003353 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003354 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3355 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003356 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003357 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003358 }
3359
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003360 __mod_ack_timer();
3361
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003362 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3363 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003364 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003365
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003366 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003367
3368drop:
3369 kfree_skb(skb);
3370 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003371}
3372
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003373static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003374{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003375 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003376 rx_control);
3377
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003378 chan->expected_ack_seq = __get_reqseq(rx_control);
3379 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003381 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3383 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3384 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003385 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003386 __mod_retrans_timer();
3387
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003388 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3389 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003390 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003391 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003392 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003393
3394 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003396
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003397 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3398 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003399 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003400 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401
3402 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003404 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003405 __mod_retrans_timer();
3406
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3408 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3409 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003410 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003412 }
3413}
3414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003416{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003417 u8 tx_seq = __get_reqseq(rx_control);
3418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003420
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003423 chan->expected_ack_seq = tx_seq;
3424 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425
3426 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3428 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003429 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3435 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436 }
3437}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003439{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003440 u8 tx_seq = __get_reqseq(rx_control);
3441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003445
3446 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003447 chan->expected_ack_seq = tx_seq;
3448 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3451 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003452
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003454
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003456 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458 }
3459 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003461 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003463 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003465 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 l2cap_retransmit_one_frame(chan, tx_seq);
3467 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003468 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003470 }
3471 }
3472}
3473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003475{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476 u8 tx_seq = __get_reqseq(rx_control);
3477
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003479
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003480 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003481 chan->expected_ack_seq = tx_seq;
3482 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003484 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003486
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003487 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003488 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003489 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003491 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003492 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003493
3494 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003496 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003498}
3499
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003501{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003504 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003506 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003507 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003508 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003510 }
3511
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003512 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3513 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003515 break;
3516
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003519 break;
3520
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003521 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003523 break;
3524
3525 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 break;
3528 }
3529
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003530 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531 return 0;
3532}
3533
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003534static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3535{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003537 struct l2cap_pinfo *pi = l2cap_pi(sk);
3538 u16 control;
3539 u8 req_seq;
3540 int len, next_tx_seq_offset, req_seq_offset;
3541
3542 control = get_unaligned_le16(skb->data);
3543 skb_pull(skb, 2);
3544 len = skb->len;
3545
3546 /*
3547 * We can just drop the corrupted I-frame here.
3548 * Receiver will miss it and start proper recovery
3549 * procedures and ask retransmission.
3550 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003551 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003552 goto drop;
3553
3554 if (__is_sar_start(control) && __is_iframe(control))
3555 len -= 2;
3556
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003557 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003558 len -= 2;
3559
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003560 if (len > chan->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003561 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003562 goto drop;
3563 }
3564
3565 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003566 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003567 if (req_seq_offset < 0)
3568 req_seq_offset += 64;
3569
3570 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003571 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003572 if (next_tx_seq_offset < 0)
3573 next_tx_seq_offset += 64;
3574
3575 /* check for invalid req-seq */
3576 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003577 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003578 goto drop;
3579 }
3580
3581 if (__is_iframe(control)) {
3582 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003583 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003584 goto drop;
3585 }
3586
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003588 } else {
3589 if (len != 0) {
3590 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003591 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003592 goto drop;
3593 }
3594
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596 }
3597
3598 return 0;
3599
3600drop:
3601 kfree_skb(skb);
3602 return 0;
3603}
3604
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3606{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003607 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003609 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003610 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003611 u8 tx_seq;
3612 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003614 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003615 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 BT_DBG("unknown cid 0x%4.4x", cid);
3617 goto drop;
3618 }
3619
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003620 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003621 pi = l2cap_pi(sk);
3622
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003623 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
3625 if (sk->sk_state != BT_CONNECTED)
3626 goto drop;
3627
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003628 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003629 case L2CAP_MODE_BASIC:
3630 /* If socket recv buffers overflows we drop data here
3631 * which is *bad* because L2CAP has to be reliable.
3632 * But we don't have any other choice. L2CAP doesn't
3633 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003635 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003638 if (!sock_queue_rcv_skb(sk, skb))
3639 goto done;
3640 break;
3641
3642 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003643 if (!sock_owned_by_user(sk)) {
3644 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003645 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003646 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003647 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003648 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003650 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003652 case L2CAP_MODE_STREAMING:
3653 control = get_unaligned_le16(skb->data);
3654 skb_pull(skb, 2);
3655 len = skb->len;
3656
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003657 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003658 goto drop;
3659
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003660 if (__is_sar_start(control))
3661 len -= 2;
3662
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003663 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003664 len -= 2;
3665
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003666 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003667 goto drop;
3668
3669 tx_seq = __get_txseq(control);
3670
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003671 if (chan->expected_tx_seq == tx_seq)
3672 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003674 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003675
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003677
3678 goto done;
3679
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003680 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003681 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003682 break;
3683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
3685drop:
3686 kfree_skb(skb);
3687
3688done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003689 if (sk)
3690 bh_unlock_sock(sk);
3691
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 return 0;
3693}
3694
Al Viro8e036fc2007-07-29 00:16:36 -07003695static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696{
3697 struct sock *sk;
3698
3699 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3700 if (!sk)
3701 goto drop;
3702
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003703 bh_lock_sock(sk);
3704
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 BT_DBG("sk %p, len %d", sk, skb->len);
3706
3707 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3708 goto drop;
3709
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003710 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 goto drop;
3712
3713 if (!sock_queue_rcv_skb(sk, skb))
3714 goto done;
3715
3716drop:
3717 kfree_skb(skb);
3718
3719done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003720 if (sk)
3721 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 return 0;
3723}
3724
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003725static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3726{
3727 struct sock *sk;
3728
3729 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3730 if (!sk)
3731 goto drop;
3732
3733 bh_lock_sock(sk);
3734
3735 BT_DBG("sk %p, len %d", sk, skb->len);
3736
3737 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3738 goto drop;
3739
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003740 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003741 goto drop;
3742
3743 if (!sock_queue_rcv_skb(sk, skb))
3744 goto done;
3745
3746drop:
3747 kfree_skb(skb);
3748
3749done:
3750 if (sk)
3751 bh_unlock_sock(sk);
3752 return 0;
3753}
3754
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3756{
3757 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003758 u16 cid, len;
3759 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
3761 skb_pull(skb, L2CAP_HDR_SIZE);
3762 cid = __le16_to_cpu(lh->cid);
3763 len = __le16_to_cpu(lh->len);
3764
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003765 if (len != skb->len) {
3766 kfree_skb(skb);
3767 return;
3768 }
3769
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3771
3772 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003773 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003774 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 l2cap_sig_channel(conn, skb);
3776 break;
3777
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003778 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003779 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 skb_pull(skb, 2);
3781 l2cap_conless_channel(conn, psm, skb);
3782 break;
3783
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003784 case L2CAP_CID_LE_DATA:
3785 l2cap_att_channel(conn, cid, skb);
3786 break;
3787
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 default:
3789 l2cap_data_channel(conn, cid, skb);
3790 break;
3791 }
3792}
3793
3794/* ---- L2CAP interface with lower layer (HCI) ---- */
3795
3796static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3797{
3798 int exact = 0, lm1 = 0, lm2 = 0;
3799 register struct sock *sk;
3800 struct hlist_node *node;
3801
3802 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003803 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
3805 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3806
3807 /* Find listening sockets and check their link_mode */
3808 read_lock(&l2cap_sk_list.lock);
3809 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003810 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
3811
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 if (sk->sk_state != BT_LISTEN)
3813 continue;
3814
3815 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003816 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003817 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003818 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003820 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3821 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003822 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003823 lm2 |= HCI_LM_MASTER;
3824 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 }
3826 read_unlock(&l2cap_sk_list.lock);
3827
3828 return exact ? lm1 : lm2;
3829}
3830
3831static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3832{
Marcel Holtmann01394182006-07-03 10:02:46 +02003833 struct l2cap_conn *conn;
3834
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3836
Ville Tervoacd7d372011-02-10 22:38:49 -03003837 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003838 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
3840 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 conn = l2cap_conn_add(hcon, status);
3842 if (conn)
3843 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003844 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 l2cap_conn_del(hcon, bt_err(status));
3846
3847 return 0;
3848}
3849
Marcel Holtmann2950f212009-02-12 14:02:50 +01003850static int l2cap_disconn_ind(struct hci_conn *hcon)
3851{
3852 struct l2cap_conn *conn = hcon->l2cap_data;
3853
3854 BT_DBG("hcon %p", hcon);
3855
3856 if (hcon->type != ACL_LINK || !conn)
3857 return 0x13;
3858
3859 return conn->disc_reason;
3860}
3861
3862static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863{
3864 BT_DBG("hcon %p reason %d", hcon, reason);
3865
Ville Tervoacd7d372011-02-10 22:38:49 -03003866 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003867 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
3869 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003870
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 return 0;
3872}
3873
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003874static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003875{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003876 struct sock *sk = chan->sk;
3877
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003878 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003879 return;
3880
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003881 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003882 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003883 l2cap_sock_clear_timer(sk);
3884 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003885 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003886 __l2cap_sock_close(sk, ECONNREFUSED);
3887 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003888 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003889 l2cap_sock_clear_timer(sk);
3890 }
3891}
3892
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003893static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003895 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003896 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Marcel Holtmann01394182006-07-03 10:02:46 +02003898 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 BT_DBG("conn %p", conn);
3902
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003903 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003905 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003906 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 bh_lock_sock(sk);
3909
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003910 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003911 bh_unlock_sock(sk);
3912 continue;
3913 }
3914
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003915 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003916 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003917 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003918 bh_unlock_sock(sk);
3919 continue;
3920 }
3921
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003922 if (sk->sk_state == BT_CONNECT) {
3923 if (!status) {
3924 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003925 req.scid = cpu_to_le16(chan->scid);
3926 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003927
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003928 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003929 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003930
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003931 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003932 L2CAP_CONN_REQ, sizeof(req), &req);
3933 } else {
3934 l2cap_sock_clear_timer(sk);
3935 l2cap_sock_set_timer(sk, HZ / 10);
3936 }
3937 } else if (sk->sk_state == BT_CONNECT2) {
3938 struct l2cap_conn_rsp rsp;
3939 __u16 result;
3940
3941 if (!status) {
3942 sk->sk_state = BT_CONFIG;
3943 result = L2CAP_CR_SUCCESS;
3944 } else {
3945 sk->sk_state = BT_DISCONN;
3946 l2cap_sock_set_timer(sk, HZ / 10);
3947 result = L2CAP_CR_SEC_BLOCK;
3948 }
3949
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003950 rsp.scid = cpu_to_le16(chan->dcid);
3951 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003952 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003953 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003954 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3955 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 }
3957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 bh_unlock_sock(sk);
3959 }
3960
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003961 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003962
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return 0;
3964}
3965
3966static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3967{
3968 struct l2cap_conn *conn = hcon->l2cap_data;
3969
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003970 if (!conn)
3971 conn = l2cap_conn_add(hcon, 0);
3972
3973 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 goto drop;
3975
3976 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3977
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003978 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003980 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003981 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 int len;
3983
3984 if (conn->rx_len) {
3985 BT_ERR("Unexpected start frame (len %d)", skb->len);
3986 kfree_skb(conn->rx_skb);
3987 conn->rx_skb = NULL;
3988 conn->rx_len = 0;
3989 l2cap_conn_unreliable(conn, ECOMM);
3990 }
3991
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003992 /* Start fragment always begin with Basic L2CAP header */
3993 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 BT_ERR("Frame is too short (len %d)", skb->len);
3995 l2cap_conn_unreliable(conn, ECOMM);
3996 goto drop;
3997 }
3998
3999 hdr = (struct l2cap_hdr *) skb->data;
4000 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004001 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
4003 if (len == skb->len) {
4004 /* Complete frame received */
4005 l2cap_recv_frame(conn, skb);
4006 return 0;
4007 }
4008
4009 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4010
4011 if (skb->len > len) {
4012 BT_ERR("Frame is too long (len %d, expected len %d)",
4013 skb->len, len);
4014 l2cap_conn_unreliable(conn, ECOMM);
4015 goto drop;
4016 }
4017
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004018 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004019
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004020 if (chan && chan->sk) {
4021 struct sock *sk = chan->sk;
4022
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004023 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004024 BT_ERR("Frame exceeding recv MTU (len %d, "
4025 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004026 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004027 bh_unlock_sock(sk);
4028 l2cap_conn_unreliable(conn, ECOMM);
4029 goto drop;
4030 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004031 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004032 }
4033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004035 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4036 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 goto drop;
4038
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004039 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004040 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 conn->rx_len = len - skb->len;
4042 } else {
4043 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4044
4045 if (!conn->rx_len) {
4046 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4047 l2cap_conn_unreliable(conn, ECOMM);
4048 goto drop;
4049 }
4050
4051 if (skb->len > conn->rx_len) {
4052 BT_ERR("Fragment is too long (len %d, expected %d)",
4053 skb->len, conn->rx_len);
4054 kfree_skb(conn->rx_skb);
4055 conn->rx_skb = NULL;
4056 conn->rx_len = 0;
4057 l2cap_conn_unreliable(conn, ECOMM);
4058 goto drop;
4059 }
4060
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004061 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004062 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 conn->rx_len -= skb->len;
4064
4065 if (!conn->rx_len) {
4066 /* Complete frame received */
4067 l2cap_recv_frame(conn, conn->rx_skb);
4068 conn->rx_skb = NULL;
4069 }
4070 }
4071
4072drop:
4073 kfree_skb(skb);
4074 return 0;
4075}
4076
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004077static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078{
4079 struct sock *sk;
4080 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
4082 read_lock_bh(&l2cap_sk_list.lock);
4083
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004084 sk_for_each(sk, node, &l2cap_sk_list.head) {
4085 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004086 struct l2cap_chan *chan = pi->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004088 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 +01004089 batostr(&bt_sk(sk)->src),
4090 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004091 sk->sk_state, __le16_to_cpu(chan->psm),
4092 chan->scid, chan->dcid,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004093 chan->imtu, chan->omtu, chan->sec_level,
4094 chan->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004098
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004099 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100}
4101
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004102static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4103{
4104 return single_open(file, l2cap_debugfs_show, inode->i_private);
4105}
4106
4107static const struct file_operations l2cap_debugfs_fops = {
4108 .open = l2cap_debugfs_open,
4109 .read = seq_read,
4110 .llseek = seq_lseek,
4111 .release = single_release,
4112};
4113
4114static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116static struct hci_proto l2cap_hci_proto = {
4117 .name = "L2CAP",
4118 .id = HCI_PROTO_L2CAP,
4119 .connect_ind = l2cap_connect_ind,
4120 .connect_cfm = l2cap_connect_cfm,
4121 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004122 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004123 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 .recv_acldata = l2cap_recv_acldata
4125};
4126
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004127int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
4129 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004130
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004131 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 if (err < 0)
4133 return err;
4134
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004135 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004136 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004137 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 goto error;
4139 }
4140
4141 err = hci_register_proto(&l2cap_hci_proto);
4142 if (err < 0) {
4143 BT_ERR("L2CAP protocol registration failed");
4144 bt_sock_unregister(BTPROTO_L2CAP);
4145 goto error;
4146 }
4147
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004148 if (bt_debugfs) {
4149 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4150 bt_debugfs, NULL, &l2cap_debugfs_fops);
4151 if (!l2cap_debugfs)
4152 BT_ERR("Failed to create L2CAP debug file");
4153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 return 0;
4156
4157error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004158 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004159 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 return err;
4161}
4162
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004163void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004165 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004167 flush_workqueue(_busy_wq);
4168 destroy_workqueue(_busy_wq);
4169
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4171 BT_ERR("L2CAP protocol unregistration failed");
4172
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004173 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174}
4175
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004176module_param(disable_ertm, bool, 0644);
4177MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");