blob: 8562ac1ba9472db73c7da497429c947b63e9d924 [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
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300172 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200173
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;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300207 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200208 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
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300221 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200222 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. Padovan8c1d7872011-04-13 20:23:55 -0300299 struct l2cap_conn *conn = chan->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. Padovan8c1d7872011-04-13 20:23:55 -0300352 struct l2cap_conn *conn = chan->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
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300397 hci_send_acl(chan->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. Padovan8c1d7872011-04-13 20:23:55 -0300420 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200421
422 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100423 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
424 return;
425
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300426 if (l2cap_check_security(chan) &&
427 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200428 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300429 req.scid = cpu_to_le16(chan->scid);
430 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200431
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300432 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300433 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200434
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300435 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
436 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200437 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200438 } else {
439 struct l2cap_info_req req;
440 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
441
442 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
443 conn->info_ident = l2cap_get_ident(conn);
444
445 mod_timer(&conn->info_timer, jiffies +
446 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
447
448 l2cap_send_cmd(conn, conn->info_ident,
449 L2CAP_INFO_REQ, sizeof(req), &req);
450 }
451}
452
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300453static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
454{
455 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300456 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300457 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
458
459 switch (mode) {
460 case L2CAP_MODE_ERTM:
461 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
462 case L2CAP_MODE_STREAMING:
463 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
464 default:
465 return 0x00;
466 }
467}
468
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300469void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300470{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300471 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300472 struct l2cap_disconn_req req;
473
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300474 if (!conn)
475 return;
476
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300477 sk = chan->sk;
478
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300479 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300480 del_timer(&chan->retrans_timer);
481 del_timer(&chan->monitor_timer);
482 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300483 }
484
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300485 req.dcid = cpu_to_le16(chan->dcid);
486 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300487 l2cap_send_cmd(conn, l2cap_get_ident(conn),
488 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300489
490 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300491 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300492}
493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200495static void l2cap_conn_start(struct l2cap_conn *conn)
496{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300497 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498
499 BT_DBG("conn %p", conn);
500
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300501 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200502
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300503 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300504 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300505
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200506 bh_lock_sock(sk);
507
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300508 if (sk->sk_type != SOCK_SEQPACKET &&
509 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200510 bh_unlock_sock(sk);
511 continue;
512 }
513
514 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300515 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300516
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300517 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300518 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300519 bh_unlock_sock(sk);
520 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200521 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300522
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300523 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300524 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300525 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300526 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300527 /* __l2cap_sock_close() calls list_del(chan)
528 * so release the lock */
529 read_unlock_bh(&conn->chan_lock);
530 __l2cap_sock_close(sk, ECONNRESET);
531 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300532 bh_unlock_sock(sk);
533 continue;
534 }
535
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300536 req.scid = cpu_to_le16(chan->scid);
537 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300538
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300539 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300540 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300542 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
543 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300544
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200545 } else if (sk->sk_state == BT_CONNECT2) {
546 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300547 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300548 rsp.scid = cpu_to_le16(chan->dcid);
549 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200550
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300551 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100552 if (bt_sk(sk)->defer_setup) {
553 struct sock *parent = bt_sk(sk)->parent;
554 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
555 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
556 parent->sk_data_ready(parent, 0);
557
558 } else {
559 sk->sk_state = BT_CONFIG;
560 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
561 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
562 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200563 } else {
564 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
565 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
566 }
567
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300568 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
569 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300570
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300571 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300572 rsp.result != L2CAP_CR_SUCCESS) {
573 bh_unlock_sock(sk);
574 continue;
575 }
576
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300577 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300578 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300579 l2cap_build_conf_req(chan, buf), buf);
580 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200581 }
582
583 bh_unlock_sock(sk);
584 }
585
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300586 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200587}
588
Ville Tervob62f3282011-02-10 22:38:50 -0300589/* Find socket with cid and source bdaddr.
590 * Returns closest match, locked.
591 */
592static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
593{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300594 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300595 struct hlist_node *node;
596
597 read_lock(&l2cap_sk_list.lock);
598
599 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300600 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
601
Ville Tervob62f3282011-02-10 22:38:50 -0300602 if (state && sk->sk_state != state)
603 continue;
604
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300605 if (chan->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300606 /* Exact match. */
607 if (!bacmp(&bt_sk(sk)->src, src))
608 break;
609
610 /* Closest match */
611 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
612 sk1 = sk;
613 }
614 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300615
Ville Tervob62f3282011-02-10 22:38:50 -0300616 read_unlock(&l2cap_sk_list.lock);
617
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300618 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300619}
620
621static void l2cap_le_conn_ready(struct l2cap_conn *conn)
622{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300623 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300624 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300625
626 BT_DBG("");
627
628 /* Check if we have socket listening on cid */
629 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
630 conn->src);
631 if (!parent)
632 return;
633
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300634 bh_lock_sock(parent);
635
Ville Tervob62f3282011-02-10 22:38:50 -0300636 /* Check for backlog size */
637 if (sk_acceptq_is_full(parent)) {
638 BT_DBG("backlog full %d", parent->sk_ack_backlog);
639 goto clean;
640 }
641
642 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
643 if (!sk)
644 goto clean;
645
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300646 chan = l2cap_chan_alloc(sk);
647 if (!chan) {
648 l2cap_sock_kill(sk);
649 goto clean;
650 }
651
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300652 l2cap_pi(sk)->chan = chan;
653
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300654 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300655
656 hci_conn_hold(conn->hcon);
657
658 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300659
Ville Tervob62f3282011-02-10 22:38:50 -0300660 bacpy(&bt_sk(sk)->src, conn->src);
661 bacpy(&bt_sk(sk)->dst, conn->dst);
662
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300663 bt_accept_enqueue(parent, sk);
664
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300665 __l2cap_chan_add(conn, chan);
666
Ville Tervob62f3282011-02-10 22:38:50 -0300667 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
668
669 sk->sk_state = BT_CONNECTED;
670 parent->sk_data_ready(parent, 0);
671
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300672 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300673
674clean:
675 bh_unlock_sock(parent);
676}
677
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200678static void l2cap_conn_ready(struct l2cap_conn *conn)
679{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300680 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200681
682 BT_DBG("conn %p", conn);
683
Ville Tervob62f3282011-02-10 22:38:50 -0300684 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
685 l2cap_le_conn_ready(conn);
686
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300687 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200688
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300689 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300690 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300691
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200692 bh_lock_sock(sk);
693
Ville Tervoacd7d372011-02-10 22:38:49 -0300694 if (conn->hcon->type == LE_LINK) {
695 l2cap_sock_clear_timer(sk);
696 sk->sk_state = BT_CONNECTED;
697 sk->sk_state_change(sk);
698 }
699
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300700 if (sk->sk_type != SOCK_SEQPACKET &&
701 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702 l2cap_sock_clear_timer(sk);
703 sk->sk_state = BT_CONNECTED;
704 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200705 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300706 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707
708 bh_unlock_sock(sk);
709 }
710
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300711 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200712}
713
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714/* Notify sockets that we cannot guaranty reliability anymore */
715static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
716{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300717 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718
719 BT_DBG("conn %p", conn);
720
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300721 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200722
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300723 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300724 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300725
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300726 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200727 sk->sk_err = err;
728 }
729
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300730 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200731}
732
733static void l2cap_info_timeout(unsigned long arg)
734{
735 struct l2cap_conn *conn = (void *) arg;
736
Marcel Holtmann984947d2009-02-06 23:35:19 +0100737 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100738 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100739
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200740 l2cap_conn_start(conn);
741}
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
744{
Marcel Holtmann01394182006-07-03 10:02:46 +0200745 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Marcel Holtmann01394182006-07-03 10:02:46 +0200747 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return conn;
749
Marcel Holtmann01394182006-07-03 10:02:46 +0200750 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
751 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
754 hcon->l2cap_data = conn;
755 conn->hcon = hcon;
756
Marcel Holtmann01394182006-07-03 10:02:46 +0200757 BT_DBG("hcon %p conn %p", hcon, conn);
758
Ville Tervoacd7d372011-02-10 22:38:49 -0300759 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
760 conn->mtu = hcon->hdev->le_mtu;
761 else
762 conn->mtu = hcon->hdev->acl_mtu;
763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 conn->src = &hcon->hdev->bdaddr;
765 conn->dst = &hcon->dst;
766
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200767 conn->feat_mask = 0;
768
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300770 rwlock_init(&conn->chan_lock);
771
772 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Ville Tervob62f3282011-02-10 22:38:50 -0300774 if (hcon->type != LE_LINK)
775 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000776 (unsigned long) conn);
777
Marcel Holtmann2950f212009-02-12 14:02:50 +0100778 conn->disc_reason = 0x13;
779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 return conn;
781}
782
Marcel Holtmann01394182006-07-03 10:02:46 +0200783static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
Marcel Holtmann01394182006-07-03 10:02:46 +0200785 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300786 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 struct sock *sk;
788
Marcel Holtmann01394182006-07-03 10:02:46 +0200789 if (!conn)
790 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
793
Wei Yongjun7585b972009-02-25 18:29:52 +0800794 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
796 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300797 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300798 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300800 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 bh_unlock_sock(sk);
802 l2cap_sock_kill(sk);
803 }
804
Dave Young8e8440f2008-03-03 12:18:55 -0800805 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
806 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 hcon->l2cap_data = NULL;
809 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810}
811
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300812static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300814 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300815 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300816 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817}
818
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821/* Find socket with psm and source bdaddr.
822 * Returns closest match.
823 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000824static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
826 struct sock *sk = NULL, *sk1 = NULL;
827 struct hlist_node *node;
828
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000829 read_lock(&l2cap_sk_list.lock);
830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300832 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 if (state && sk->sk_state != state)
835 continue;
836
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300837 if (chan->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 /* Exact match. */
839 if (!bacmp(&bt_sk(sk)->src, src))
840 break;
841
842 /* Closest match */
843 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
844 sk1 = sk;
845 }
846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000849
850 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
852
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300853int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300855 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 bdaddr_t *src = &bt_sk(sk)->src;
857 bdaddr_t *dst = &bt_sk(sk)->dst;
858 struct l2cap_conn *conn;
859 struct hci_conn *hcon;
860 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200861 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200862 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100864 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300865 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300867 hdev = hci_get_route(dst, src);
868 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 return -EHOSTUNREACH;
870
871 hci_dev_lock_bh(hdev);
872
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300873 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200874
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300875 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -0300876 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300877 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300878 else
879 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300880 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300881
Ville Tervo30e76272011-02-22 16:10:53 -0300882 if (IS_ERR(hcon)) {
883 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 conn = l2cap_conn_add(hcon, 0);
888 if (!conn) {
889 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300890 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 goto done;
892 }
893
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 /* Update source addr of the socket */
895 bacpy(src, conn->src);
896
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300897 l2cap_chan_add(conn, chan);
898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 sk->sk_state = BT_CONNECT;
900 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
901
902 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300903 if (sk->sk_type != SOCK_SEQPACKET &&
904 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300906 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +0530907 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200908 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300909 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911
Ville Tervo30e76272011-02-22 16:10:53 -0300912 err = 0;
913
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914done:
915 hci_dev_unlock_bh(hdev);
916 hci_dev_put(hdev);
917 return err;
918}
919
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200920int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300921{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300922 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300923 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. Padovan8c1d7872011-04-13 20:23:55 -0300928 while ((chan->unacked_frames > 0 && chan->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. Padovan8c1d7872011-04-13 20:23:55 -0300961 l2cap_send_disconn_req(chan->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. Padovan8c1d7872011-04-13 20:23:55 -03001011 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001012 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001013
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001014 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001016 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001017 flags = ACL_START_NO_FLUSH;
1018 else
1019 flags = ACL_START;
1020
1021 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001022}
1023
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001024void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001025{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001026 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001027 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001028
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001029 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001030 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001031 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001033
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001034 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001035 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1036 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001037 }
1038
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001039 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001040
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001041 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001042 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001043}
1044
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001045static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001046{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047 struct sk_buff *skb, *tx_skb;
1048 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001049
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001050 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001051 if (!skb)
1052 return;
1053
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001055 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001056 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001058 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001059 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001060
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001061 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001063 if (chan->remote_max_tx &&
1064 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001065 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001066 return;
1067 }
1068
1069 tx_skb = skb_clone(skb, GFP_ATOMIC);
1070 bt_cb(skb)->retries++;
1071 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001072 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001073
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001074 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001075 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001076 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001077 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001078
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001079 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001080 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001081
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001082 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1083
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001084 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001085 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1086 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1087 }
1088
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001089 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001090}
1091
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001092int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001093{
1094 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001095 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001096 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001097 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001098
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001099 if (sk->sk_state != BT_CONNECTED)
1100 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001101
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001102 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001104 if (chan->remote_max_tx &&
1105 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001106 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001107 break;
1108 }
1109
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001110 tx_skb = skb_clone(skb, GFP_ATOMIC);
1111
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001112 bt_cb(skb)->retries++;
1113
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001114 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001115 control &= L2CAP_CTRL_SAR;
1116
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001117 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001118 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001119 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001120 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001121 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1122 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001123 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1124
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001125
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001126 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001127 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1128 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1129 }
1130
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001131 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001132
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001133 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001134
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001135 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1136 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001137
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301138 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001139 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301140
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001141 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001142
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001143 if (skb_queue_is_last(&chan->tx_q, skb))
1144 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001145 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001146 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001147
1148 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001149 }
1150
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001151 return nsent;
1152}
1153
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001154static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001155{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001156 int ret;
1157
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001158 if (!skb_queue_empty(&chan->tx_q))
1159 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001160
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001161 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001162 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001163 return ret;
1164}
1165
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001166static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001167{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001168 u16 control = 0;
1169
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001170 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001171
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001172 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001173 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001174 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1175 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001176 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001178
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001179 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180 return;
1181
1182 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001183 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001184}
1185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001187{
1188 struct srej_list *tail;
1189 u16 control;
1190
1191 control = L2CAP_SUPER_SELECT_REJECT;
1192 control |= L2CAP_CTRL_FINAL;
1193
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001194 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001195 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1196
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001197 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001198}
1199
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001200static 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 -07001201{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001202 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001203 struct sk_buff **frag;
1204 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001206 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209 sent += count;
1210 len -= count;
1211
1212 /* Continuation fragments (no L2CAP header) */
1213 frag = &skb_shinfo(skb)->frag_list;
1214 while (len) {
1215 count = min_t(unsigned int, conn->mtu, len);
1216
1217 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1218 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001219 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001220 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1221 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 sent += count;
1224 len -= count;
1225
1226 frag = &(*frag)->next;
1227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001232struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001233{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001234 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001235 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236 struct sk_buff *skb;
1237 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1238 struct l2cap_hdr *lh;
1239
1240 BT_DBG("sk %p len %d", sk, (int)len);
1241
1242 count = min_t(unsigned int, (conn->mtu - hlen), len);
1243 skb = bt_skb_send_alloc(sk, count + hlen,
1244 msg->msg_flags & MSG_DONTWAIT, &err);
1245 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001246 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247
1248 /* Create L2CAP header */
1249 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001250 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001252 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253
1254 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1255 if (unlikely(err < 0)) {
1256 kfree_skb(skb);
1257 return ERR_PTR(err);
1258 }
1259 return skb;
1260}
1261
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001262struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001263{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001264 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001265 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001266 struct sk_buff *skb;
1267 int err, count, hlen = L2CAP_HDR_SIZE;
1268 struct l2cap_hdr *lh;
1269
1270 BT_DBG("sk %p len %d", sk, (int)len);
1271
1272 count = min_t(unsigned int, (conn->mtu - hlen), len);
1273 skb = bt_skb_send_alloc(sk, count + hlen,
1274 msg->msg_flags & MSG_DONTWAIT, &err);
1275 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001276 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001277
1278 /* Create L2CAP header */
1279 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001280 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001281 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1282
1283 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1284 if (unlikely(err < 0)) {
1285 kfree_skb(skb);
1286 return ERR_PTR(err);
1287 }
1288 return skb;
1289}
1290
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001291struct 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 -03001292{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001293 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001294 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295 struct sk_buff *skb;
1296 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1297 struct l2cap_hdr *lh;
1298
1299 BT_DBG("sk %p len %d", sk, (int)len);
1300
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001301 if (!conn)
1302 return ERR_PTR(-ENOTCONN);
1303
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001304 if (sdulen)
1305 hlen += 2;
1306
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001307 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001308 hlen += 2;
1309
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001310 count = min_t(unsigned int, (conn->mtu - hlen), len);
1311 skb = bt_skb_send_alloc(sk, count + hlen,
1312 msg->msg_flags & MSG_DONTWAIT, &err);
1313 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001314 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001315
1316 /* Create L2CAP header */
1317 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001318 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001319 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1320 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001321 if (sdulen)
1322 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001323
1324 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1325 if (unlikely(err < 0)) {
1326 kfree_skb(skb);
1327 return ERR_PTR(err);
1328 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001329
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001330 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001331 put_unaligned_le16(0, skb_put(skb, 2));
1332
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001333 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335}
1336
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001337int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001338{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001339 struct sk_buff *skb;
1340 struct sk_buff_head sar_queue;
1341 u16 control;
1342 size_t size = 0;
1343
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001344 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001345 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001346 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 if (IS_ERR(skb))
1348 return PTR_ERR(skb);
1349
1350 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001351 len -= chan->remote_mps;
1352 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353
1354 while (len > 0) {
1355 size_t buflen;
1356
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001357 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001358 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001361 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001362 buflen = len;
1363 }
1364
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001365 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 if (IS_ERR(skb)) {
1367 skb_queue_purge(&sar_queue);
1368 return PTR_ERR(skb);
1369 }
1370
1371 __skb_queue_tail(&sar_queue, skb);
1372 len -= buflen;
1373 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001375 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1376 if (chan->tx_send_head == NULL)
1377 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378
1379 return size;
1380}
1381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382static void l2cap_chan_ready(struct sock *sk)
1383{
1384 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001385 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 BT_DBG("sk %p, parent %p", sk, parent);
1388
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001389 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 l2cap_sock_clear_timer(sk);
1391
1392 if (!parent) {
1393 /* Outgoing channel.
1394 * Wake up socket sleeping on connect.
1395 */
1396 sk->sk_state = BT_CONNECTED;
1397 sk->sk_state_change(sk);
1398 } else {
1399 /* Incoming channel.
1400 * Wake up socket sleeping on accept.
1401 */
1402 parent->sk_data_ready(parent, 0);
1403 }
1404}
1405
1406/* Copy frame to all raw sockets on that connection */
1407static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1408{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001410 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412 BT_DBG("conn %p", conn);
1413
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001414 read_lock(&conn->chan_lock);
1415 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001416 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 if (sk->sk_type != SOCK_RAW)
1418 continue;
1419
1420 /* Don't send frame to the socket it came from */
1421 if (skb->sk == sk)
1422 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001423 nskb = skb_clone(skb, GFP_ATOMIC);
1424 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 continue;
1426
1427 if (sock_queue_rcv_skb(sk, nskb))
1428 kfree_skb(nskb);
1429 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001430 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431}
1432
1433/* ---- L2CAP signalling commands ---- */
1434static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1435 u8 code, u8 ident, u16 dlen, void *data)
1436{
1437 struct sk_buff *skb, **frag;
1438 struct l2cap_cmd_hdr *cmd;
1439 struct l2cap_hdr *lh;
1440 int len, count;
1441
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001442 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1443 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1446 count = min_t(unsigned int, conn->mtu, len);
1447
1448 skb = bt_skb_alloc(count, GFP_ATOMIC);
1449 if (!skb)
1450 return NULL;
1451
1452 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001453 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001454
1455 if (conn->hcon->type == LE_LINK)
1456 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1457 else
1458 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1461 cmd->code = code;
1462 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001463 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 if (dlen) {
1466 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1467 memcpy(skb_put(skb, count), data, count);
1468 data += count;
1469 }
1470
1471 len -= skb->len;
1472
1473 /* Continuation fragments (no L2CAP header) */
1474 frag = &skb_shinfo(skb)->frag_list;
1475 while (len) {
1476 count = min_t(unsigned int, conn->mtu, len);
1477
1478 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1479 if (!*frag)
1480 goto fail;
1481
1482 memcpy(skb_put(*frag, count), data, count);
1483
1484 len -= count;
1485 data += count;
1486
1487 frag = &(*frag)->next;
1488 }
1489
1490 return skb;
1491
1492fail:
1493 kfree_skb(skb);
1494 return NULL;
1495}
1496
1497static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1498{
1499 struct l2cap_conf_opt *opt = *ptr;
1500 int len;
1501
1502 len = L2CAP_CONF_OPT_SIZE + opt->len;
1503 *ptr += len;
1504
1505 *type = opt->type;
1506 *olen = opt->len;
1507
1508 switch (opt->len) {
1509 case 1:
1510 *val = *((u8 *) opt->val);
1511 break;
1512
1513 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001514 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 break;
1516
1517 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001518 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 break;
1520
1521 default:
1522 *val = (unsigned long) opt->val;
1523 break;
1524 }
1525
1526 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1527 return len;
1528}
1529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1531{
1532 struct l2cap_conf_opt *opt = *ptr;
1533
1534 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1535
1536 opt->type = type;
1537 opt->len = len;
1538
1539 switch (len) {
1540 case 1:
1541 *((u8 *) opt->val) = val;
1542 break;
1543
1544 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001545 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 break;
1547
1548 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001549 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 break;
1551
1552 default:
1553 memcpy(opt->val, (void *) val, len);
1554 break;
1555 }
1556
1557 *ptr += L2CAP_CONF_OPT_SIZE + len;
1558}
1559
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001560static void l2cap_ack_timeout(unsigned long arg)
1561{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001562 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001564 bh_lock_sock(chan->sk);
1565 l2cap_send_ack(chan);
1566 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001567}
1568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001569static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001570{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571 struct sock *sk = chan->sk;
1572
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001573 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001574 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001575 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001576 chan->num_acked = 0;
1577 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001578
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001579 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1580 (unsigned long) chan);
1581 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1582 (unsigned long) chan);
1583 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001584
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001585 skb_queue_head_init(&chan->srej_q);
1586 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001587
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001588 INIT_LIST_HEAD(&chan->srej_l);
1589
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001590 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001591
1592 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001593}
1594
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001595static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1596{
1597 switch (mode) {
1598 case L2CAP_MODE_STREAMING:
1599 case L2CAP_MODE_ERTM:
1600 if (l2cap_mode_supported(mode, remote_feat_mask))
1601 return mode;
1602 /* fall through */
1603 default:
1604 return L2CAP_MODE_BASIC;
1605 }
1606}
1607
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001608static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001611 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 void *ptr = req->data;
1613
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001614 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001616 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001617 goto done;
1618
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001619 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001620 case L2CAP_MODE_STREAMING:
1621 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001622 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001623 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001624
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001625 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001626 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001627 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001628 break;
1629 }
1630
1631done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001632 if (chan->imtu != L2CAP_DEFAULT_MTU)
1633 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001634
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001635 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001636 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001637 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1638 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001639 break;
1640
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001641 rfc.mode = L2CAP_MODE_BASIC;
1642 rfc.txwin_size = 0;
1643 rfc.max_transmit = 0;
1644 rfc.retrans_timeout = 0;
1645 rfc.monitor_timeout = 0;
1646 rfc.max_pdu_size = 0;
1647
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001648 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1649 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001650 break;
1651
1652 case L2CAP_MODE_ERTM:
1653 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001654 rfc.txwin_size = chan->tx_win;
1655 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001656 rfc.retrans_timeout = 0;
1657 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001658 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001659 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1660 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001661
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001662 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1663 (unsigned long) &rfc);
1664
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001665 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001666 break;
1667
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001668 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001669 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001670 chan->fcs = L2CAP_FCS_NONE;
1671 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001672 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001673 break;
1674
1675 case L2CAP_MODE_STREAMING:
1676 rfc.mode = L2CAP_MODE_STREAMING;
1677 rfc.txwin_size = 0;
1678 rfc.max_transmit = 0;
1679 rfc.retrans_timeout = 0;
1680 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001681 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001682 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1683 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001684
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001685 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1686 (unsigned long) &rfc);
1687
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001688 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001689 break;
1690
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001691 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001692 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001693 chan->fcs = L2CAP_FCS_NONE;
1694 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001695 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001696 break;
1697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001699 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001700 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 return ptr - data;
1703}
1704
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001705static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001707 struct l2cap_conf_rsp *rsp = data;
1708 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001709 void *req = chan->conf_req;
1710 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001711 int type, hint, olen;
1712 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001713 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001714 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001715 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001717 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001718
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001719 while (len >= L2CAP_CONF_OPT_SIZE) {
1720 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001722 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001723 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724
1725 switch (type) {
1726 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001727 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001728 break;
1729
1730 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001731 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001732 break;
1733
1734 case L2CAP_CONF_QOS:
1735 break;
1736
Marcel Holtmann6464f352007-10-20 13:39:51 +02001737 case L2CAP_CONF_RFC:
1738 if (olen == sizeof(rfc))
1739 memcpy(&rfc, (void *) val, olen);
1740 break;
1741
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001742 case L2CAP_CONF_FCS:
1743 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001744 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001745
1746 break;
1747
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001748 default:
1749 if (hint)
1750 break;
1751
1752 result = L2CAP_CONF_UNKNOWN;
1753 *((u8 *) ptr++) = type;
1754 break;
1755 }
1756 }
1757
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001758 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001759 goto done;
1760
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001761 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001762 case L2CAP_MODE_STREAMING:
1763 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001764 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001765 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001766 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001767 break;
1768 }
1769
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001770 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001771 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001772
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001774 }
1775
1776done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001777 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001779 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001781 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782 return -ECONNREFUSED;
1783
1784 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1785 sizeof(rfc), (unsigned long) &rfc);
1786 }
1787
1788
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001789 if (result == L2CAP_CONF_SUCCESS) {
1790 /* Configure output options and let the other side know
1791 * which ones we don't like. */
1792
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001793 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1794 result = L2CAP_CONF_UNACCEPT;
1795 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001796 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001797 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001798 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001799 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001800
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001801 switch (rfc.mode) {
1802 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001803 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001804 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001805 break;
1806
1807 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001808 chan->remote_tx_win = rfc.txwin_size;
1809 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001810
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001811 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1812 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001813
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001814 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001815
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001816 rfc.retrans_timeout =
1817 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1818 rfc.monitor_timeout =
1819 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001820
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001821 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001822
1823 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1824 sizeof(rfc), (unsigned long) &rfc);
1825
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001826 break;
1827
1828 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001829 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1830 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001831
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001832 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001834 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001835
1836 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1837 sizeof(rfc), (unsigned long) &rfc);
1838
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001839 break;
1840
1841 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001842 result = L2CAP_CONF_UNACCEPT;
1843
1844 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001845 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001846 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001847
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001848 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001849 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001851 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001852 rsp->result = cpu_to_le16(result);
1853 rsp->flags = cpu_to_le16(0x0000);
1854
1855 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856}
1857
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001858static 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 -03001859{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001860 struct l2cap_conf_req *req = data;
1861 void *ptr = req->data;
1862 int type, olen;
1863 unsigned long val;
1864 struct l2cap_conf_rfc rfc;
1865
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001866 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001867
1868 while (len >= L2CAP_CONF_OPT_SIZE) {
1869 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1870
1871 switch (type) {
1872 case L2CAP_CONF_MTU:
1873 if (val < L2CAP_DEFAULT_MIN_MTU) {
1874 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001875 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001876 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001877 chan->imtu = val;
1878 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001879 break;
1880
1881 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001882 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001883 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001884 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885 break;
1886
1887 case L2CAP_CONF_RFC:
1888 if (olen == sizeof(rfc))
1889 memcpy(&rfc, (void *)val, olen);
1890
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001891 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001892 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001893 return -ECONNREFUSED;
1894
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001895 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001896
1897 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1898 sizeof(rfc), (unsigned long) &rfc);
1899 break;
1900 }
1901 }
1902
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001903 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001904 return -ECONNREFUSED;
1905
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001906 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001907
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001908 if (*result == L2CAP_CONF_SUCCESS) {
1909 switch (rfc.mode) {
1910 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001911 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1912 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1913 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 break;
1915 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001916 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001917 }
1918 }
1919
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001920 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921 req->flags = cpu_to_le16(0x0000);
1922
1923 return ptr - data;
1924}
1925
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001926static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927{
1928 struct l2cap_conf_rsp *rsp = data;
1929 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001931 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001933 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001934 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001935 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
1937 return ptr - data;
1938}
1939
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001940void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001941{
1942 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001943 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001944 u8 buf[128];
1945
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001946 rsp.scid = cpu_to_le16(chan->dcid);
1947 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001948 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1949 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1950 l2cap_send_cmd(conn, chan->ident,
1951 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1952
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001953 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001954 return;
1955
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001956 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001957 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1958 l2cap_build_conf_req(chan, buf), buf);
1959 chan->num_conf_req++;
1960}
1961
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001962static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001963{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001964 int type, olen;
1965 unsigned long val;
1966 struct l2cap_conf_rfc rfc;
1967
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001968 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001969
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001970 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001971 return;
1972
1973 while (len >= L2CAP_CONF_OPT_SIZE) {
1974 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1975
1976 switch (type) {
1977 case L2CAP_CONF_RFC:
1978 if (olen == sizeof(rfc))
1979 memcpy(&rfc, (void *)val, olen);
1980 goto done;
1981 }
1982 }
1983
1984done:
1985 switch (rfc.mode) {
1986 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001987 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1988 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1989 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001990 break;
1991 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001992 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001993 }
1994}
1995
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001996static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1997{
1998 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1999
2000 if (rej->reason != 0x0000)
2001 return 0;
2002
2003 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2004 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002005 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002006
2007 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002008 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002009
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002010 l2cap_conn_start(conn);
2011 }
2012
2013 return 0;
2014}
2015
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2017{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2019 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002020 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002021 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002022 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
2024 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002025 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
2027 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2028
2029 /* Check if we have socket listening on psm */
2030 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2031 if (!parent) {
2032 result = L2CAP_CR_BAD_PSM;
2033 goto sendresp;
2034 }
2035
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002036 bh_lock_sock(parent);
2037
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002038 /* Check if the ACL is secure enough (if not SDP) */
2039 if (psm != cpu_to_le16(0x0001) &&
2040 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002041 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002042 result = L2CAP_CR_SEC_BLOCK;
2043 goto response;
2044 }
2045
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 result = L2CAP_CR_NO_MEM;
2047
2048 /* Check for backlog size */
2049 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002050 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 goto response;
2052 }
2053
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002054 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 if (!sk)
2056 goto response;
2057
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002058 chan = l2cap_chan_alloc(sk);
2059 if (!chan) {
2060 l2cap_sock_kill(sk);
2061 goto response;
2062 }
2063
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002064 l2cap_pi(sk)->chan = chan;
2065
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002066 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
2068 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002069 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2070 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 sock_set_flag(sk, SOCK_ZAPPED);
2072 l2cap_sock_kill(sk);
2073 goto response;
2074 }
2075
2076 hci_conn_hold(conn->hcon);
2077
2078 l2cap_sock_init(sk, parent);
2079 bacpy(&bt_sk(sk)->src, conn->src);
2080 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002081 chan->psm = psm;
2082 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002084 bt_accept_enqueue(parent, sk);
2085
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002086 __l2cap_chan_add(conn, chan);
2087
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002088 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
2090 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2091
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002092 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Marcel Holtmann984947d2009-02-06 23:35:19 +01002094 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002095 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002096 if (bt_sk(sk)->defer_setup) {
2097 sk->sk_state = BT_CONNECT2;
2098 result = L2CAP_CR_PEND;
2099 status = L2CAP_CS_AUTHOR_PEND;
2100 parent->sk_data_ready(parent, 0);
2101 } else {
2102 sk->sk_state = BT_CONFIG;
2103 result = L2CAP_CR_SUCCESS;
2104 status = L2CAP_CS_NO_INFO;
2105 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002106 } else {
2107 sk->sk_state = BT_CONNECT2;
2108 result = L2CAP_CR_PEND;
2109 status = L2CAP_CS_AUTHEN_PEND;
2110 }
2111 } else {
2112 sk->sk_state = BT_CONNECT2;
2113 result = L2CAP_CR_PEND;
2114 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 }
2116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002117 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
2119response:
2120 bh_unlock_sock(parent);
2121
2122sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002123 rsp.scid = cpu_to_le16(scid);
2124 rsp.dcid = cpu_to_le16(dcid);
2125 rsp.result = cpu_to_le16(result);
2126 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002128
2129 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2130 struct l2cap_info_req info;
2131 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2132
2133 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2134 conn->info_ident = l2cap_get_ident(conn);
2135
2136 mod_timer(&conn->info_timer, jiffies +
2137 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2138
2139 l2cap_send_cmd(conn, conn->info_ident,
2140 L2CAP_INFO_REQ, sizeof(info), &info);
2141 }
2142
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002143 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002144 result == L2CAP_CR_SUCCESS) {
2145 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002146 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002147 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002148 l2cap_build_conf_req(chan, buf), buf);
2149 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002150 }
2151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 return 0;
2153}
2154
2155static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2156{
2157 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2158 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002159 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 struct sock *sk;
2161 u8 req[128];
2162
2163 scid = __le16_to_cpu(rsp->scid);
2164 dcid = __le16_to_cpu(rsp->dcid);
2165 result = __le16_to_cpu(rsp->result);
2166 status = __le16_to_cpu(rsp->status);
2167
2168 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2169
2170 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002171 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002172 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002173 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002175 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002176 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002177 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 }
2179
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002180 sk = chan->sk;
2181
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 switch (result) {
2183 case L2CAP_CR_SUCCESS:
2184 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002185 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002186 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002187 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002188
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002189 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002190 break;
2191
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002192 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002193
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002195 l2cap_build_conf_req(chan, req), req);
2196 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 break;
2198
2199 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002200 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 break;
2202
2203 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002204 /* don't delete l2cap channel if sk is owned by user */
2205 if (sock_owned_by_user(sk)) {
2206 sk->sk_state = BT_DISCONN;
2207 l2cap_sock_clear_timer(sk);
2208 l2cap_sock_set_timer(sk, HZ / 5);
2209 break;
2210 }
2211
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002212 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 break;
2214 }
2215
2216 bh_unlock_sock(sk);
2217 return 0;
2218}
2219
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002220static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002221{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002222 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2223
Mat Martineau8c462b62010-08-24 15:35:42 -07002224 /* FCS is enabled only in ERTM or streaming mode, if one or both
2225 * sides request it.
2226 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002227 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002228 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002229 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002230 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002231}
2232
Al Viro88219a02007-07-29 00:17:25 -07002233static 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 -07002234{
2235 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2236 u16 dcid, flags;
2237 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002238 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002240 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
2242 dcid = __le16_to_cpu(req->dcid);
2243 flags = __le16_to_cpu(req->flags);
2244
2245 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2246
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002247 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002248 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 return -ENOENT;
2250
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002251 sk = chan->sk;
2252
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002253 if (sk->sk_state != BT_CONFIG) {
2254 struct l2cap_cmd_rej rej;
2255
2256 rej.reason = cpu_to_le16(0x0002);
2257 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2258 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002259 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002260 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002261
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002262 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002263 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002264 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002265 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002266 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002267 L2CAP_CONF_REJECT, flags), rsp);
2268 goto unlock;
2269 }
2270
2271 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002272 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2273 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
2275 if (flags & 0x0001) {
2276 /* Incomplete config. Send empty response. */
2277 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002278 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002279 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 goto unlock;
2281 }
2282
2283 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002284 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002285 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002286 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002290 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002291 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002293 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002294 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002295
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002296 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002297 goto unlock;
2298
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002299 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002300 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002301
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002303
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002304 chan->next_tx_seq = 0;
2305 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002306 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002307 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002308 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002311 goto unlock;
2312 }
2313
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002314 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002315 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002316 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002318 l2cap_build_conf_req(chan, buf), buf);
2319 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 }
2321
2322unlock:
2323 bh_unlock_sock(sk);
2324 return 0;
2325}
2326
2327static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2328{
2329 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2330 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002331 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002333 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
2335 scid = __le16_to_cpu(rsp->scid);
2336 flags = __le16_to_cpu(rsp->flags);
2337 result = __le16_to_cpu(rsp->result);
2338
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002339 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2340 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002342 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002343 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 return 0;
2345
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002346 sk = chan->sk;
2347
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 switch (result) {
2349 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002350 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 break;
2352
2353 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002354 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002355 char req[64];
2356
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002357 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002358 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002359 goto done;
2360 }
2361
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002362 /* throw out any old stored conf requests */
2363 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002364 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2365 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002366 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002367 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002368 goto done;
2369 }
2370
2371 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2372 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002373 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002374 if (result != L2CAP_CONF_SUCCESS)
2375 goto done;
2376 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 }
2378
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002379 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002380 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002382 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 goto done;
2384 }
2385
2386 if (flags & 0x01)
2387 goto done;
2388
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002389 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002391 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002392 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002393
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002395 chan->next_tx_seq = 0;
2396 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002397 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002398 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002399 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002400
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 l2cap_chan_ready(sk);
2402 }
2403
2404done:
2405 bh_unlock_sock(sk);
2406 return 0;
2407}
2408
2409static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2410{
2411 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2412 struct l2cap_disconn_rsp rsp;
2413 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002414 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 struct sock *sk;
2416
2417 scid = __le16_to_cpu(req->scid);
2418 dcid = __le16_to_cpu(req->dcid);
2419
2420 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2421
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002422 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002423 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 return 0;
2425
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002426 sk = chan->sk;
2427
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002428 rsp.dcid = cpu_to_le16(chan->scid);
2429 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2431
2432 sk->sk_shutdown = SHUTDOWN_MASK;
2433
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002434 /* don't delete l2cap channel if sk is owned by user */
2435 if (sock_owned_by_user(sk)) {
2436 sk->sk_state = BT_DISCONN;
2437 l2cap_sock_clear_timer(sk);
2438 l2cap_sock_set_timer(sk, HZ / 5);
2439 bh_unlock_sock(sk);
2440 return 0;
2441 }
2442
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002443 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 bh_unlock_sock(sk);
2445
2446 l2cap_sock_kill(sk);
2447 return 0;
2448}
2449
2450static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2451{
2452 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2453 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002454 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 struct sock *sk;
2456
2457 scid = __le16_to_cpu(rsp->scid);
2458 dcid = __le16_to_cpu(rsp->dcid);
2459
2460 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2461
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002462 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 return 0;
2465
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002466 sk = chan->sk;
2467
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002468 /* don't delete l2cap channel if sk is owned by user */
2469 if (sock_owned_by_user(sk)) {
2470 sk->sk_state = BT_DISCONN;
2471 l2cap_sock_clear_timer(sk);
2472 l2cap_sock_set_timer(sk, HZ / 5);
2473 bh_unlock_sock(sk);
2474 return 0;
2475 }
2476
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002477 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 bh_unlock_sock(sk);
2479
2480 l2cap_sock_kill(sk);
2481 return 0;
2482}
2483
2484static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2485{
2486 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 u16 type;
2488
2489 type = __le16_to_cpu(req->type);
2490
2491 BT_DBG("type 0x%4.4x", type);
2492
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002493 if (type == L2CAP_IT_FEAT_MASK) {
2494 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002495 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002496 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2497 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2498 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002499 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002500 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2501 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002502 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002503 l2cap_send_cmd(conn, cmd->ident,
2504 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002505 } else if (type == L2CAP_IT_FIXED_CHAN) {
2506 u8 buf[12];
2507 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2508 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2509 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2510 memcpy(buf + 4, l2cap_fixed_chan, 8);
2511 l2cap_send_cmd(conn, cmd->ident,
2512 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002513 } else {
2514 struct l2cap_info_rsp rsp;
2515 rsp.type = cpu_to_le16(type);
2516 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2517 l2cap_send_cmd(conn, cmd->ident,
2518 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
2521 return 0;
2522}
2523
2524static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2525{
2526 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2527 u16 type, result;
2528
2529 type = __le16_to_cpu(rsp->type);
2530 result = __le16_to_cpu(rsp->result);
2531
2532 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2533
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002534 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2535 if (cmd->ident != conn->info_ident ||
2536 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2537 return 0;
2538
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002539 del_timer(&conn->info_timer);
2540
Ville Tervoadb08ed2010-08-04 09:43:33 +03002541 if (result != L2CAP_IR_SUCCESS) {
2542 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2543 conn->info_ident = 0;
2544
2545 l2cap_conn_start(conn);
2546
2547 return 0;
2548 }
2549
Marcel Holtmann984947d2009-02-06 23:35:19 +01002550 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002551 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002552
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002553 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002554 struct l2cap_info_req req;
2555 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2556
2557 conn->info_ident = l2cap_get_ident(conn);
2558
2559 l2cap_send_cmd(conn, conn->info_ident,
2560 L2CAP_INFO_REQ, sizeof(req), &req);
2561 } else {
2562 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2563 conn->info_ident = 0;
2564
2565 l2cap_conn_start(conn);
2566 }
2567 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002568 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002569 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002570
2571 l2cap_conn_start(conn);
2572 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002573
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 return 0;
2575}
2576
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002577static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002578 u16 to_multiplier)
2579{
2580 u16 max_latency;
2581
2582 if (min > max || min < 6 || max > 3200)
2583 return -EINVAL;
2584
2585 if (to_multiplier < 10 || to_multiplier > 3200)
2586 return -EINVAL;
2587
2588 if (max >= to_multiplier * 8)
2589 return -EINVAL;
2590
2591 max_latency = (to_multiplier * 8 / max) - 1;
2592 if (latency > 499 || latency > max_latency)
2593 return -EINVAL;
2594
2595 return 0;
2596}
2597
2598static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2599 struct l2cap_cmd_hdr *cmd, u8 *data)
2600{
2601 struct hci_conn *hcon = conn->hcon;
2602 struct l2cap_conn_param_update_req *req;
2603 struct l2cap_conn_param_update_rsp rsp;
2604 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002605 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002606
2607 if (!(hcon->link_mode & HCI_LM_MASTER))
2608 return -EINVAL;
2609
2610 cmd_len = __le16_to_cpu(cmd->len);
2611 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2612 return -EPROTO;
2613
2614 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002615 min = __le16_to_cpu(req->min);
2616 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002617 latency = __le16_to_cpu(req->latency);
2618 to_multiplier = __le16_to_cpu(req->to_multiplier);
2619
2620 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2621 min, max, latency, to_multiplier);
2622
2623 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002624
2625 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2626 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002627 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2628 else
2629 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2630
2631 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2632 sizeof(rsp), &rsp);
2633
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002634 if (!err)
2635 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2636
Claudio Takahaside731152011-02-11 19:28:55 -02002637 return 0;
2638}
2639
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002640static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2641 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2642{
2643 int err = 0;
2644
2645 switch (cmd->code) {
2646 case L2CAP_COMMAND_REJ:
2647 l2cap_command_rej(conn, cmd, data);
2648 break;
2649
2650 case L2CAP_CONN_REQ:
2651 err = l2cap_connect_req(conn, cmd, data);
2652 break;
2653
2654 case L2CAP_CONN_RSP:
2655 err = l2cap_connect_rsp(conn, cmd, data);
2656 break;
2657
2658 case L2CAP_CONF_REQ:
2659 err = l2cap_config_req(conn, cmd, cmd_len, data);
2660 break;
2661
2662 case L2CAP_CONF_RSP:
2663 err = l2cap_config_rsp(conn, cmd, data);
2664 break;
2665
2666 case L2CAP_DISCONN_REQ:
2667 err = l2cap_disconnect_req(conn, cmd, data);
2668 break;
2669
2670 case L2CAP_DISCONN_RSP:
2671 err = l2cap_disconnect_rsp(conn, cmd, data);
2672 break;
2673
2674 case L2CAP_ECHO_REQ:
2675 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2676 break;
2677
2678 case L2CAP_ECHO_RSP:
2679 break;
2680
2681 case L2CAP_INFO_REQ:
2682 err = l2cap_information_req(conn, cmd, data);
2683 break;
2684
2685 case L2CAP_INFO_RSP:
2686 err = l2cap_information_rsp(conn, cmd, data);
2687 break;
2688
2689 default:
2690 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2691 err = -EINVAL;
2692 break;
2693 }
2694
2695 return err;
2696}
2697
2698static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2699 struct l2cap_cmd_hdr *cmd, u8 *data)
2700{
2701 switch (cmd->code) {
2702 case L2CAP_COMMAND_REJ:
2703 return 0;
2704
2705 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002706 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002707
2708 case L2CAP_CONN_PARAM_UPDATE_RSP:
2709 return 0;
2710
2711 default:
2712 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2713 return -EINVAL;
2714 }
2715}
2716
2717static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2718 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719{
2720 u8 *data = skb->data;
2721 int len = skb->len;
2722 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002723 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
2725 l2cap_raw_recv(conn, skb);
2726
2727 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002728 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2730 data += L2CAP_CMD_HDR_SIZE;
2731 len -= L2CAP_CMD_HDR_SIZE;
2732
Al Viro88219a02007-07-29 00:17:25 -07002733 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
Al Viro88219a02007-07-29 00:17:25 -07002735 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 -07002736
Al Viro88219a02007-07-29 00:17:25 -07002737 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 BT_DBG("corrupted command");
2739 break;
2740 }
2741
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002742 if (conn->hcon->type == LE_LINK)
2743 err = l2cap_le_sig_cmd(conn, &cmd, data);
2744 else
2745 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
2747 if (err) {
2748 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002749
2750 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751
2752 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002753 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2755 }
2756
Al Viro88219a02007-07-29 00:17:25 -07002757 data += cmd_len;
2758 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 }
2760
2761 kfree_skb(skb);
2762}
2763
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002764static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002765{
2766 u16 our_fcs, rcv_fcs;
2767 int hdr_size = L2CAP_HDR_SIZE + 2;
2768
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002769 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002770 skb_trim(skb, skb->len - 2);
2771 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2772 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2773
2774 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002775 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002776 }
2777 return 0;
2778}
2779
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002780static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002781{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002782 u16 control = 0;
2783
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002784 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002785
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002786 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002787
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002788 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002789 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002790 l2cap_send_sframe(chan, control);
2791 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002792 }
2793
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002794 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2795 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002797 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002798
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002799 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002800 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002801 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002802 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002803 }
2804}
2805
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002806static 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 -03002807{
2808 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002809 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002810
2811 bt_cb(skb)->tx_seq = tx_seq;
2812 bt_cb(skb)->sar = sar;
2813
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002814 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002815 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002816 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002817 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002818 }
2819
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002820 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002821 if (tx_seq_offset < 0)
2822 tx_seq_offset += 64;
2823
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002824 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002825 if (bt_cb(next_skb)->tx_seq == tx_seq)
2826 return -EINVAL;
2827
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002828 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002829 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002830 if (next_tx_seq_offset < 0)
2831 next_tx_seq_offset += 64;
2832
2833 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002834 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002835 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002836 }
2837
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002838 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002839 break;
2840
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002841 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002842
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002843 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002844
2845 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846}
2847
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002848static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002849{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002850 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002851 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002852
2853 switch (control & L2CAP_CTRL_SAR) {
2854 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002855 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002856 goto drop;
2857
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002858 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859 if (!err)
2860 return err;
2861
2862 break;
2863
2864 case L2CAP_SDU_START:
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. Padovan6f61fd472011-03-25 20:09:37 -03002868 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002869
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002870 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002871 goto disconnect;
2872
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002873 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2874 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002875 return -ENOMEM;
2876
2877 /* pull sdu_len bytes only after alloc, because of Local Busy
2878 * condition we have to be sure that this will be executed
2879 * only once, i.e., when alloc does not fail */
2880 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002881
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002882 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002883
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002884 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002885 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002886 break;
2887
2888 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002889 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002890 goto disconnect;
2891
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002892 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002893 goto disconnect;
2894
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002895 chan->partial_sdu_len += skb->len;
2896 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897 goto drop;
2898
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002899 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002900
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901 break;
2902
2903 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002904 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002905 goto disconnect;
2906
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002907 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 goto disconnect;
2909
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002910 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002911 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002913 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002914 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002915
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002916 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002917 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002918
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002919 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002920 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002921
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002922 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002923 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002924 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 return -ENOMEM;
2926 }
2927
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002928 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002929 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002930 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002931 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932 return err;
2933 }
2934
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002935 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2936 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002937
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002938 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002939 break;
2940 }
2941
2942 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002943 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002944
2945drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002946 kfree_skb(chan->sdu);
2947 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948
2949disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002950 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002951 kfree_skb(skb);
2952 return 0;
2953}
2954
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002955static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002956{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002957 struct sk_buff *skb;
2958 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002959 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002960
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002961 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002962 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002963 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002964 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002965 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002966 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967 }
2968
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002969 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002970 }
2971
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002972 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002973 goto done;
2974
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002975 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002976 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002977 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002978 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002980 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002981 __mod_monitor_timer();
2982
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002983 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002984
2985done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002986 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2987 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002989 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002990
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002991 return 0;
2992}
2993
2994static void l2cap_busy_work(struct work_struct *work)
2995{
2996 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03002997 struct l2cap_chan *chan =
2998 container_of(work, struct l2cap_chan, busy_work);
2999 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003000 int n_tries = 0, timeo = HZ/5, err;
3001 struct sk_buff *skb;
3002
3003 lock_sock(sk);
3004
3005 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003006 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003007 set_current_state(TASK_INTERRUPTIBLE);
3008
3009 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3010 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003011 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003012 break;
3013 }
3014
3015 if (!timeo)
3016 timeo = HZ/5;
3017
3018 if (signal_pending(current)) {
3019 err = sock_intr_errno(timeo);
3020 break;
3021 }
3022
3023 release_sock(sk);
3024 timeo = schedule_timeout(timeo);
3025 lock_sock(sk);
3026
3027 err = sock_error(sk);
3028 if (err)
3029 break;
3030
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003031 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003032 break;
3033 }
3034
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003035 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003036 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003037
3038 release_sock(sk);
3039}
3040
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003041static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003042{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003043 int sctrl, err;
3044
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003045 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003046 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003047 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003048 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003049
3050
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003051 }
3052
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003053 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003055 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 return err;
3057 }
3058
3059 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003060 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003061
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003064 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003065
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003066 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003067 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003069
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003072 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003073
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003074 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003075
3076 return err;
3077}
3078
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003079static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003080{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003081 struct sk_buff *_skb;
3082 int err = -EINVAL;
3083
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003084 /*
3085 * TODO: We have to notify the userland if some data is lost with the
3086 * Streaming Mode.
3087 */
3088
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003089 switch (control & L2CAP_CTRL_SAR) {
3090 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003091 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003092 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003093 break;
3094 }
3095
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003096 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097 if (!err)
3098 return 0;
3099
3100 break;
3101
3102 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003103 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003104 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003105 break;
3106 }
3107
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003108 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003109 skb_pull(skb, 2);
3110
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003111 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003112 err = -EMSGSIZE;
3113 break;
3114 }
3115
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003116 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3117 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003118 err = -ENOMEM;
3119 break;
3120 }
3121
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003122 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003123
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003124 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003125 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003126 err = 0;
3127 break;
3128
3129 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003130 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003131 break;
3132
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003133 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003134
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003135 chan->partial_sdu_len += skb->len;
3136 if (chan->partial_sdu_len > chan->sdu_len)
3137 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003138 else
3139 err = 0;
3140
3141 break;
3142
3143 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003144 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003145 break;
3146
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003147 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003148
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003149 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003150 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003151
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003152 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003153 goto drop;
3154
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003155 if (chan->partial_sdu_len == chan->sdu_len) {
3156 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003157 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003158 if (err < 0)
3159 kfree_skb(_skb);
3160 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161 err = 0;
3162
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003163drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003164 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003165 break;
3166 }
3167
3168 kfree_skb(skb);
3169 return err;
3170}
3171
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003172static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003173{
3174 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003175 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003176
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003177 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003178 if (bt_cb(skb)->tx_seq != tx_seq)
3179 break;
3180
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003181 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003182 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003183 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003184 chan->buffer_seq_srej =
3185 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003186 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003187 }
3188}
3189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003192 struct srej_list *l, *tmp;
3193 u16 control;
3194
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003195 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003196 if (l->tx_seq == tx_seq) {
3197 list_del(&l->list);
3198 kfree(l);
3199 return;
3200 }
3201 control = L2CAP_SUPER_SELECT_REJECT;
3202 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003203 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003205 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 }
3207}
3208
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003209static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003211 struct srej_list *new;
3212 u16 control;
3213
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003214 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003215 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003216 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003218
3219 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003220 new->tx_seq = chan->expected_tx_seq;
3221 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003222 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003223 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003224 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225}
3226
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003227static 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 -03003228{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003229 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003230 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003232 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003233 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003234 int err = 0;
3235
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003236 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3237 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003238
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003239 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003240 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003241 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003242 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003243 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003244 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003245 }
3246
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003247 chan->expected_ack_seq = req_seq;
3248 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003249
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003250 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003251 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003252
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003253 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003254 if (tx_seq_offset < 0)
3255 tx_seq_offset += 64;
3256
3257 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003258 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003259 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003260 goto drop;
3261 }
3262
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003263 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003264 goto drop;
3265
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003266 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003267 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003268
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003269 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003270 struct srej_list, list);
3271 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003272 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003273 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003274
3275 list_del(&first->list);
3276 kfree(first);
3277
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003278 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003279 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003280 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3281 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003282 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003283 }
3284 } else {
3285 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003286
3287 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003288 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003289 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003290
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003291 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003293 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003294 return 0;
3295 }
3296 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003297 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003298 }
3299 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003300 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003301 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003302 if (expected_tx_seq_offset < 0)
3303 expected_tx_seq_offset += 64;
3304
3305 /* duplicated tx_seq */
3306 if (tx_seq_offset < expected_tx_seq_offset)
3307 goto drop;
3308
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003309 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003310
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003311 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003312
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003313 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003314 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003315
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003316 __skb_queue_head_init(&chan->srej_q);
3317 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003318 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003319
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003320 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003321
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003322 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003323
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003324 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003325 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003326 return 0;
3327
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003328expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003329 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003332 bt_cb(skb)->tx_seq = tx_seq;
3333 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003334 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335 return 0;
3336 }
3337
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003338 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003339 if (err < 0)
3340 return 0;
3341
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003342 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003343 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3344 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003345 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003346 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003347 }
3348
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003349 __mod_ack_timer();
3350
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003351 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3352 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003354
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003355 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003356
3357drop:
3358 kfree_skb(skb);
3359 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003360}
3361
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003363{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003364 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003365 rx_control);
3366
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003367 chan->expected_ack_seq = __get_reqseq(rx_control);
3368 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003369
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003370 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3372 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3373 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003374 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003375 __mod_retrans_timer();
3376
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003377 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3378 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003379 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003380 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003381 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003382
3383 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003385
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3387 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003388 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003389 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003390
3391 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003392 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003393 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 __mod_retrans_timer();
3395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003396 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3397 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3398 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003399 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003400 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401 }
3402}
3403
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003405{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406 u8 tx_seq = __get_reqseq(rx_control);
3407
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003411
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003412 chan->expected_ack_seq = tx_seq;
3413 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003414
3415 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3417 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003418 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3424 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 }
3426}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003428{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429 u8 tx_seq = __get_reqseq(rx_control);
3430
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003431 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003432
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003433 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003434
3435 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003436 chan->expected_ack_seq = tx_seq;
3437 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003438
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003439 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3440 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003445 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003447 }
3448 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003449 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003450 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003452 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003454 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 l2cap_retransmit_one_frame(chan, tx_seq);
3456 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003457 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003459 }
3460 }
3461}
3462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003464{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003465 u8 tx_seq = __get_reqseq(rx_control);
3466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003468
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003470 chan->expected_ack_seq = tx_seq;
3471 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003472
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003473 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003475
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003477 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003478 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003480 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003481 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003482
3483 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003485 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003487}
3488
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003489static 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 -03003490{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003492
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003493 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003494 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003495 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003496 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003497 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003499 }
3500
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003501 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3502 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003504 break;
3505
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003506 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003508 break;
3509
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003510 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003511 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003512 break;
3513
3514 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003516 break;
3517 }
3518
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003519 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003520 return 0;
3521}
3522
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003523static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3524{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003526 u16 control;
3527 u8 req_seq;
3528 int len, next_tx_seq_offset, req_seq_offset;
3529
3530 control = get_unaligned_le16(skb->data);
3531 skb_pull(skb, 2);
3532 len = skb->len;
3533
3534 /*
3535 * We can just drop the corrupted I-frame here.
3536 * Receiver will miss it and start proper recovery
3537 * procedures and ask retransmission.
3538 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003539 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003540 goto drop;
3541
3542 if (__is_sar_start(control) && __is_iframe(control))
3543 len -= 2;
3544
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003545 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003546 len -= 2;
3547
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003548 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003549 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003550 goto drop;
3551 }
3552
3553 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003554 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003555 if (req_seq_offset < 0)
3556 req_seq_offset += 64;
3557
3558 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003559 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003560 if (next_tx_seq_offset < 0)
3561 next_tx_seq_offset += 64;
3562
3563 /* check for invalid req-seq */
3564 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003565 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003566 goto drop;
3567 }
3568
3569 if (__is_iframe(control)) {
3570 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003571 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003572 goto drop;
3573 }
3574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003575 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003576 } else {
3577 if (len != 0) {
3578 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003579 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 goto drop;
3581 }
3582
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003583 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003584 }
3585
3586 return 0;
3587
3588drop:
3589 kfree_skb(skb);
3590 return 0;
3591}
3592
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3594{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003595 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003597 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003598 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003599 u8 tx_seq;
3600 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003602 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003603 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604 BT_DBG("unknown cid 0x%4.4x", cid);
3605 goto drop;
3606 }
3607
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003608 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003609 pi = l2cap_pi(sk);
3610
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003611 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
3613 if (sk->sk_state != BT_CONNECTED)
3614 goto drop;
3615
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003616 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003617 case L2CAP_MODE_BASIC:
3618 /* If socket recv buffers overflows we drop data here
3619 * which is *bad* because L2CAP has to be reliable.
3620 * But we don't have any other choice. L2CAP doesn't
3621 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003623 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003624 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003626 if (!sock_queue_rcv_skb(sk, skb))
3627 goto done;
3628 break;
3629
3630 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003631 if (!sock_owned_by_user(sk)) {
3632 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003633 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003634 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003635 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003636 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003637
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003638 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003639
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003640 case L2CAP_MODE_STREAMING:
3641 control = get_unaligned_le16(skb->data);
3642 skb_pull(skb, 2);
3643 len = skb->len;
3644
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003645 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003646 goto drop;
3647
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003648 if (__is_sar_start(control))
3649 len -= 2;
3650
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003651 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003652 len -= 2;
3653
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003654 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003655 goto drop;
3656
3657 tx_seq = __get_txseq(control);
3658
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003659 if (chan->expected_tx_seq == tx_seq)
3660 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003661 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003662 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003663
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003664 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665
3666 goto done;
3667
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003668 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003669 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003670 break;
3671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672
3673drop:
3674 kfree_skb(skb);
3675
3676done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003677 if (sk)
3678 bh_unlock_sock(sk);
3679
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 return 0;
3681}
3682
Al Viro8e036fc2007-07-29 00:16:36 -07003683static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684{
3685 struct sock *sk;
3686
3687 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3688 if (!sk)
3689 goto drop;
3690
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003691 bh_lock_sock(sk);
3692
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 BT_DBG("sk %p, len %d", sk, skb->len);
3694
3695 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3696 goto drop;
3697
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003698 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699 goto drop;
3700
3701 if (!sock_queue_rcv_skb(sk, skb))
3702 goto done;
3703
3704drop:
3705 kfree_skb(skb);
3706
3707done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003708 if (sk)
3709 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 return 0;
3711}
3712
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003713static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3714{
3715 struct sock *sk;
3716
3717 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3718 if (!sk)
3719 goto drop;
3720
3721 bh_lock_sock(sk);
3722
3723 BT_DBG("sk %p, len %d", sk, skb->len);
3724
3725 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3726 goto drop;
3727
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003728 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003729 goto drop;
3730
3731 if (!sock_queue_rcv_skb(sk, skb))
3732 goto done;
3733
3734drop:
3735 kfree_skb(skb);
3736
3737done:
3738 if (sk)
3739 bh_unlock_sock(sk);
3740 return 0;
3741}
3742
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3744{
3745 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003746 u16 cid, len;
3747 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
3749 skb_pull(skb, L2CAP_HDR_SIZE);
3750 cid = __le16_to_cpu(lh->cid);
3751 len = __le16_to_cpu(lh->len);
3752
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003753 if (len != skb->len) {
3754 kfree_skb(skb);
3755 return;
3756 }
3757
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3759
3760 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003761 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003762 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 l2cap_sig_channel(conn, skb);
3764 break;
3765
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003766 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003767 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 skb_pull(skb, 2);
3769 l2cap_conless_channel(conn, psm, skb);
3770 break;
3771
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003772 case L2CAP_CID_LE_DATA:
3773 l2cap_att_channel(conn, cid, skb);
3774 break;
3775
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 default:
3777 l2cap_data_channel(conn, cid, skb);
3778 break;
3779 }
3780}
3781
3782/* ---- L2CAP interface with lower layer (HCI) ---- */
3783
3784static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3785{
3786 int exact = 0, lm1 = 0, lm2 = 0;
3787 register struct sock *sk;
3788 struct hlist_node *node;
3789
3790 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003791 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
3793 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3794
3795 /* Find listening sockets and check their link_mode */
3796 read_lock(&l2cap_sk_list.lock);
3797 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003798 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
3799
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 if (sk->sk_state != BT_LISTEN)
3801 continue;
3802
3803 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003804 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003805 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003806 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003808 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3809 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003810 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003811 lm2 |= HCI_LM_MASTER;
3812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 }
3814 read_unlock(&l2cap_sk_list.lock);
3815
3816 return exact ? lm1 : lm2;
3817}
3818
3819static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3820{
Marcel Holtmann01394182006-07-03 10:02:46 +02003821 struct l2cap_conn *conn;
3822
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3824
Ville Tervoacd7d372011-02-10 22:38:49 -03003825 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003826 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827
3828 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 conn = l2cap_conn_add(hcon, status);
3830 if (conn)
3831 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003832 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 l2cap_conn_del(hcon, bt_err(status));
3834
3835 return 0;
3836}
3837
Marcel Holtmann2950f212009-02-12 14:02:50 +01003838static int l2cap_disconn_ind(struct hci_conn *hcon)
3839{
3840 struct l2cap_conn *conn = hcon->l2cap_data;
3841
3842 BT_DBG("hcon %p", hcon);
3843
3844 if (hcon->type != ACL_LINK || !conn)
3845 return 0x13;
3846
3847 return conn->disc_reason;
3848}
3849
3850static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851{
3852 BT_DBG("hcon %p reason %d", hcon, reason);
3853
Ville Tervoacd7d372011-02-10 22:38:49 -03003854 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003855 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
3857 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003858
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 return 0;
3860}
3861
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003862static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003863{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003864 struct sock *sk = chan->sk;
3865
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003866 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003867 return;
3868
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003869 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003870 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003871 l2cap_sock_clear_timer(sk);
3872 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003873 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003874 __l2cap_sock_close(sk, ECONNREFUSED);
3875 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003876 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003877 l2cap_sock_clear_timer(sk);
3878 }
3879}
3880
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003881static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003883 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003884 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885
Marcel Holtmann01394182006-07-03 10:02:46 +02003886 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003888
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 BT_DBG("conn %p", conn);
3890
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003891 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003893 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003894 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003895
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 bh_lock_sock(sk);
3897
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003898 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003899 bh_unlock_sock(sk);
3900 continue;
3901 }
3902
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003903 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003904 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003905 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003906 bh_unlock_sock(sk);
3907 continue;
3908 }
3909
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003910 if (sk->sk_state == BT_CONNECT) {
3911 if (!status) {
3912 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003913 req.scid = cpu_to_le16(chan->scid);
3914 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003915
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003916 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003917 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003918
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003919 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003920 L2CAP_CONN_REQ, sizeof(req), &req);
3921 } else {
3922 l2cap_sock_clear_timer(sk);
3923 l2cap_sock_set_timer(sk, HZ / 10);
3924 }
3925 } else if (sk->sk_state == BT_CONNECT2) {
3926 struct l2cap_conn_rsp rsp;
3927 __u16 result;
3928
3929 if (!status) {
3930 sk->sk_state = BT_CONFIG;
3931 result = L2CAP_CR_SUCCESS;
3932 } else {
3933 sk->sk_state = BT_DISCONN;
3934 l2cap_sock_set_timer(sk, HZ / 10);
3935 result = L2CAP_CR_SEC_BLOCK;
3936 }
3937
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003938 rsp.scid = cpu_to_le16(chan->dcid);
3939 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003940 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003941 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003942 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3943 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 }
3945
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 bh_unlock_sock(sk);
3947 }
3948
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003949 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003950
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 return 0;
3952}
3953
3954static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3955{
3956 struct l2cap_conn *conn = hcon->l2cap_data;
3957
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003958 if (!conn)
3959 conn = l2cap_conn_add(hcon, 0);
3960
3961 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 goto drop;
3963
3964 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3965
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003966 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003968 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003969 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 int len;
3971
3972 if (conn->rx_len) {
3973 BT_ERR("Unexpected start frame (len %d)", skb->len);
3974 kfree_skb(conn->rx_skb);
3975 conn->rx_skb = NULL;
3976 conn->rx_len = 0;
3977 l2cap_conn_unreliable(conn, ECOMM);
3978 }
3979
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003980 /* Start fragment always begin with Basic L2CAP header */
3981 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 BT_ERR("Frame is too short (len %d)", skb->len);
3983 l2cap_conn_unreliable(conn, ECOMM);
3984 goto drop;
3985 }
3986
3987 hdr = (struct l2cap_hdr *) skb->data;
3988 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003989 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
3991 if (len == skb->len) {
3992 /* Complete frame received */
3993 l2cap_recv_frame(conn, skb);
3994 return 0;
3995 }
3996
3997 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3998
3999 if (skb->len > len) {
4000 BT_ERR("Frame is too long (len %d, expected len %d)",
4001 skb->len, len);
4002 l2cap_conn_unreliable(conn, ECOMM);
4003 goto drop;
4004 }
4005
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004006 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004007
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004008 if (chan && chan->sk) {
4009 struct sock *sk = chan->sk;
4010
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004011 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004012 BT_ERR("Frame exceeding recv MTU (len %d, "
4013 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004014 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004015 bh_unlock_sock(sk);
4016 l2cap_conn_unreliable(conn, ECOMM);
4017 goto drop;
4018 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004019 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004020 }
4021
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004023 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4024 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 goto drop;
4026
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004027 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004028 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 conn->rx_len = len - skb->len;
4030 } else {
4031 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4032
4033 if (!conn->rx_len) {
4034 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4035 l2cap_conn_unreliable(conn, ECOMM);
4036 goto drop;
4037 }
4038
4039 if (skb->len > conn->rx_len) {
4040 BT_ERR("Fragment is too long (len %d, expected %d)",
4041 skb->len, conn->rx_len);
4042 kfree_skb(conn->rx_skb);
4043 conn->rx_skb = NULL;
4044 conn->rx_len = 0;
4045 l2cap_conn_unreliable(conn, ECOMM);
4046 goto drop;
4047 }
4048
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004049 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004050 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 conn->rx_len -= skb->len;
4052
4053 if (!conn->rx_len) {
4054 /* Complete frame received */
4055 l2cap_recv_frame(conn, conn->rx_skb);
4056 conn->rx_skb = NULL;
4057 }
4058 }
4059
4060drop:
4061 kfree_skb(skb);
4062 return 0;
4063}
4064
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004065static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066{
4067 struct sock *sk;
4068 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
4070 read_lock_bh(&l2cap_sk_list.lock);
4071
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004072 sk_for_each(sk, node, &l2cap_sk_list.head) {
4073 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004074 struct l2cap_chan *chan = pi->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004076 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 +01004077 batostr(&bt_sk(sk)->src),
4078 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004079 sk->sk_state, __le16_to_cpu(chan->psm),
4080 chan->scid, chan->dcid,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004081 chan->imtu, chan->omtu, chan->sec_level,
4082 chan->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004086
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004087 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088}
4089
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004090static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4091{
4092 return single_open(file, l2cap_debugfs_show, inode->i_private);
4093}
4094
4095static const struct file_operations l2cap_debugfs_fops = {
4096 .open = l2cap_debugfs_open,
4097 .read = seq_read,
4098 .llseek = seq_lseek,
4099 .release = single_release,
4100};
4101
4102static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104static struct hci_proto l2cap_hci_proto = {
4105 .name = "L2CAP",
4106 .id = HCI_PROTO_L2CAP,
4107 .connect_ind = l2cap_connect_ind,
4108 .connect_cfm = l2cap_connect_cfm,
4109 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004110 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004111 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 .recv_acldata = l2cap_recv_acldata
4113};
4114
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004115int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116{
4117 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004118
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004119 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 if (err < 0)
4121 return err;
4122
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004123 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004124 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004125 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 goto error;
4127 }
4128
4129 err = hci_register_proto(&l2cap_hci_proto);
4130 if (err < 0) {
4131 BT_ERR("L2CAP protocol registration failed");
4132 bt_sock_unregister(BTPROTO_L2CAP);
4133 goto error;
4134 }
4135
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004136 if (bt_debugfs) {
4137 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4138 bt_debugfs, NULL, &l2cap_debugfs_fops);
4139 if (!l2cap_debugfs)
4140 BT_ERR("Failed to create L2CAP debug file");
4141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 return 0;
4144
4145error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004146 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004147 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 return err;
4149}
4150
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004151void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004153 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004155 flush_workqueue(_busy_wq);
4156 destroy_workqueue(_busy_wq);
4157
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4159 BT_ERR("L2CAP protocol unregistration failed");
4160
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004161 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162}
4163
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004164module_param(disable_ertm, bool, 0644);
4165MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");