blob: a378acc491ec687a009a5c59ca4d254d62f47e2b [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
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. Padovan6ff5abb2011-04-25 15:10:41 -0300163void l2cap_chan_free(struct l2cap_chan *chan)
164{
165 kfree(chan);
166}
167
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300168static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200169{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300170 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300172 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300173 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200174
Marcel Holtmann2950f212009-02-12 14:02:50 +0100175 conn->disc_reason = 0x13;
176
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300177 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200178
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300179 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300180 if (conn->hcon->type == LE_LINK) {
181 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300182 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300183 chan->scid = L2CAP_CID_LE_DATA;
184 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300185 } else {
186 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300187 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300188 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300189 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200190 } else if (sk->sk_type == SOCK_DGRAM) {
191 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300192 chan->scid = L2CAP_CID_CONN_LESS;
193 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300194 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200195 } else {
196 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300197 chan->scid = L2CAP_CID_SIGNALING;
198 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300199 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200200 }
201
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300202 sock_hold(sk);
203
204 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200205}
206
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900207/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200208 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300209void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200210{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300211 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300212 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200213 struct sock *parent = bt_sk(sk)->parent;
214
215 l2cap_sock_clear_timer(sk);
216
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300217 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200218
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900219 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300220 /* Delete from channel list */
221 write_lock_bh(&conn->chan_lock);
222 list_del(&chan->list);
223 write_unlock_bh(&conn->chan_lock);
224 __sock_put(sk);
225
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300226 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200227 hci_conn_put(conn->hcon);
228 }
229
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200230 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200231 sock_set_flag(sk, SOCK_ZAPPED);
232
233 if (err)
234 sk->sk_err = err;
235
236 if (parent) {
237 bt_accept_unlink(sk);
238 parent->sk_data_ready(parent, 0);
239 } else
240 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300241
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300242 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
243 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300244 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300245
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300246 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300247
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300248 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300249 struct srej_list *l, *tmp;
250
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300251 del_timer(&chan->retrans_timer);
252 del_timer(&chan->monitor_timer);
253 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300255 skb_queue_purge(&chan->srej_q);
256 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300257
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300258 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300259 list_del(&l->list);
260 kfree(l);
261 }
262 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300265static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530266{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300267 struct sock *sk = chan->sk;
268
Johan Hedberg8556edd32011-01-19 12:06:50 +0530269 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300270 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530271 case BT_SECURITY_HIGH:
272 return HCI_AT_DEDICATED_BONDING_MITM;
273 case BT_SECURITY_MEDIUM:
274 return HCI_AT_DEDICATED_BONDING;
275 default:
276 return HCI_AT_NO_BONDING;
277 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300278 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300279 if (chan->sec_level == BT_SECURITY_LOW)
280 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530281
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300282 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530283 return HCI_AT_NO_BONDING_MITM;
284 else
285 return HCI_AT_NO_BONDING;
286 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300287 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530288 case BT_SECURITY_HIGH:
289 return HCI_AT_GENERAL_BONDING_MITM;
290 case BT_SECURITY_MEDIUM:
291 return HCI_AT_GENERAL_BONDING;
292 default:
293 return HCI_AT_NO_BONDING;
294 }
295 }
296}
297
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300299static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200300{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300301 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100302 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200303
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300304 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100305
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300306 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200307}
308
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200309u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200310{
311 u8 id;
312
313 /* Get next available identificator.
314 * 1 - 128 are used by kernel.
315 * 129 - 199 are reserved.
316 * 200 - 254 are used by utilities like l2ping, etc.
317 */
318
319 spin_lock_bh(&conn->lock);
320
321 if (++conn->tx_ident > 128)
322 conn->tx_ident = 1;
323
324 id = conn->tx_ident;
325
326 spin_unlock_bh(&conn->lock);
327
328 return id;
329}
330
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200331void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200332{
333 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200334 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200335
336 BT_DBG("code 0x%2.2x", code);
337
338 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300339 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200340
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200341 if (lmp_no_flush_capable(conn->hcon->hdev))
342 flags = ACL_START_NO_FLUSH;
343 else
344 flags = ACL_START;
345
346 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200347}
348
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300349static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300350{
351 struct sk_buff *skb;
352 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300353 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300354 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300355 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200357 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300358
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300359 if (sk->sk_state != BT_CONNECTED)
360 return;
361
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300362 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300363 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300364
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300365 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300366
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300367 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300368 control |= L2CAP_CTRL_FRAME_TYPE;
369
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300370 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300371 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300372 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300373 }
374
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300375 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300376 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300377 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300378 }
379
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300380 skb = bt_skb_alloc(count, GFP_ATOMIC);
381 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300382 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300383
384 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300385 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300386 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300387 put_unaligned_le16(control, skb_put(skb, 2));
388
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300389 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300390 u16 fcs = crc16(0, (u8 *)lh, count - 2);
391 put_unaligned_le16(fcs, skb_put(skb, 2));
392 }
393
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200394 if (lmp_no_flush_capable(conn->hcon->hdev))
395 flags = ACL_START_NO_FLUSH;
396 else
397 flags = ACL_START;
398
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300399 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300400}
401
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300402static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300403{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300404 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300405 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300406 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300407 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300408 control |= L2CAP_SUPER_RCV_READY;
409
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300410 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300411
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300412 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300413}
414
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300415static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300416{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300417 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300418}
419
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300420static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200421{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300422 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200423
424 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100425 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
426 return;
427
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300428 if (l2cap_check_security(chan) &&
429 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200430 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300431 req.scid = cpu_to_le16(chan->scid);
432 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200433
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300434 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300435 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200436
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300437 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
438 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200439 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200440 } else {
441 struct l2cap_info_req req;
442 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
443
444 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
445 conn->info_ident = l2cap_get_ident(conn);
446
447 mod_timer(&conn->info_timer, jiffies +
448 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
449
450 l2cap_send_cmd(conn, conn->info_ident,
451 L2CAP_INFO_REQ, sizeof(req), &req);
452 }
453}
454
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300455static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
456{
457 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300458 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300459 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
460
461 switch (mode) {
462 case L2CAP_MODE_ERTM:
463 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
464 case L2CAP_MODE_STREAMING:
465 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
466 default:
467 return 0x00;
468 }
469}
470
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300471void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300472{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300473 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300474 struct l2cap_disconn_req req;
475
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300476 if (!conn)
477 return;
478
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300479 sk = chan->sk;
480
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300481 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300482 del_timer(&chan->retrans_timer);
483 del_timer(&chan->monitor_timer);
484 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300485 }
486
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300487 req.dcid = cpu_to_le16(chan->dcid);
488 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300489 l2cap_send_cmd(conn, l2cap_get_ident(conn),
490 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300491
492 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300493 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300494}
495
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200497static void l2cap_conn_start(struct l2cap_conn *conn)
498{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300499 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200500
501 BT_DBG("conn %p", conn);
502
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300503 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200504
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300505 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300506 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300507
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200508 bh_lock_sock(sk);
509
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300510 if (sk->sk_type != SOCK_SEQPACKET &&
511 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200512 bh_unlock_sock(sk);
513 continue;
514 }
515
516 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300517 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300518
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300519 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300520 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300521 bh_unlock_sock(sk);
522 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200523 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300524
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300525 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300526 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300527 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300528 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300529 /* __l2cap_sock_close() calls list_del(chan)
530 * so release the lock */
531 read_unlock_bh(&conn->chan_lock);
532 __l2cap_sock_close(sk, ECONNRESET);
533 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300534 bh_unlock_sock(sk);
535 continue;
536 }
537
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300538 req.scid = cpu_to_le16(chan->scid);
539 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300540
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300541 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300542 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300543
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300544 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
545 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300546
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200547 } else if (sk->sk_state == BT_CONNECT2) {
548 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300549 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300550 rsp.scid = cpu_to_le16(chan->dcid);
551 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200552
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300553 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100554 if (bt_sk(sk)->defer_setup) {
555 struct sock *parent = bt_sk(sk)->parent;
556 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
557 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
558 parent->sk_data_ready(parent, 0);
559
560 } else {
561 sk->sk_state = BT_CONFIG;
562 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
563 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
564 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200565 } else {
566 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
567 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
568 }
569
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300570 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
571 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300572
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300573 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300574 rsp.result != L2CAP_CR_SUCCESS) {
575 bh_unlock_sock(sk);
576 continue;
577 }
578
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300579 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300580 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300581 l2cap_build_conf_req(chan, buf), buf);
582 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200583 }
584
585 bh_unlock_sock(sk);
586 }
587
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300588 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200589}
590
Ville Tervob62f3282011-02-10 22:38:50 -0300591/* Find socket with cid and source bdaddr.
592 * Returns closest match, locked.
593 */
594static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
595{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300596 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300597 struct hlist_node *node;
598
599 read_lock(&l2cap_sk_list.lock);
600
601 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300602 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
603
Ville Tervob62f3282011-02-10 22:38:50 -0300604 if (state && sk->sk_state != state)
605 continue;
606
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300607 if (chan->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300608 /* Exact match. */
609 if (!bacmp(&bt_sk(sk)->src, src))
610 break;
611
612 /* Closest match */
613 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
614 sk1 = sk;
615 }
616 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300617
Ville Tervob62f3282011-02-10 22:38:50 -0300618 read_unlock(&l2cap_sk_list.lock);
619
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300620 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300621}
622
623static void l2cap_le_conn_ready(struct l2cap_conn *conn)
624{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300625 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300626 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300627
628 BT_DBG("");
629
630 /* Check if we have socket listening on cid */
631 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
632 conn->src);
633 if (!parent)
634 return;
635
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300636 bh_lock_sock(parent);
637
Ville Tervob62f3282011-02-10 22:38:50 -0300638 /* Check for backlog size */
639 if (sk_acceptq_is_full(parent)) {
640 BT_DBG("backlog full %d", parent->sk_ack_backlog);
641 goto clean;
642 }
643
644 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
645 if (!sk)
646 goto clean;
647
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300648 chan = l2cap_chan_alloc(sk);
649 if (!chan) {
650 l2cap_sock_kill(sk);
651 goto clean;
652 }
653
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300654 l2cap_pi(sk)->chan = chan;
655
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300656 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300657
658 hci_conn_hold(conn->hcon);
659
660 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300661
Ville Tervob62f3282011-02-10 22:38:50 -0300662 bacpy(&bt_sk(sk)->src, conn->src);
663 bacpy(&bt_sk(sk)->dst, conn->dst);
664
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300665 bt_accept_enqueue(parent, sk);
666
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300667 __l2cap_chan_add(conn, chan);
668
Ville Tervob62f3282011-02-10 22:38:50 -0300669 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
670
671 sk->sk_state = BT_CONNECTED;
672 parent->sk_data_ready(parent, 0);
673
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300674 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300675
676clean:
677 bh_unlock_sock(parent);
678}
679
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680static void l2cap_conn_ready(struct l2cap_conn *conn)
681{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300682 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200683
684 BT_DBG("conn %p", conn);
685
Ville Tervob62f3282011-02-10 22:38:50 -0300686 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
687 l2cap_le_conn_ready(conn);
688
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300689 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200690
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300691 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300692 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300693
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200694 bh_lock_sock(sk);
695
Ville Tervoacd7d372011-02-10 22:38:49 -0300696 if (conn->hcon->type == LE_LINK) {
697 l2cap_sock_clear_timer(sk);
698 sk->sk_state = BT_CONNECTED;
699 sk->sk_state_change(sk);
700 }
701
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300702 if (sk->sk_type != SOCK_SEQPACKET &&
703 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200704 l2cap_sock_clear_timer(sk);
705 sk->sk_state = BT_CONNECTED;
706 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200707 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300708 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200709
710 bh_unlock_sock(sk);
711 }
712
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300713 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714}
715
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200716/* Notify sockets that we cannot guaranty reliability anymore */
717static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
718{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300719 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200720
721 BT_DBG("conn %p", conn);
722
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300723 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200724
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300725 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300726 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300727
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300728 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200729 sk->sk_err = err;
730 }
731
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300732 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200733}
734
735static void l2cap_info_timeout(unsigned long arg)
736{
737 struct l2cap_conn *conn = (void *) arg;
738
Marcel Holtmann984947d2009-02-06 23:35:19 +0100739 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100740 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100741
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200742 l2cap_conn_start(conn);
743}
744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
746{
Marcel Holtmann01394182006-07-03 10:02:46 +0200747 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
Marcel Holtmann01394182006-07-03 10:02:46 +0200749 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 return conn;
751
Marcel Holtmann01394182006-07-03 10:02:46 +0200752 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
753 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
756 hcon->l2cap_data = conn;
757 conn->hcon = hcon;
758
Marcel Holtmann01394182006-07-03 10:02:46 +0200759 BT_DBG("hcon %p conn %p", hcon, conn);
760
Ville Tervoacd7d372011-02-10 22:38:49 -0300761 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
762 conn->mtu = hcon->hdev->le_mtu;
763 else
764 conn->mtu = hcon->hdev->acl_mtu;
765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 conn->src = &hcon->hdev->bdaddr;
767 conn->dst = &hcon->dst;
768
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200769 conn->feat_mask = 0;
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300772 rwlock_init(&conn->chan_lock);
773
774 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Ville Tervob62f3282011-02-10 22:38:50 -0300776 if (hcon->type != LE_LINK)
777 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000778 (unsigned long) conn);
779
Marcel Holtmann2950f212009-02-12 14:02:50 +0100780 conn->disc_reason = 0x13;
781
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 return conn;
783}
784
Marcel Holtmann01394182006-07-03 10:02:46 +0200785static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Marcel Holtmann01394182006-07-03 10:02:46 +0200787 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300788 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 struct sock *sk;
790
Marcel Holtmann01394182006-07-03 10:02:46 +0200791 if (!conn)
792 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
794 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
795
Wei Yongjun7585b972009-02-25 18:29:52 +0800796 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300799 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300800 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300802 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 bh_unlock_sock(sk);
804 l2cap_sock_kill(sk);
805 }
806
Dave Young8e8440f2008-03-03 12:18:55 -0800807 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
808 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 hcon->l2cap_data = NULL;
811 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812}
813
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300814static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300816 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300817 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300818 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819}
820
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
823/* Find socket with psm and source bdaddr.
824 * Returns closest match.
825 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000826static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
828 struct sock *sk = NULL, *sk1 = NULL;
829 struct hlist_node *node;
830
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000831 read_lock(&l2cap_sk_list.lock);
832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300834 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 if (state && sk->sk_state != state)
837 continue;
838
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300839 if (chan->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 /* Exact match. */
841 if (!bacmp(&bt_sk(sk)->src, src))
842 break;
843
844 /* Closest match */
845 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
846 sk1 = sk;
847 }
848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000851
852 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853}
854
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300855int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300857 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 bdaddr_t *src = &bt_sk(sk)->src;
859 bdaddr_t *dst = &bt_sk(sk)->dst;
860 struct l2cap_conn *conn;
861 struct hci_conn *hcon;
862 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200863 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200864 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100866 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300867 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300869 hdev = hci_get_route(dst, src);
870 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 return -EHOSTUNREACH;
872
873 hci_dev_lock_bh(hdev);
874
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300875 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200876
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300877 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -0300878 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300879 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300880 else
881 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300882 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300883
Ville Tervo30e76272011-02-22 16:10:53 -0300884 if (IS_ERR(hcon)) {
885 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
889 conn = l2cap_conn_add(hcon, 0);
890 if (!conn) {
891 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300892 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 goto done;
894 }
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 /* Update source addr of the socket */
897 bacpy(src, conn->src);
898
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300899 l2cap_chan_add(conn, chan);
900
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 sk->sk_state = BT_CONNECT;
902 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
903
904 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300905 if (sk->sk_type != SOCK_SEQPACKET &&
906 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300908 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +0530909 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200910 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300911 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 }
913
Ville Tervo30e76272011-02-22 16:10:53 -0300914 err = 0;
915
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916done:
917 hci_dev_unlock_bh(hdev);
918 hci_dev_put(hdev);
919 return err;
920}
921
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200922int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300923{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300924 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300925 DECLARE_WAITQUEUE(wait, current);
926 int err = 0;
927 int timeo = HZ/5;
928
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200929 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300930 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300931 set_current_state(TASK_INTERRUPTIBLE);
932
933 if (!timeo)
934 timeo = HZ/5;
935
936 if (signal_pending(current)) {
937 err = sock_intr_errno(timeo);
938 break;
939 }
940
941 release_sock(sk);
942 timeo = schedule_timeout(timeo);
943 lock_sock(sk);
944
945 err = sock_error(sk);
946 if (err)
947 break;
948 }
949 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200950 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300951 return err;
952}
953
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300954static void l2cap_monitor_timeout(unsigned long arg)
955{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300956 struct l2cap_chan *chan = (void *) arg;
957 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300958
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300959 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300960
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300961 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300962 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300963 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200964 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300965 return;
966 }
967
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300968 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300969 __mod_monitor_timer();
970
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300971 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300972 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973}
974
975static void l2cap_retrans_timeout(unsigned long arg)
976{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300977 struct l2cap_chan *chan = (void *) arg;
978 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300979
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300980 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300981
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300982 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300983 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984 __mod_monitor_timer();
985
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300986 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300987
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300988 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300989 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300990}
991
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300992static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993{
994 struct sk_buff *skb;
995
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300996 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300997 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300998 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300999 break;
1000
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001001 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001002 kfree_skb(skb);
1003
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001004 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005 }
1006
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001007 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001008 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001009}
1010
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001011void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001012{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001013 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001014 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001016 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001017
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001018 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001019 flags = ACL_START_NO_FLUSH;
1020 else
1021 flags = ACL_START;
1022
1023 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001024}
1025
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001026void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001027{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001028 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001029 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001030
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001031 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001033 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001034 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001035
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001036 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001037 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1038 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001039 }
1040
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001041 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001042
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001043 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001044 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001045}
1046
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001047static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001048{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001049 struct sk_buff *skb, *tx_skb;
1050 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001051
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001052 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001053 if (!skb)
1054 return;
1055
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001056 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001057 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001060 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001061 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001063 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001064
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001065 if (chan->remote_max_tx &&
1066 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001067 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 return;
1069 }
1070
1071 tx_skb = skb_clone(skb, GFP_ATOMIC);
1072 bt_cb(skb)->retries++;
1073 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001074 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001075
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001076 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001077 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001078 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001079 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001080
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001081 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001082 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001083
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001084 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1085
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001086 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001087 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1088 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1089 }
1090
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001091 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001092}
1093
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001094int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001095{
1096 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001097 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001098 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001099 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001101 if (sk->sk_state != BT_CONNECTED)
1102 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001103
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001104 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001106 if (chan->remote_max_tx &&
1107 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001108 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 break;
1110 }
1111
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001112 tx_skb = skb_clone(skb, GFP_ATOMIC);
1113
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114 bt_cb(skb)->retries++;
1115
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001117 control &= L2CAP_CTRL_SAR;
1118
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001119 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001120 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001121 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001123 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1124 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001125 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1126
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001127
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001128 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001129 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1130 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1131 }
1132
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001133 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001134
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001135 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001137 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1138 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301140 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001141 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301142
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001143 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001144
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001145 if (skb_queue_is_last(&chan->tx_q, skb))
1146 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001148 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001149
1150 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001151 }
1152
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001153 return nsent;
1154}
1155
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001156static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001157{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001158 int ret;
1159
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001160 if (!skb_queue_empty(&chan->tx_q))
1161 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001163 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 return ret;
1166}
1167
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001168static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001169{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001170 u16 control = 0;
1171
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001172 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001173
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001174 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1177 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001178 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001182 return;
1183
1184 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001185 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001186}
1187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001189{
1190 struct srej_list *tail;
1191 u16 control;
1192
1193 control = L2CAP_SUPER_SELECT_REJECT;
1194 control |= L2CAP_CTRL_FINAL;
1195
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001196 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001199 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001200}
1201
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202static 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 -07001203{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001204 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205 struct sk_buff **frag;
1206 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001208 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 sent += count;
1212 len -= count;
1213
1214 /* Continuation fragments (no L2CAP header) */
1215 frag = &skb_shinfo(skb)->frag_list;
1216 while (len) {
1217 count = min_t(unsigned int, conn->mtu, len);
1218
1219 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1220 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001221 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001222 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1223 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 sent += count;
1226 len -= count;
1227
1228 frag = &(*frag)->next;
1229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001234struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001236 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001237 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001238 struct sk_buff *skb;
1239 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1240 struct l2cap_hdr *lh;
1241
1242 BT_DBG("sk %p len %d", sk, (int)len);
1243
1244 count = min_t(unsigned int, (conn->mtu - hlen), len);
1245 skb = bt_skb_send_alloc(sk, count + hlen,
1246 msg->msg_flags & MSG_DONTWAIT, &err);
1247 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001248 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249
1250 /* Create L2CAP header */
1251 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001252 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001254 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
1256 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1257 if (unlikely(err < 0)) {
1258 kfree_skb(skb);
1259 return ERR_PTR(err);
1260 }
1261 return skb;
1262}
1263
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001264struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001265{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001266 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001267 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001268 struct sk_buff *skb;
1269 int err, count, hlen = L2CAP_HDR_SIZE;
1270 struct l2cap_hdr *lh;
1271
1272 BT_DBG("sk %p len %d", sk, (int)len);
1273
1274 count = min_t(unsigned int, (conn->mtu - hlen), len);
1275 skb = bt_skb_send_alloc(sk, count + hlen,
1276 msg->msg_flags & MSG_DONTWAIT, &err);
1277 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001278 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001279
1280 /* Create L2CAP header */
1281 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001282 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001283 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1284
1285 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1286 if (unlikely(err < 0)) {
1287 kfree_skb(skb);
1288 return ERR_PTR(err);
1289 }
1290 return skb;
1291}
1292
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001293struct 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 -03001294{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001295 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001296 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001297 struct sk_buff *skb;
1298 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1299 struct l2cap_hdr *lh;
1300
1301 BT_DBG("sk %p len %d", sk, (int)len);
1302
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001303 if (!conn)
1304 return ERR_PTR(-ENOTCONN);
1305
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001306 if (sdulen)
1307 hlen += 2;
1308
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001309 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001310 hlen += 2;
1311
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001312 count = min_t(unsigned int, (conn->mtu - hlen), len);
1313 skb = bt_skb_send_alloc(sk, count + hlen,
1314 msg->msg_flags & MSG_DONTWAIT, &err);
1315 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001316 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001317
1318 /* Create L2CAP header */
1319 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001320 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1322 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001323 if (sdulen)
1324 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001325
1326 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1327 if (unlikely(err < 0)) {
1328 kfree_skb(skb);
1329 return ERR_PTR(err);
1330 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001331
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001332 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001333 put_unaligned_le16(0, skb_put(skb, 2));
1334
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001335 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001336 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337}
1338
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001339int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001340{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001341 struct sk_buff *skb;
1342 struct sk_buff_head sar_queue;
1343 u16 control;
1344 size_t size = 0;
1345
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001346 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001348 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349 if (IS_ERR(skb))
1350 return PTR_ERR(skb);
1351
1352 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001353 len -= chan->remote_mps;
1354 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001355
1356 while (len > 0) {
1357 size_t buflen;
1358
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001360 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001361 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001362 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001363 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001364 buflen = len;
1365 }
1366
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001367 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001368 if (IS_ERR(skb)) {
1369 skb_queue_purge(&sar_queue);
1370 return PTR_ERR(skb);
1371 }
1372
1373 __skb_queue_tail(&sar_queue, skb);
1374 len -= buflen;
1375 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001376 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001377 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1378 if (chan->tx_send_head == NULL)
1379 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001380
1381 return size;
1382}
1383
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384static void l2cap_chan_ready(struct sock *sk)
1385{
1386 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001387 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
1389 BT_DBG("sk %p, parent %p", sk, parent);
1390
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001391 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 l2cap_sock_clear_timer(sk);
1393
1394 if (!parent) {
1395 /* Outgoing channel.
1396 * Wake up socket sleeping on connect.
1397 */
1398 sk->sk_state = BT_CONNECTED;
1399 sk->sk_state_change(sk);
1400 } else {
1401 /* Incoming channel.
1402 * Wake up socket sleeping on accept.
1403 */
1404 parent->sk_data_ready(parent, 0);
1405 }
1406}
1407
1408/* Copy frame to all raw sockets on that connection */
1409static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1410{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001412 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
1414 BT_DBG("conn %p", conn);
1415
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001416 read_lock(&conn->chan_lock);
1417 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001418 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 if (sk->sk_type != SOCK_RAW)
1420 continue;
1421
1422 /* Don't send frame to the socket it came from */
1423 if (skb->sk == sk)
1424 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001425 nskb = skb_clone(skb, GFP_ATOMIC);
1426 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 continue;
1428
1429 if (sock_queue_rcv_skb(sk, nskb))
1430 kfree_skb(nskb);
1431 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001432 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433}
1434
1435/* ---- L2CAP signalling commands ---- */
1436static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1437 u8 code, u8 ident, u16 dlen, void *data)
1438{
1439 struct sk_buff *skb, **frag;
1440 struct l2cap_cmd_hdr *cmd;
1441 struct l2cap_hdr *lh;
1442 int len, count;
1443
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001444 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1445 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1448 count = min_t(unsigned int, conn->mtu, len);
1449
1450 skb = bt_skb_alloc(count, GFP_ATOMIC);
1451 if (!skb)
1452 return NULL;
1453
1454 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001455 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001456
1457 if (conn->hcon->type == LE_LINK)
1458 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1459 else
1460 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1463 cmd->code = code;
1464 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001465 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 if (dlen) {
1468 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1469 memcpy(skb_put(skb, count), data, count);
1470 data += count;
1471 }
1472
1473 len -= skb->len;
1474
1475 /* Continuation fragments (no L2CAP header) */
1476 frag = &skb_shinfo(skb)->frag_list;
1477 while (len) {
1478 count = min_t(unsigned int, conn->mtu, len);
1479
1480 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1481 if (!*frag)
1482 goto fail;
1483
1484 memcpy(skb_put(*frag, count), data, count);
1485
1486 len -= count;
1487 data += count;
1488
1489 frag = &(*frag)->next;
1490 }
1491
1492 return skb;
1493
1494fail:
1495 kfree_skb(skb);
1496 return NULL;
1497}
1498
1499static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1500{
1501 struct l2cap_conf_opt *opt = *ptr;
1502 int len;
1503
1504 len = L2CAP_CONF_OPT_SIZE + opt->len;
1505 *ptr += len;
1506
1507 *type = opt->type;
1508 *olen = opt->len;
1509
1510 switch (opt->len) {
1511 case 1:
1512 *val = *((u8 *) opt->val);
1513 break;
1514
1515 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001516 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 break;
1518
1519 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001520 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 break;
1522
1523 default:
1524 *val = (unsigned long) opt->val;
1525 break;
1526 }
1527
1528 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1529 return len;
1530}
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1533{
1534 struct l2cap_conf_opt *opt = *ptr;
1535
1536 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1537
1538 opt->type = type;
1539 opt->len = len;
1540
1541 switch (len) {
1542 case 1:
1543 *((u8 *) opt->val) = val;
1544 break;
1545
1546 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001547 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 break;
1549
1550 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001551 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 break;
1553
1554 default:
1555 memcpy(opt->val, (void *) val, len);
1556 break;
1557 }
1558
1559 *ptr += L2CAP_CONF_OPT_SIZE + len;
1560}
1561
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001562static void l2cap_ack_timeout(unsigned long arg)
1563{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001564 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001565
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001566 bh_lock_sock(chan->sk);
1567 l2cap_send_ack(chan);
1568 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001569}
1570
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001572{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573 struct sock *sk = chan->sk;
1574
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001575 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001576 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001577 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001578 chan->num_acked = 0;
1579 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001580
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001581 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1582 (unsigned long) chan);
1583 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1584 (unsigned long) chan);
1585 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001586
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001587 skb_queue_head_init(&chan->srej_q);
1588 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001589
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001590 INIT_LIST_HEAD(&chan->srej_l);
1591
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001592 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001593
1594 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001595}
1596
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001597static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1598{
1599 switch (mode) {
1600 case L2CAP_MODE_STREAMING:
1601 case L2CAP_MODE_ERTM:
1602 if (l2cap_mode_supported(mode, remote_feat_mask))
1603 return mode;
1604 /* fall through */
1605 default:
1606 return L2CAP_MODE_BASIC;
1607 }
1608}
1609
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001610static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001613 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 void *ptr = req->data;
1615
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001616 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001618 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001619 goto done;
1620
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001621 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001622 case L2CAP_MODE_STREAMING:
1623 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001624 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001625 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001626
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001627 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001628 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001629 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001630 break;
1631 }
1632
1633done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001634 if (chan->imtu != L2CAP_DEFAULT_MTU)
1635 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan79906812011-01-24 16:01:43 -02001636
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001637 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001638 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001639 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1640 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001641 break;
1642
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001643 rfc.mode = L2CAP_MODE_BASIC;
1644 rfc.txwin_size = 0;
1645 rfc.max_transmit = 0;
1646 rfc.retrans_timeout = 0;
1647 rfc.monitor_timeout = 0;
1648 rfc.max_pdu_size = 0;
1649
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001650 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1651 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001652 break;
1653
1654 case L2CAP_MODE_ERTM:
1655 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001656 rfc.txwin_size = chan->tx_win;
1657 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001658 rfc.retrans_timeout = 0;
1659 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001660 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001661 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1662 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001663
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001664 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1665 (unsigned long) &rfc);
1666
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001667 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001668 break;
1669
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001670 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001671 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001672 chan->fcs = L2CAP_FCS_NONE;
1673 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001674 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001675 break;
1676
1677 case L2CAP_MODE_STREAMING:
1678 rfc.mode = L2CAP_MODE_STREAMING;
1679 rfc.txwin_size = 0;
1680 rfc.max_transmit = 0;
1681 rfc.retrans_timeout = 0;
1682 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001683 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001684 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1685 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001686
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001687 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1688 (unsigned long) &rfc);
1689
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001690 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001691 break;
1692
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001693 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001694 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001695 chan->fcs = L2CAP_FCS_NONE;
1696 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001697 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001698 break;
1699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001701 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001702 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
1704 return ptr - data;
1705}
1706
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001707static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001709 struct l2cap_conf_rsp *rsp = data;
1710 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001711 void *req = chan->conf_req;
1712 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001713 int type, hint, olen;
1714 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001715 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001716 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001717 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001719 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001720
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001721 while (len >= L2CAP_CONF_OPT_SIZE) {
1722 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001724 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001725 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726
1727 switch (type) {
1728 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001729 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001730 break;
1731
1732 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001733 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001734 break;
1735
1736 case L2CAP_CONF_QOS:
1737 break;
1738
Marcel Holtmann6464f352007-10-20 13:39:51 +02001739 case L2CAP_CONF_RFC:
1740 if (olen == sizeof(rfc))
1741 memcpy(&rfc, (void *) val, olen);
1742 break;
1743
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001744 case L2CAP_CONF_FCS:
1745 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001746 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747
1748 break;
1749
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001750 default:
1751 if (hint)
1752 break;
1753
1754 result = L2CAP_CONF_UNKNOWN;
1755 *((u8 *) ptr++) = type;
1756 break;
1757 }
1758 }
1759
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001760 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001761 goto done;
1762
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001763 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001764 case L2CAP_MODE_STREAMING:
1765 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001766 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001767 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001768 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001769 break;
1770 }
1771
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001772 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001774
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001775 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001776 }
1777
1778done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001779 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001781 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001783 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 return -ECONNREFUSED;
1785
1786 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1787 sizeof(rfc), (unsigned long) &rfc);
1788 }
1789
1790
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001791 if (result == L2CAP_CONF_SUCCESS) {
1792 /* Configure output options and let the other side know
1793 * which ones we don't like. */
1794
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001795 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1796 result = L2CAP_CONF_UNACCEPT;
1797 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001798 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001799 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001801 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001802
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001803 switch (rfc.mode) {
1804 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001805 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001806 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001807 break;
1808
1809 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001810 chan->remote_tx_win = rfc.txwin_size;
1811 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001812
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001813 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1814 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001815
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001816 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001817
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001818 rfc.retrans_timeout =
1819 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1820 rfc.monitor_timeout =
1821 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001822
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001823 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001824
1825 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1826 sizeof(rfc), (unsigned long) &rfc);
1827
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001828 break;
1829
1830 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001831 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1832 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001833
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001834 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001836 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001837
1838 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1839 sizeof(rfc), (unsigned long) &rfc);
1840
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001841 break;
1842
1843 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001844 result = L2CAP_CONF_UNACCEPT;
1845
1846 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001847 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001848 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001849
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001851 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001853 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001854 rsp->result = cpu_to_le16(result);
1855 rsp->flags = cpu_to_le16(0x0000);
1856
1857 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858}
1859
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001860static 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 -03001861{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001862 struct l2cap_conf_req *req = data;
1863 void *ptr = req->data;
1864 int type, olen;
1865 unsigned long val;
1866 struct l2cap_conf_rfc rfc;
1867
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001868 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001869
1870 while (len >= L2CAP_CONF_OPT_SIZE) {
1871 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1872
1873 switch (type) {
1874 case L2CAP_CONF_MTU:
1875 if (val < L2CAP_DEFAULT_MIN_MTU) {
1876 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001877 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001878 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001879 chan->imtu = val;
1880 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001881 break;
1882
1883 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001884 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001886 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001887 break;
1888
1889 case L2CAP_CONF_RFC:
1890 if (olen == sizeof(rfc))
1891 memcpy(&rfc, (void *)val, olen);
1892
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001893 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001894 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001895 return -ECONNREFUSED;
1896
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001897 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001898
1899 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1900 sizeof(rfc), (unsigned long) &rfc);
1901 break;
1902 }
1903 }
1904
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001905 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001906 return -ECONNREFUSED;
1907
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001908 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001909
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 if (*result == L2CAP_CONF_SUCCESS) {
1911 switch (rfc.mode) {
1912 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001913 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1914 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1915 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 break;
1917 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001918 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001919 }
1920 }
1921
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001922 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 req->flags = cpu_to_le16(0x0000);
1924
1925 return ptr - data;
1926}
1927
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001928static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929{
1930 struct l2cap_conf_rsp *rsp = data;
1931 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001933 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001935 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001936 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001937 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 return ptr - data;
1940}
1941
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001942void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001943{
1944 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001945 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001946 u8 buf[128];
1947
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001948 rsp.scid = cpu_to_le16(chan->dcid);
1949 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001950 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1951 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1952 l2cap_send_cmd(conn, chan->ident,
1953 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1954
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001955 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001956 return;
1957
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001958 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001959 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1960 l2cap_build_conf_req(chan, buf), buf);
1961 chan->num_conf_req++;
1962}
1963
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001964static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001965{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001966 int type, olen;
1967 unsigned long val;
1968 struct l2cap_conf_rfc rfc;
1969
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001970 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001971
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001972 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001973 return;
1974
1975 while (len >= L2CAP_CONF_OPT_SIZE) {
1976 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1977
1978 switch (type) {
1979 case L2CAP_CONF_RFC:
1980 if (olen == sizeof(rfc))
1981 memcpy(&rfc, (void *)val, olen);
1982 goto done;
1983 }
1984 }
1985
1986done:
1987 switch (rfc.mode) {
1988 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001989 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1990 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1991 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001992 break;
1993 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001994 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001995 }
1996}
1997
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001998static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1999{
2000 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2001
2002 if (rej->reason != 0x0000)
2003 return 0;
2004
2005 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2006 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002007 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002008
2009 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002010 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002011
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002012 l2cap_conn_start(conn);
2013 }
2014
2015 return 0;
2016}
2017
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2019{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2021 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002022 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002023 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002024 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
2026 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002027 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028
2029 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2030
2031 /* Check if we have socket listening on psm */
2032 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2033 if (!parent) {
2034 result = L2CAP_CR_BAD_PSM;
2035 goto sendresp;
2036 }
2037
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002038 bh_lock_sock(parent);
2039
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002040 /* Check if the ACL is secure enough (if not SDP) */
2041 if (psm != cpu_to_le16(0x0001) &&
2042 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002043 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002044 result = L2CAP_CR_SEC_BLOCK;
2045 goto response;
2046 }
2047
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 result = L2CAP_CR_NO_MEM;
2049
2050 /* Check for backlog size */
2051 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002052 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 goto response;
2054 }
2055
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002056 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 if (!sk)
2058 goto response;
2059
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002060 chan = l2cap_chan_alloc(sk);
2061 if (!chan) {
2062 l2cap_sock_kill(sk);
2063 goto response;
2064 }
2065
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002066 l2cap_pi(sk)->chan = chan;
2067
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002068 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
2070 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002071 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2072 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 sock_set_flag(sk, SOCK_ZAPPED);
2074 l2cap_sock_kill(sk);
2075 goto response;
2076 }
2077
2078 hci_conn_hold(conn->hcon);
2079
2080 l2cap_sock_init(sk, parent);
2081 bacpy(&bt_sk(sk)->src, conn->src);
2082 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002083 chan->psm = psm;
2084 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002086 bt_accept_enqueue(parent, sk);
2087
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002088 __l2cap_chan_add(conn, chan);
2089
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002090 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
2092 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2093
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002094 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Marcel Holtmann984947d2009-02-06 23:35:19 +01002096 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002097 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002098 if (bt_sk(sk)->defer_setup) {
2099 sk->sk_state = BT_CONNECT2;
2100 result = L2CAP_CR_PEND;
2101 status = L2CAP_CS_AUTHOR_PEND;
2102 parent->sk_data_ready(parent, 0);
2103 } else {
2104 sk->sk_state = BT_CONFIG;
2105 result = L2CAP_CR_SUCCESS;
2106 status = L2CAP_CS_NO_INFO;
2107 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002108 } else {
2109 sk->sk_state = BT_CONNECT2;
2110 result = L2CAP_CR_PEND;
2111 status = L2CAP_CS_AUTHEN_PEND;
2112 }
2113 } else {
2114 sk->sk_state = BT_CONNECT2;
2115 result = L2CAP_CR_PEND;
2116 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 }
2118
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002119 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
2121response:
2122 bh_unlock_sock(parent);
2123
2124sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002125 rsp.scid = cpu_to_le16(scid);
2126 rsp.dcid = cpu_to_le16(dcid);
2127 rsp.result = cpu_to_le16(result);
2128 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002130
2131 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2132 struct l2cap_info_req info;
2133 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2134
2135 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2136 conn->info_ident = l2cap_get_ident(conn);
2137
2138 mod_timer(&conn->info_timer, jiffies +
2139 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2140
2141 l2cap_send_cmd(conn, conn->info_ident,
2142 L2CAP_INFO_REQ, sizeof(info), &info);
2143 }
2144
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002145 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002146 result == L2CAP_CR_SUCCESS) {
2147 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002148 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002149 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002150 l2cap_build_conf_req(chan, buf), buf);
2151 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002152 }
2153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 return 0;
2155}
2156
2157static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2158{
2159 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2160 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002161 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 struct sock *sk;
2163 u8 req[128];
2164
2165 scid = __le16_to_cpu(rsp->scid);
2166 dcid = __le16_to_cpu(rsp->dcid);
2167 result = __le16_to_cpu(rsp->result);
2168 status = __le16_to_cpu(rsp->status);
2169
2170 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2171
2172 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002173 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002174 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002175 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002177 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002178 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002179 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 }
2181
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002182 sk = chan->sk;
2183
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 switch (result) {
2185 case L2CAP_CR_SUCCESS:
2186 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002187 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002188 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002189 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002190
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002191 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002192 break;
2193
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002194 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002195
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002197 l2cap_build_conf_req(chan, req), req);
2198 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 break;
2200
2201 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002202 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 break;
2204
2205 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002206 /* don't delete l2cap channel if sk is owned by user */
2207 if (sock_owned_by_user(sk)) {
2208 sk->sk_state = BT_DISCONN;
2209 l2cap_sock_clear_timer(sk);
2210 l2cap_sock_set_timer(sk, HZ / 5);
2211 break;
2212 }
2213
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002214 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 break;
2216 }
2217
2218 bh_unlock_sock(sk);
2219 return 0;
2220}
2221
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002222static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002223{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002224 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2225
Mat Martineau8c462b62010-08-24 15:35:42 -07002226 /* FCS is enabled only in ERTM or streaming mode, if one or both
2227 * sides request it.
2228 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002229 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002230 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002231 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002232 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002233}
2234
Al Viro88219a02007-07-29 00:17:25 -07002235static 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 -07002236{
2237 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2238 u16 dcid, flags;
2239 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002240 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002242 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244 dcid = __le16_to_cpu(req->dcid);
2245 flags = __le16_to_cpu(req->flags);
2246
2247 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2248
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002249 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002250 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 return -ENOENT;
2252
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002253 sk = chan->sk;
2254
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002255 if (sk->sk_state != BT_CONFIG) {
2256 struct l2cap_cmd_rej rej;
2257
2258 rej.reason = cpu_to_le16(0x0002);
2259 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2260 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002261 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002262 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002263
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002264 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002265 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002266 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002267 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002268 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002269 L2CAP_CONF_REJECT, flags), rsp);
2270 goto unlock;
2271 }
2272
2273 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002274 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2275 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
2277 if (flags & 0x0001) {
2278 /* Incomplete config. Send empty response. */
2279 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002280 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002281 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 goto unlock;
2283 }
2284
2285 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002286 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002287 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002288 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002293 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002294
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002295 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002296 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002297
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002298 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002299 goto unlock;
2300
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002301 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002302 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002303
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002305
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002306 chan->next_tx_seq = 0;
2307 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002308 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002309 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002310 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002313 goto unlock;
2314 }
2315
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002316 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002317 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002318 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002320 l2cap_build_conf_req(chan, buf), buf);
2321 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 }
2323
2324unlock:
2325 bh_unlock_sock(sk);
2326 return 0;
2327}
2328
2329static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2330{
2331 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2332 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002333 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002335 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
2337 scid = __le16_to_cpu(rsp->scid);
2338 flags = __le16_to_cpu(rsp->flags);
2339 result = __le16_to_cpu(rsp->result);
2340
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002341 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2342 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002344 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002345 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 return 0;
2347
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002348 sk = chan->sk;
2349
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 switch (result) {
2351 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002352 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 break;
2354
2355 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002356 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002357 char req[64];
2358
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002359 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002360 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002361 goto done;
2362 }
2363
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002364 /* throw out any old stored conf requests */
2365 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002366 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2367 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002368 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002369 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002370 goto done;
2371 }
2372
2373 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2374 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002375 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002376 if (result != L2CAP_CONF_SUCCESS)
2377 goto done;
2378 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 }
2380
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002381 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002382 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002384 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 goto done;
2386 }
2387
2388 if (flags & 0x01)
2389 goto done;
2390
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002391 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002393 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002394 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002395
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002397 chan->next_tx_seq = 0;
2398 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002399 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002400 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002401 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002402
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 l2cap_chan_ready(sk);
2404 }
2405
2406done:
2407 bh_unlock_sock(sk);
2408 return 0;
2409}
2410
2411static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2412{
2413 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2414 struct l2cap_disconn_rsp rsp;
2415 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002416 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 struct sock *sk;
2418
2419 scid = __le16_to_cpu(req->scid);
2420 dcid = __le16_to_cpu(req->dcid);
2421
2422 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2423
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002424 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002425 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 return 0;
2427
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002428 sk = chan->sk;
2429
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002430 rsp.dcid = cpu_to_le16(chan->scid);
2431 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2433
2434 sk->sk_shutdown = SHUTDOWN_MASK;
2435
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002436 /* don't delete l2cap channel if sk is owned by user */
2437 if (sock_owned_by_user(sk)) {
2438 sk->sk_state = BT_DISCONN;
2439 l2cap_sock_clear_timer(sk);
2440 l2cap_sock_set_timer(sk, HZ / 5);
2441 bh_unlock_sock(sk);
2442 return 0;
2443 }
2444
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002445 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 bh_unlock_sock(sk);
2447
2448 l2cap_sock_kill(sk);
2449 return 0;
2450}
2451
2452static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2453{
2454 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2455 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002456 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 struct sock *sk;
2458
2459 scid = __le16_to_cpu(rsp->scid);
2460 dcid = __le16_to_cpu(rsp->dcid);
2461
2462 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2463
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002464 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002465 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 return 0;
2467
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002468 sk = chan->sk;
2469
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002470 /* don't delete l2cap channel if sk is owned by user */
2471 if (sock_owned_by_user(sk)) {
2472 sk->sk_state = BT_DISCONN;
2473 l2cap_sock_clear_timer(sk);
2474 l2cap_sock_set_timer(sk, HZ / 5);
2475 bh_unlock_sock(sk);
2476 return 0;
2477 }
2478
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002479 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 bh_unlock_sock(sk);
2481
2482 l2cap_sock_kill(sk);
2483 return 0;
2484}
2485
2486static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2487{
2488 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 u16 type;
2490
2491 type = __le16_to_cpu(req->type);
2492
2493 BT_DBG("type 0x%4.4x", type);
2494
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002495 if (type == L2CAP_IT_FEAT_MASK) {
2496 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002497 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002498 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2499 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2500 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002501 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002502 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2503 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002504 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002505 l2cap_send_cmd(conn, cmd->ident,
2506 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002507 } else if (type == L2CAP_IT_FIXED_CHAN) {
2508 u8 buf[12];
2509 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2510 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2511 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2512 memcpy(buf + 4, l2cap_fixed_chan, 8);
2513 l2cap_send_cmd(conn, cmd->ident,
2514 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002515 } else {
2516 struct l2cap_info_rsp rsp;
2517 rsp.type = cpu_to_le16(type);
2518 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2519 l2cap_send_cmd(conn, cmd->ident,
2520 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
2523 return 0;
2524}
2525
2526static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2527{
2528 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2529 u16 type, result;
2530
2531 type = __le16_to_cpu(rsp->type);
2532 result = __le16_to_cpu(rsp->result);
2533
2534 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2535
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002536 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2537 if (cmd->ident != conn->info_ident ||
2538 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2539 return 0;
2540
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002541 del_timer(&conn->info_timer);
2542
Ville Tervoadb08ed2010-08-04 09:43:33 +03002543 if (result != L2CAP_IR_SUCCESS) {
2544 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2545 conn->info_ident = 0;
2546
2547 l2cap_conn_start(conn);
2548
2549 return 0;
2550 }
2551
Marcel Holtmann984947d2009-02-06 23:35:19 +01002552 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002553 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002554
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002555 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002556 struct l2cap_info_req req;
2557 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2558
2559 conn->info_ident = l2cap_get_ident(conn);
2560
2561 l2cap_send_cmd(conn, conn->info_ident,
2562 L2CAP_INFO_REQ, sizeof(req), &req);
2563 } else {
2564 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2565 conn->info_ident = 0;
2566
2567 l2cap_conn_start(conn);
2568 }
2569 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002570 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002571 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002572
2573 l2cap_conn_start(conn);
2574 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002575
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 return 0;
2577}
2578
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002579static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002580 u16 to_multiplier)
2581{
2582 u16 max_latency;
2583
2584 if (min > max || min < 6 || max > 3200)
2585 return -EINVAL;
2586
2587 if (to_multiplier < 10 || to_multiplier > 3200)
2588 return -EINVAL;
2589
2590 if (max >= to_multiplier * 8)
2591 return -EINVAL;
2592
2593 max_latency = (to_multiplier * 8 / max) - 1;
2594 if (latency > 499 || latency > max_latency)
2595 return -EINVAL;
2596
2597 return 0;
2598}
2599
2600static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2601 struct l2cap_cmd_hdr *cmd, u8 *data)
2602{
2603 struct hci_conn *hcon = conn->hcon;
2604 struct l2cap_conn_param_update_req *req;
2605 struct l2cap_conn_param_update_rsp rsp;
2606 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002607 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002608
2609 if (!(hcon->link_mode & HCI_LM_MASTER))
2610 return -EINVAL;
2611
2612 cmd_len = __le16_to_cpu(cmd->len);
2613 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2614 return -EPROTO;
2615
2616 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002617 min = __le16_to_cpu(req->min);
2618 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002619 latency = __le16_to_cpu(req->latency);
2620 to_multiplier = __le16_to_cpu(req->to_multiplier);
2621
2622 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2623 min, max, latency, to_multiplier);
2624
2625 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002626
2627 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2628 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002629 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2630 else
2631 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2632
2633 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2634 sizeof(rsp), &rsp);
2635
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002636 if (!err)
2637 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2638
Claudio Takahaside731152011-02-11 19:28:55 -02002639 return 0;
2640}
2641
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002642static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2643 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2644{
2645 int err = 0;
2646
2647 switch (cmd->code) {
2648 case L2CAP_COMMAND_REJ:
2649 l2cap_command_rej(conn, cmd, data);
2650 break;
2651
2652 case L2CAP_CONN_REQ:
2653 err = l2cap_connect_req(conn, cmd, data);
2654 break;
2655
2656 case L2CAP_CONN_RSP:
2657 err = l2cap_connect_rsp(conn, cmd, data);
2658 break;
2659
2660 case L2CAP_CONF_REQ:
2661 err = l2cap_config_req(conn, cmd, cmd_len, data);
2662 break;
2663
2664 case L2CAP_CONF_RSP:
2665 err = l2cap_config_rsp(conn, cmd, data);
2666 break;
2667
2668 case L2CAP_DISCONN_REQ:
2669 err = l2cap_disconnect_req(conn, cmd, data);
2670 break;
2671
2672 case L2CAP_DISCONN_RSP:
2673 err = l2cap_disconnect_rsp(conn, cmd, data);
2674 break;
2675
2676 case L2CAP_ECHO_REQ:
2677 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2678 break;
2679
2680 case L2CAP_ECHO_RSP:
2681 break;
2682
2683 case L2CAP_INFO_REQ:
2684 err = l2cap_information_req(conn, cmd, data);
2685 break;
2686
2687 case L2CAP_INFO_RSP:
2688 err = l2cap_information_rsp(conn, cmd, data);
2689 break;
2690
2691 default:
2692 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2693 err = -EINVAL;
2694 break;
2695 }
2696
2697 return err;
2698}
2699
2700static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2701 struct l2cap_cmd_hdr *cmd, u8 *data)
2702{
2703 switch (cmd->code) {
2704 case L2CAP_COMMAND_REJ:
2705 return 0;
2706
2707 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002708 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002709
2710 case L2CAP_CONN_PARAM_UPDATE_RSP:
2711 return 0;
2712
2713 default:
2714 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2715 return -EINVAL;
2716 }
2717}
2718
2719static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2720 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721{
2722 u8 *data = skb->data;
2723 int len = skb->len;
2724 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002725 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
2727 l2cap_raw_recv(conn, skb);
2728
2729 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002730 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2732 data += L2CAP_CMD_HDR_SIZE;
2733 len -= L2CAP_CMD_HDR_SIZE;
2734
Al Viro88219a02007-07-29 00:17:25 -07002735 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Al Viro88219a02007-07-29 00:17:25 -07002737 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 -07002738
Al Viro88219a02007-07-29 00:17:25 -07002739 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 BT_DBG("corrupted command");
2741 break;
2742 }
2743
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002744 if (conn->hcon->type == LE_LINK)
2745 err = l2cap_le_sig_cmd(conn, &cmd, data);
2746 else
2747 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748
2749 if (err) {
2750 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002751
2752 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
2754 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002755 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2757 }
2758
Al Viro88219a02007-07-29 00:17:25 -07002759 data += cmd_len;
2760 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 }
2762
2763 kfree_skb(skb);
2764}
2765
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002766static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002767{
2768 u16 our_fcs, rcv_fcs;
2769 int hdr_size = L2CAP_HDR_SIZE + 2;
2770
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002771 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002772 skb_trim(skb, skb->len - 2);
2773 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2774 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2775
2776 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002777 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002778 }
2779 return 0;
2780}
2781
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002782static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002783{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002784 u16 control = 0;
2785
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002786 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002787
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002788 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002789
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002790 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002791 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002792 l2cap_send_sframe(chan, control);
2793 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002794 }
2795
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002796 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2797 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002798
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002799 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002800
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002801 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002802 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002803 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002804 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002805 }
2806}
2807
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002808static 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 -03002809{
2810 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002811 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002812
2813 bt_cb(skb)->tx_seq = tx_seq;
2814 bt_cb(skb)->sar = sar;
2815
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002816 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002817 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002818 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002819 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002820 }
2821
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002822 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002823 if (tx_seq_offset < 0)
2824 tx_seq_offset += 64;
2825
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002826 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002827 if (bt_cb(next_skb)->tx_seq == tx_seq)
2828 return -EINVAL;
2829
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002830 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002831 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002832 if (next_tx_seq_offset < 0)
2833 next_tx_seq_offset += 64;
2834
2835 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002836 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002837 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002838 }
2839
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002840 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002841 break;
2842
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002843 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002844
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002845 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002846
2847 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002848}
2849
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002850static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002851{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002852 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002853 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002854
2855 switch (control & L2CAP_CTRL_SAR) {
2856 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002857 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002858 goto drop;
2859
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861 if (!err)
2862 return err;
2863
2864 break;
2865
2866 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002867 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002868 goto drop;
2869
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002870 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002871
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002872 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002873 goto disconnect;
2874
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002875 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2876 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002877 return -ENOMEM;
2878
2879 /* pull sdu_len bytes only after alloc, because of Local Busy
2880 * condition we have to be sure that this will be executed
2881 * only once, i.e., when alloc does not fail */
2882 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002883
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002884 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002885
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002886 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002887 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002888 break;
2889
2890 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002891 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002892 goto disconnect;
2893
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002894 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002895 goto disconnect;
2896
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002897 chan->partial_sdu_len += skb->len;
2898 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002899 goto drop;
2900
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002901 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002902
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002903 break;
2904
2905 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002906 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002907 goto disconnect;
2908
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002909 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002910 goto disconnect;
2911
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002912 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002913 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002915 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002916 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002917
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002918 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002919 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002920
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002921 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002922 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002924 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002926 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002927 return -ENOMEM;
2928 }
2929
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002930 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002933 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 return err;
2935 }
2936
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002937 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2938 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002939
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002940 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002941 break;
2942 }
2943
2944 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002945 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002946
2947drop:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002948 kfree_skb(chan->sdu);
2949 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002950
2951disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002952 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002953 kfree_skb(skb);
2954 return 0;
2955}
2956
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002957static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002958{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002959 struct sk_buff *skb;
2960 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002961 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002962
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002963 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002964 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002965 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002966 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002967 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002968 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969 }
2970
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002971 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972 }
2973
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002974 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002975 goto done;
2976
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002977 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002978 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002979 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002980 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002981
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002982 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002983 __mod_monitor_timer();
2984
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002985 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986
2987done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002988 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2989 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002990
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002991 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002992
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002993 return 0;
2994}
2995
2996static void l2cap_busy_work(struct work_struct *work)
2997{
2998 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03002999 struct l2cap_chan *chan =
3000 container_of(work, struct l2cap_chan, busy_work);
3001 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003002 int n_tries = 0, timeo = HZ/5, err;
3003 struct sk_buff *skb;
3004
3005 lock_sock(sk);
3006
3007 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003008 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003009 set_current_state(TASK_INTERRUPTIBLE);
3010
3011 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3012 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003013 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003014 break;
3015 }
3016
3017 if (!timeo)
3018 timeo = HZ/5;
3019
3020 if (signal_pending(current)) {
3021 err = sock_intr_errno(timeo);
3022 break;
3023 }
3024
3025 release_sock(sk);
3026 timeo = schedule_timeout(timeo);
3027 lock_sock(sk);
3028
3029 err = sock_error(sk);
3030 if (err)
3031 break;
3032
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003033 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003034 break;
3035 }
3036
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003037 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003038 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003039
3040 release_sock(sk);
3041}
3042
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003043static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003044{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003045 int sctrl, err;
3046
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003047 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003048 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003049 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003050 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003051
3052
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003053 }
3054
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003055 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003057 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003058 return err;
3059 }
3060
3061 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003062 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003063
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003064 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003065 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003066 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003067
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003068 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003069 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003072 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003073
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003074 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003075
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003076 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077
3078 return err;
3079}
3080
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003081static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003082{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003083 struct sk_buff *_skb;
3084 int err = -EINVAL;
3085
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003086 /*
3087 * TODO: We have to notify the userland if some data is lost with the
3088 * Streaming Mode.
3089 */
3090
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003091 switch (control & L2CAP_CTRL_SAR) {
3092 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003093 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003094 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095 break;
3096 }
3097
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003098 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 if (!err)
3100 return 0;
3101
3102 break;
3103
3104 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003105 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003106 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 break;
3108 }
3109
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003110 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003111 skb_pull(skb, 2);
3112
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003113 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003114 err = -EMSGSIZE;
3115 break;
3116 }
3117
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003118 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3119 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003120 err = -ENOMEM;
3121 break;
3122 }
3123
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003124 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003125
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003126 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003127 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003128 err = 0;
3129 break;
3130
3131 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003132 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003133 break;
3134
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003135 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003136
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003137 chan->partial_sdu_len += skb->len;
3138 if (chan->partial_sdu_len > chan->sdu_len)
3139 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003140 else
3141 err = 0;
3142
3143 break;
3144
3145 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003146 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003147 break;
3148
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003149 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003150
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003151 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003152 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003153
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003154 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003155 goto drop;
3156
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003157 if (chan->partial_sdu_len == chan->sdu_len) {
3158 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003159 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003160 if (err < 0)
3161 kfree_skb(_skb);
3162 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003163 err = 0;
3164
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003165drop:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003166 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003167 break;
3168 }
3169
3170 kfree_skb(skb);
3171 return err;
3172}
3173
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003174static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003175{
3176 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003177 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003178
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003179 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003180 if (bt_cb(skb)->tx_seq != tx_seq)
3181 break;
3182
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003183 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003184 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003185 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003186 chan->buffer_seq_srej =
3187 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003188 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003189 }
3190}
3191
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003192static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003194 struct srej_list *l, *tmp;
3195 u16 control;
3196
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003197 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003198 if (l->tx_seq == tx_seq) {
3199 list_del(&l->list);
3200 kfree(l);
3201 return;
3202 }
3203 control = L2CAP_SUPER_SELECT_REJECT;
3204 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003205 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003207 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003208 }
3209}
3210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003213 struct srej_list *new;
3214 u16 control;
3215
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003216 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003217 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003218 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003219 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003220
3221 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003222 new->tx_seq = chan->expected_tx_seq;
3223 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003224 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003226 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003227}
3228
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003229static 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 -03003230{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003231 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003232 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003234 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003235 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003236 int err = 0;
3237
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003238 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3239 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003240
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003241 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003242 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003243 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003244 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003245 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003246 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003247 }
3248
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003249 chan->expected_ack_seq = req_seq;
3250 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003251
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003252 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003253 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003254
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003255 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003256 if (tx_seq_offset < 0)
3257 tx_seq_offset += 64;
3258
3259 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003260 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003261 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003262 goto drop;
3263 }
3264
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003265 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003266 goto drop;
3267
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003268 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003269 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003270
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003271 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003272 struct srej_list, list);
3273 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003274 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003275 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003276
3277 list_del(&first->list);
3278 kfree(first);
3279
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003280 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003281 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3283 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003284 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003285 }
3286 } else {
3287 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003288
3289 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003290 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003291 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003293 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003294 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003295 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296 return 0;
3297 }
3298 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003299 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003300 }
3301 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003302 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003303 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003304 if (expected_tx_seq_offset < 0)
3305 expected_tx_seq_offset += 64;
3306
3307 /* duplicated tx_seq */
3308 if (tx_seq_offset < expected_tx_seq_offset)
3309 goto drop;
3310
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003311 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003312
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003313 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003314
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003315 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003316 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003317
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003318 __skb_queue_head_init(&chan->srej_q);
3319 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003320 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003321
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003322 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003323
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003324 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003325
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003326 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003327 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003328 return 0;
3329
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003331 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003334 bt_cb(skb)->tx_seq = tx_seq;
3335 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003336 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337 return 0;
3338 }
3339
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003340 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003341 if (err < 0)
3342 return 0;
3343
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003344 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003345 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3346 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003347 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003348 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003349 }
3350
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003351 __mod_ack_timer();
3352
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003353 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3354 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003356
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003357 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003358
3359drop:
3360 kfree_skb(skb);
3361 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003362}
3363
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003364static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003365{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003366 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003367 rx_control);
3368
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003369 chan->expected_ack_seq = __get_reqseq(rx_control);
3370 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003371
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003372 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003373 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3374 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3375 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003376 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003377 __mod_retrans_timer();
3378
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003379 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3380 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003381 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003383 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003384
3385 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003387
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003388 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3389 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003390 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003391 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392
3393 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003394 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003395 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003396 __mod_retrans_timer();
3397
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3399 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3400 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003401 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003402 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003403 }
3404}
3405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003407{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003408 u8 tx_seq = __get_reqseq(rx_control);
3409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003411
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003412 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003413
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003414 chan->expected_ack_seq = tx_seq;
3415 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003416
3417 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003418 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3419 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003420 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003424
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3426 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003427 }
3428}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431 u8 tx_seq = __get_reqseq(rx_control);
3432
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003433 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003434
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003435 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436
3437 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003438 chan->expected_ack_seq = tx_seq;
3439 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003440
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003441 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3442 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003445
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003447 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449 }
3450 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003452 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
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);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 l2cap_retransmit_one_frame(chan, tx_seq);
3458 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003459 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003461 }
3462 }
3463}
3464
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003467 u8 tx_seq = __get_reqseq(rx_control);
3468
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003470
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003471 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003472 chan->expected_ack_seq = tx_seq;
3473 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003475 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003477
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003479 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003480 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003481 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003482 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003484
3485 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003487 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003489}
3490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491static 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 -03003492{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003494
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003495 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003496 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003497 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003498 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003499 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003501 }
3502
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3504 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003506 break;
3507
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003508 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003510 break;
3511
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003512 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003514 break;
3515
3516 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003518 break;
3519 }
3520
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003521 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003522 return 0;
3523}
3524
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003525static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3526{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003527 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003528 u16 control;
3529 u8 req_seq;
3530 int len, next_tx_seq_offset, req_seq_offset;
3531
3532 control = get_unaligned_le16(skb->data);
3533 skb_pull(skb, 2);
3534 len = skb->len;
3535
3536 /*
3537 * We can just drop the corrupted I-frame here.
3538 * Receiver will miss it and start proper recovery
3539 * procedures and ask retransmission.
3540 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003541 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003542 goto drop;
3543
3544 if (__is_sar_start(control) && __is_iframe(control))
3545 len -= 2;
3546
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003547 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003548 len -= 2;
3549
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003550 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003551 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003552 goto drop;
3553 }
3554
3555 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003556 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003557 if (req_seq_offset < 0)
3558 req_seq_offset += 64;
3559
3560 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003561 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003562 if (next_tx_seq_offset < 0)
3563 next_tx_seq_offset += 64;
3564
3565 /* check for invalid req-seq */
3566 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003567 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003568 goto drop;
3569 }
3570
3571 if (__is_iframe(control)) {
3572 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003573 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003574 goto drop;
3575 }
3576
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003578 } else {
3579 if (len != 0) {
3580 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003581 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003582 goto drop;
3583 }
3584
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 }
3587
3588 return 0;
3589
3590drop:
3591 kfree_skb(skb);
3592 return 0;
3593}
3594
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3596{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003597 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003598 struct sock *sk = NULL;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003599 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003600 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003601 u8 tx_seq;
3602 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003604 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003605 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 BT_DBG("unknown cid 0x%4.4x", cid);
3607 goto drop;
3608 }
3609
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003610 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003611 pi = l2cap_pi(sk);
3612
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003613 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
3615 if (sk->sk_state != BT_CONNECTED)
3616 goto drop;
3617
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003618 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003619 case L2CAP_MODE_BASIC:
3620 /* If socket recv buffers overflows we drop data here
3621 * which is *bad* because L2CAP has to be reliable.
3622 * But we don't have any other choice. L2CAP doesn't
3623 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003625 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003626 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003628 if (!sock_queue_rcv_skb(sk, skb))
3629 goto done;
3630 break;
3631
3632 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003633 if (!sock_owned_by_user(sk)) {
3634 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003635 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003636 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003637 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003638 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003639
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003640 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003641
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003642 case L2CAP_MODE_STREAMING:
3643 control = get_unaligned_le16(skb->data);
3644 skb_pull(skb, 2);
3645 len = skb->len;
3646
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003647 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003648 goto drop;
3649
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003650 if (__is_sar_start(control))
3651 len -= 2;
3652
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003653 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003654 len -= 2;
3655
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003656 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003657 goto drop;
3658
3659 tx_seq = __get_txseq(control);
3660
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003661 if (chan->expected_tx_seq == tx_seq)
3662 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003663 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003664 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003667
3668 goto done;
3669
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003670 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003671 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003672 break;
3673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
3675drop:
3676 kfree_skb(skb);
3677
3678done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003679 if (sk)
3680 bh_unlock_sock(sk);
3681
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 return 0;
3683}
3684
Al Viro8e036fc2007-07-29 00:16:36 -07003685static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686{
3687 struct sock *sk;
3688
3689 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3690 if (!sk)
3691 goto drop;
3692
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003693 bh_lock_sock(sk);
3694
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695 BT_DBG("sk %p, len %d", sk, skb->len);
3696
3697 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3698 goto drop;
3699
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003700 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 goto drop;
3702
3703 if (!sock_queue_rcv_skb(sk, skb))
3704 goto done;
3705
3706drop:
3707 kfree_skb(skb);
3708
3709done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003710 if (sk)
3711 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 return 0;
3713}
3714
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003715static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3716{
3717 struct sock *sk;
3718
3719 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3720 if (!sk)
3721 goto drop;
3722
3723 bh_lock_sock(sk);
3724
3725 BT_DBG("sk %p, len %d", sk, skb->len);
3726
3727 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3728 goto drop;
3729
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003730 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003731 goto drop;
3732
3733 if (!sock_queue_rcv_skb(sk, skb))
3734 goto done;
3735
3736drop:
3737 kfree_skb(skb);
3738
3739done:
3740 if (sk)
3741 bh_unlock_sock(sk);
3742 return 0;
3743}
3744
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3746{
3747 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003748 u16 cid, len;
3749 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750
3751 skb_pull(skb, L2CAP_HDR_SIZE);
3752 cid = __le16_to_cpu(lh->cid);
3753 len = __le16_to_cpu(lh->len);
3754
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003755 if (len != skb->len) {
3756 kfree_skb(skb);
3757 return;
3758 }
3759
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3761
3762 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003763 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003764 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 l2cap_sig_channel(conn, skb);
3766 break;
3767
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003768 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003769 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 skb_pull(skb, 2);
3771 l2cap_conless_channel(conn, psm, skb);
3772 break;
3773
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003774 case L2CAP_CID_LE_DATA:
3775 l2cap_att_channel(conn, cid, skb);
3776 break;
3777
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 default:
3779 l2cap_data_channel(conn, cid, skb);
3780 break;
3781 }
3782}
3783
3784/* ---- L2CAP interface with lower layer (HCI) ---- */
3785
3786static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3787{
3788 int exact = 0, lm1 = 0, lm2 = 0;
3789 register struct sock *sk;
3790 struct hlist_node *node;
3791
3792 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003793 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
3795 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3796
3797 /* Find listening sockets and check their link_mode */
3798 read_lock(&l2cap_sk_list.lock);
3799 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003800 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
3801
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 if (sk->sk_state != BT_LISTEN)
3803 continue;
3804
3805 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003806 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003807 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003808 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003810 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3811 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003812 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003813 lm2 |= HCI_LM_MASTER;
3814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 }
3816 read_unlock(&l2cap_sk_list.lock);
3817
3818 return exact ? lm1 : lm2;
3819}
3820
3821static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3822{
Marcel Holtmann01394182006-07-03 10:02:46 +02003823 struct l2cap_conn *conn;
3824
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3826
Ville Tervoacd7d372011-02-10 22:38:49 -03003827 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003828 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829
3830 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 conn = l2cap_conn_add(hcon, status);
3832 if (conn)
3833 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003834 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 l2cap_conn_del(hcon, bt_err(status));
3836
3837 return 0;
3838}
3839
Marcel Holtmann2950f212009-02-12 14:02:50 +01003840static int l2cap_disconn_ind(struct hci_conn *hcon)
3841{
3842 struct l2cap_conn *conn = hcon->l2cap_data;
3843
3844 BT_DBG("hcon %p", hcon);
3845
3846 if (hcon->type != ACL_LINK || !conn)
3847 return 0x13;
3848
3849 return conn->disc_reason;
3850}
3851
3852static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853{
3854 BT_DBG("hcon %p reason %d", hcon, reason);
3855
Ville Tervoacd7d372011-02-10 22:38:49 -03003856 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003857 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858
3859 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003860
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 return 0;
3862}
3863
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003864static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003865{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003866 struct sock *sk = chan->sk;
3867
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003868 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003869 return;
3870
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003871 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003872 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003873 l2cap_sock_clear_timer(sk);
3874 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003875 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003876 __l2cap_sock_close(sk, ECONNREFUSED);
3877 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003878 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003879 l2cap_sock_clear_timer(sk);
3880 }
3881}
3882
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003883static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003885 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003886 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
Marcel Holtmann01394182006-07-03 10:02:46 +02003888 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003890
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 BT_DBG("conn %p", conn);
3892
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003893 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003895 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003896 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003897
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 bh_lock_sock(sk);
3899
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003900 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003901 bh_unlock_sock(sk);
3902 continue;
3903 }
3904
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003905 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003906 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003907 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003908 bh_unlock_sock(sk);
3909 continue;
3910 }
3911
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003912 if (sk->sk_state == BT_CONNECT) {
3913 if (!status) {
3914 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003915 req.scid = cpu_to_le16(chan->scid);
3916 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003917
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003918 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003919 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003920
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003921 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003922 L2CAP_CONN_REQ, sizeof(req), &req);
3923 } else {
3924 l2cap_sock_clear_timer(sk);
3925 l2cap_sock_set_timer(sk, HZ / 10);
3926 }
3927 } else if (sk->sk_state == BT_CONNECT2) {
3928 struct l2cap_conn_rsp rsp;
3929 __u16 result;
3930
3931 if (!status) {
3932 sk->sk_state = BT_CONFIG;
3933 result = L2CAP_CR_SUCCESS;
3934 } else {
3935 sk->sk_state = BT_DISCONN;
3936 l2cap_sock_set_timer(sk, HZ / 10);
3937 result = L2CAP_CR_SEC_BLOCK;
3938 }
3939
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003940 rsp.scid = cpu_to_le16(chan->dcid);
3941 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003942 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003943 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003944 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3945 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 }
3947
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 bh_unlock_sock(sk);
3949 }
3950
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003951 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003952
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 return 0;
3954}
3955
3956static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3957{
3958 struct l2cap_conn *conn = hcon->l2cap_data;
3959
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003960 if (!conn)
3961 conn = l2cap_conn_add(hcon, 0);
3962
3963 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 goto drop;
3965
3966 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3967
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003968 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003970 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003971 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 int len;
3973
3974 if (conn->rx_len) {
3975 BT_ERR("Unexpected start frame (len %d)", skb->len);
3976 kfree_skb(conn->rx_skb);
3977 conn->rx_skb = NULL;
3978 conn->rx_len = 0;
3979 l2cap_conn_unreliable(conn, ECOMM);
3980 }
3981
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003982 /* Start fragment always begin with Basic L2CAP header */
3983 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 BT_ERR("Frame is too short (len %d)", skb->len);
3985 l2cap_conn_unreliable(conn, ECOMM);
3986 goto drop;
3987 }
3988
3989 hdr = (struct l2cap_hdr *) skb->data;
3990 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003991 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
3993 if (len == skb->len) {
3994 /* Complete frame received */
3995 l2cap_recv_frame(conn, skb);
3996 return 0;
3997 }
3998
3999 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4000
4001 if (skb->len > len) {
4002 BT_ERR("Frame is too long (len %d, expected len %d)",
4003 skb->len, len);
4004 l2cap_conn_unreliable(conn, ECOMM);
4005 goto drop;
4006 }
4007
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004008 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004009
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004010 if (chan && chan->sk) {
4011 struct sock *sk = chan->sk;
4012
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004013 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004014 BT_ERR("Frame exceeding recv MTU (len %d, "
4015 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004016 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004017 bh_unlock_sock(sk);
4018 l2cap_conn_unreliable(conn, ECOMM);
4019 goto drop;
4020 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004021 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004022 }
4023
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004025 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4026 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 goto drop;
4028
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004029 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004030 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 conn->rx_len = len - skb->len;
4032 } else {
4033 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4034
4035 if (!conn->rx_len) {
4036 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4037 l2cap_conn_unreliable(conn, ECOMM);
4038 goto drop;
4039 }
4040
4041 if (skb->len > conn->rx_len) {
4042 BT_ERR("Fragment is too long (len %d, expected %d)",
4043 skb->len, conn->rx_len);
4044 kfree_skb(conn->rx_skb);
4045 conn->rx_skb = NULL;
4046 conn->rx_len = 0;
4047 l2cap_conn_unreliable(conn, ECOMM);
4048 goto drop;
4049 }
4050
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004051 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004052 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 conn->rx_len -= skb->len;
4054
4055 if (!conn->rx_len) {
4056 /* Complete frame received */
4057 l2cap_recv_frame(conn, conn->rx_skb);
4058 conn->rx_skb = NULL;
4059 }
4060 }
4061
4062drop:
4063 kfree_skb(skb);
4064 return 0;
4065}
4066
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004067static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068{
4069 struct sock *sk;
4070 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
4072 read_lock_bh(&l2cap_sk_list.lock);
4073
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004074 sk_for_each(sk, node, &l2cap_sk_list.head) {
4075 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004076 struct l2cap_chan *chan = pi->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004078 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 +01004079 batostr(&bt_sk(sk)->src),
4080 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004081 sk->sk_state, __le16_to_cpu(chan->psm),
4082 chan->scid, chan->dcid,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004083 chan->imtu, chan->omtu, chan->sec_level,
4084 chan->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004088
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004089 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090}
4091
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004092static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4093{
4094 return single_open(file, l2cap_debugfs_show, inode->i_private);
4095}
4096
4097static const struct file_operations l2cap_debugfs_fops = {
4098 .open = l2cap_debugfs_open,
4099 .read = seq_read,
4100 .llseek = seq_lseek,
4101 .release = single_release,
4102};
4103
4104static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106static struct hci_proto l2cap_hci_proto = {
4107 .name = "L2CAP",
4108 .id = HCI_PROTO_L2CAP,
4109 .connect_ind = l2cap_connect_ind,
4110 .connect_cfm = l2cap_connect_cfm,
4111 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004112 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004113 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 .recv_acldata = l2cap_recv_acldata
4115};
4116
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004117int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118{
4119 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004120
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004121 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 if (err < 0)
4123 return err;
4124
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004125 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004126 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004127 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 goto error;
4129 }
4130
4131 err = hci_register_proto(&l2cap_hci_proto);
4132 if (err < 0) {
4133 BT_ERR("L2CAP protocol registration failed");
4134 bt_sock_unregister(BTPROTO_L2CAP);
4135 goto error;
4136 }
4137
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004138 if (bt_debugfs) {
4139 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4140 bt_debugfs, NULL, &l2cap_debugfs_fops);
4141 if (!l2cap_debugfs)
4142 BT_ERR("Failed to create L2CAP debug file");
4143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145 return 0;
4146
4147error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004148 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004149 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 return err;
4151}
4152
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004153void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004155 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004157 flush_workqueue(_busy_wq);
4158 destroy_workqueue(_busy_wq);
4159
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4161 BT_ERR("L2CAP protocol unregistration failed");
4162
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004163 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164}
4165
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004166module_param(disable_ertm, bool, 0644);
4167MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");