blob: 481cec22ef96f71aa1f62bd9d14f71e4452dad87 [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
4
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth L2CAP core and sockets. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080030#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
32#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/sched.h>
34#include <linux/slab.h>
35#include <linux/poll.h>
36#include <linux/fcntl.h>
37#include <linux/init.h>
38#include <linux/interrupt.h>
39#include <linux/socket.h>
40#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080042#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010043#include <linux/debugfs.h>
44#include <linux/seq_file.h>
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -030045#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030046#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <net/sock.h>
48
49#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <asm/unaligned.h>
51
52#include <net/bluetooth/bluetooth.h>
53#include <net/bluetooth/hci_core.h>
54#include <net/bluetooth/l2cap.h>
55
Marcel Holtmann44dd46d2009-05-02 19:09:01 -070056#define VERSION "2.14"
57
Gustavo F. Padovan84fb0a62010-05-01 16:15:42 -030058#ifdef CONFIG_BT_L2CAP_EXT_FEATURES
59static int enable_ertm = 1;
60#else
Marcel Holtmann44dd46d2009-05-02 19:09:01 -070061static int enable_ertm = 0;
Gustavo F. Padovan84fb0a62010-05-01 16:15:42 -030062#endif
Marcel Holtmann5fbcd3d2009-10-05 11:35:43 +020063static int max_transmit = L2CAP_DEFAULT_MAX_TX;
Gustavo F. Padovan369ba302010-05-01 16:15:41 -030064static int tx_window = L2CAP_DEFAULT_TX_WINDOW;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020065
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070066static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010067static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Eric Dumazet90ddc4f2005-12-22 12:49:22 -080069static const struct proto_ops l2cap_sock_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
71static struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070072 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
Linus Torvalds1da177e2005-04-16 15:20:36 -070075static void __l2cap_sock_close(struct sock *sk, int reason);
76static void l2cap_sock_close(struct sock *sk);
77static void l2cap_sock_kill(struct sock *sk);
78
79static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
80 u8 code, u8 ident, u16 dlen, void *data);
81
82/* ---- L2CAP timers ---- */
83static void l2cap_sock_timeout(unsigned long arg)
84{
85 struct sock *sk = (struct sock *) arg;
Marcel Holtmannb1235d72008-07-14 20:13:54 +020086 int reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88 BT_DBG("sock %p state %d", sk, sk->sk_state);
89
90 bh_lock_sock(sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +020091
Marcel Holtmannf62e4322009-01-15 21:58:44 +010092 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
93 reason = ECONNREFUSED;
94 else if (sk->sk_state == BT_CONNECT &&
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +010095 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
Marcel Holtmannb1235d72008-07-14 20:13:54 +020096 reason = ECONNREFUSED;
97 else
98 reason = ETIMEDOUT;
99
100 __l2cap_sock_close(sk, reason);
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 bh_unlock_sock(sk);
103
104 l2cap_sock_kill(sk);
105 sock_put(sk);
106}
107
108static void l2cap_sock_set_timer(struct sock *sk, long timeout)
109{
110 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
111 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
112}
113
114static void l2cap_sock_clear_timer(struct sock *sk)
115{
116 BT_DBG("sock %p state %d", sk, sk->sk_state);
117 sk_stop_timer(sk, &sk->sk_timer);
118}
119
Marcel Holtmann01394182006-07-03 10:02:46 +0200120/* ---- L2CAP channels ---- */
121static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
122{
123 struct sock *s;
124 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
125 if (l2cap_pi(s)->dcid == cid)
126 break;
127 }
128 return s;
129}
130
131static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
132{
133 struct sock *s;
134 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
135 if (l2cap_pi(s)->scid == cid)
136 break;
137 }
138 return s;
139}
140
141/* Find channel with given SCID.
142 * Returns locked socket */
143static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
144{
145 struct sock *s;
146 read_lock(&l->lock);
147 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300148 if (s)
149 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200150 read_unlock(&l->lock);
151 return s;
152}
153
154static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
155{
156 struct sock *s;
157 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
158 if (l2cap_pi(s)->ident == ident)
159 break;
160 }
161 return s;
162}
163
164static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
165{
166 struct sock *s;
167 read_lock(&l->lock);
168 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300169 if (s)
170 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171 read_unlock(&l->lock);
172 return s;
173}
174
175static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
176{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300177 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200178
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300179 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300180 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200181 return cid;
182 }
183
184 return 0;
185}
186
187static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
188{
189 sock_hold(sk);
190
191 if (l->head)
192 l2cap_pi(l->head)->prev_c = sk;
193
194 l2cap_pi(sk)->next_c = l->head;
195 l2cap_pi(sk)->prev_c = NULL;
196 l->head = sk;
197}
198
199static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
200{
201 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
202
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200203 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200204 if (sk == l->head)
205 l->head = next;
206
207 if (next)
208 l2cap_pi(next)->prev_c = prev;
209 if (prev)
210 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200211 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200212
213 __sock_put(sk);
214}
215
216static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
217{
218 struct l2cap_chan_list *l = &conn->chan_list;
219
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300220 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
221 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200222
Marcel Holtmann2950f212009-02-12 14:02:50 +0100223 conn->disc_reason = 0x13;
224
Marcel Holtmann01394182006-07-03 10:02:46 +0200225 l2cap_pi(sk)->conn = conn;
226
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300227 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 /* Alloc CID for connection-oriented socket */
229 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
230 } else if (sk->sk_type == SOCK_DGRAM) {
231 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300232 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
233 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200234 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
235 } else {
236 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300237 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
238 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200239 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
240 }
241
242 __l2cap_chan_link(l, sk);
243
244 if (parent)
245 bt_accept_enqueue(parent, sk);
246}
247
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900248/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200249 * Must be called on the locked socket. */
250static void l2cap_chan_del(struct sock *sk, int err)
251{
252 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
253 struct sock *parent = bt_sk(sk)->parent;
254
255 l2cap_sock_clear_timer(sk);
256
257 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
258
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900259 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200260 /* Unlink from channel list */
261 l2cap_chan_unlink(&conn->chan_list, sk);
262 l2cap_pi(sk)->conn = NULL;
263 hci_conn_put(conn->hcon);
264 }
265
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200266 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200267 sock_set_flag(sk, SOCK_ZAPPED);
268
269 if (err)
270 sk->sk_err = err;
271
272 if (parent) {
273 bt_accept_unlink(sk);
274 parent->sk_data_ready(parent, 0);
275 } else
276 sk->sk_state_change(sk);
277}
278
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200279/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100280static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200281{
282 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100283 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200284
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100285 if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
286 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
287 auth_type = HCI_AT_NO_BONDING_MITM;
288 else
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300289 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100290
291 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
292 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
293 } else {
294 switch (l2cap_pi(sk)->sec_level) {
295 case BT_SECURITY_HIGH:
296 auth_type = HCI_AT_GENERAL_BONDING_MITM;
297 break;
298 case BT_SECURITY_MEDIUM:
299 auth_type = HCI_AT_GENERAL_BONDING;
300 break;
301 default:
302 auth_type = HCI_AT_NO_BONDING;
303 break;
304 }
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100305 }
306
307 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
308 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200309}
310
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200311static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
312{
313 u8 id;
314
315 /* Get next available identificator.
316 * 1 - 128 are used by kernel.
317 * 129 - 199 are reserved.
318 * 200 - 254 are used by utilities like l2ping, etc.
319 */
320
321 spin_lock_bh(&conn->lock);
322
323 if (++conn->tx_ident > 128)
324 conn->tx_ident = 1;
325
326 id = conn->tx_ident;
327
328 spin_unlock_bh(&conn->lock);
329
330 return id;
331}
332
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300333static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334{
335 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
336
337 BT_DBG("code 0x%2.2x", code);
338
339 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300340 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200341
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300342 hci_send_acl(conn->hcon, skb, 0);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200343}
344
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300345static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300346{
347 struct sk_buff *skb;
348 struct l2cap_hdr *lh;
349 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350 int count, hlen = L2CAP_HDR_SIZE + 2;
351
352 if (pi->fcs == L2CAP_FCS_CRC16)
353 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300354
355 BT_DBG("pi %p, control 0x%2.2x", pi, control);
356
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300357 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300358 control |= L2CAP_CTRL_FRAME_TYPE;
359
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300360 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
361 control |= L2CAP_CTRL_FINAL;
362 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
363 }
364
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300365 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
366 control |= L2CAP_CTRL_POLL;
367 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
368 }
369
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300370 skb = bt_skb_alloc(count, GFP_ATOMIC);
371 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300372 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300373
374 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300375 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300376 lh->cid = cpu_to_le16(pi->dcid);
377 put_unaligned_le16(control, skb_put(skb, 2));
378
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300379 if (pi->fcs == L2CAP_FCS_CRC16) {
380 u16 fcs = crc16(0, (u8 *)lh, count - 2);
381 put_unaligned_le16(fcs, skb_put(skb, 2));
382 }
383
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300384 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385}
386
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300387static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300388{
389 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY)
390 control |= L2CAP_SUPER_RCV_NOT_READY;
391 else
392 control |= L2CAP_SUPER_RCV_READY;
393
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300394 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
395
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300396 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300397}
398
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200399static void l2cap_do_start(struct sock *sk)
400{
401 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
402
403 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100404 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
405 return;
406
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100407 if (l2cap_check_security(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200408 struct l2cap_conn_req req;
409 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
410 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200411
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200412 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200413
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200414 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200415 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200416 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200417 } else {
418 struct l2cap_info_req req;
419 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
420
421 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
422 conn->info_ident = l2cap_get_ident(conn);
423
424 mod_timer(&conn->info_timer, jiffies +
425 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
426
427 l2cap_send_cmd(conn, conn->info_ident,
428 L2CAP_INFO_REQ, sizeof(req), &req);
429 }
430}
431
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300432static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
433{
434 struct l2cap_disconn_req req;
435
436 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
437 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
438 l2cap_send_cmd(conn, l2cap_get_ident(conn),
439 L2CAP_DISCONN_REQ, sizeof(req), &req);
440}
441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200443static void l2cap_conn_start(struct l2cap_conn *conn)
444{
445 struct l2cap_chan_list *l = &conn->chan_list;
446 struct sock *sk;
447
448 BT_DBG("conn %p", conn);
449
450 read_lock(&l->lock);
451
452 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
453 bh_lock_sock(sk);
454
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300455 if (sk->sk_type != SOCK_SEQPACKET &&
456 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200457 bh_unlock_sock(sk);
458 continue;
459 }
460
461 if (sk->sk_state == BT_CONNECT) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100462 if (l2cap_check_security(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200463 struct l2cap_conn_req req;
464 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
465 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200466
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200467 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200468
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200469 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200470 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200471 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200472 } else if (sk->sk_state == BT_CONNECT2) {
473 struct l2cap_conn_rsp rsp;
474 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
475 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
476
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100477 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100478 if (bt_sk(sk)->defer_setup) {
479 struct sock *parent = bt_sk(sk)->parent;
480 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
481 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
482 parent->sk_data_ready(parent, 0);
483
484 } else {
485 sk->sk_state = BT_CONFIG;
486 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
487 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
488 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200489 } else {
490 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
491 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
492 }
493
494 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
495 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
496 }
497
498 bh_unlock_sock(sk);
499 }
500
501 read_unlock(&l->lock);
502}
503
504static void l2cap_conn_ready(struct l2cap_conn *conn)
505{
506 struct l2cap_chan_list *l = &conn->chan_list;
507 struct sock *sk;
508
509 BT_DBG("conn %p", conn);
510
511 read_lock(&l->lock);
512
513 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
514 bh_lock_sock(sk);
515
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300516 if (sk->sk_type != SOCK_SEQPACKET &&
517 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200518 l2cap_sock_clear_timer(sk);
519 sk->sk_state = BT_CONNECTED;
520 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200521 } else if (sk->sk_state == BT_CONNECT)
522 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200523
524 bh_unlock_sock(sk);
525 }
526
527 read_unlock(&l->lock);
528}
529
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200530/* Notify sockets that we cannot guaranty reliability anymore */
531static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
532{
533 struct l2cap_chan_list *l = &conn->chan_list;
534 struct sock *sk;
535
536 BT_DBG("conn %p", conn);
537
538 read_lock(&l->lock);
539
540 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100541 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200542 sk->sk_err = err;
543 }
544
545 read_unlock(&l->lock);
546}
547
548static void l2cap_info_timeout(unsigned long arg)
549{
550 struct l2cap_conn *conn = (void *) arg;
551
Marcel Holtmann984947d2009-02-06 23:35:19 +0100552 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100553 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100554
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200555 l2cap_conn_start(conn);
556}
557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
559{
Marcel Holtmann01394182006-07-03 10:02:46 +0200560 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Marcel Holtmann01394182006-07-03 10:02:46 +0200562 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 return conn;
564
Marcel Holtmann01394182006-07-03 10:02:46 +0200565 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
566 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 hcon->l2cap_data = conn;
570 conn->hcon = hcon;
571
Marcel Holtmann01394182006-07-03 10:02:46 +0200572 BT_DBG("hcon %p conn %p", hcon, conn);
573
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 conn->mtu = hcon->hdev->acl_mtu;
575 conn->src = &hcon->hdev->bdaddr;
576 conn->dst = &hcon->dst;
577
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200578 conn->feat_mask = 0;
579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 spin_lock_init(&conn->lock);
581 rwlock_init(&conn->chan_list.lock);
582
Dave Young45054dc2009-10-18 20:28:30 +0000583 setup_timer(&conn->info_timer, l2cap_info_timeout,
584 (unsigned long) conn);
585
Marcel Holtmann2950f212009-02-12 14:02:50 +0100586 conn->disc_reason = 0x13;
587
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 return conn;
589}
590
Marcel Holtmann01394182006-07-03 10:02:46 +0200591static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592{
Marcel Holtmann01394182006-07-03 10:02:46 +0200593 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 struct sock *sk;
595
Marcel Holtmann01394182006-07-03 10:02:46 +0200596 if (!conn)
597 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
600
Wei Yongjun7585b972009-02-25 18:29:52 +0800601 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
603 /* Kill channels */
604 while ((sk = conn->chan_list.head)) {
605 bh_lock_sock(sk);
606 l2cap_chan_del(sk, err);
607 bh_unlock_sock(sk);
608 l2cap_sock_kill(sk);
609 }
610
Dave Young8e8440f2008-03-03 12:18:55 -0800611 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
612 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800613
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 hcon->l2cap_data = NULL;
615 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616}
617
618static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
619{
620 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200621 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200623 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626/* ---- Socket interface ---- */
Al Viro8e036fc2007-07-29 00:16:36 -0700627static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 struct sock *sk;
630 struct hlist_node *node;
631 sk_for_each(sk, node, &l2cap_sk_list.head)
632 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
633 goto found;
634 sk = NULL;
635found:
636 return sk;
637}
638
639/* Find socket with psm and source bdaddr.
640 * Returns closest match.
641 */
Al Viro8e036fc2007-07-29 00:16:36 -0700642static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{
644 struct sock *sk = NULL, *sk1 = NULL;
645 struct hlist_node *node;
646
647 sk_for_each(sk, node, &l2cap_sk_list.head) {
648 if (state && sk->sk_state != state)
649 continue;
650
651 if (l2cap_pi(sk)->psm == psm) {
652 /* Exact match. */
653 if (!bacmp(&bt_sk(sk)->src, src))
654 break;
655
656 /* Closest match */
657 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
658 sk1 = sk;
659 }
660 }
661 return node ? sk : sk1;
662}
663
664/* Find socket with given address (psm, src).
665 * Returns locked socket */
Al Viro8e036fc2007-07-29 00:16:36 -0700666static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667{
668 struct sock *s;
669 read_lock(&l2cap_sk_list.lock);
670 s = __l2cap_get_sock_by_psm(state, psm, src);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300671 if (s)
672 bh_lock_sock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 read_unlock(&l2cap_sk_list.lock);
674 return s;
675}
676
677static void l2cap_sock_destruct(struct sock *sk)
678{
679 BT_DBG("sk %p", sk);
680
681 skb_queue_purge(&sk->sk_receive_queue);
682 skb_queue_purge(&sk->sk_write_queue);
683}
684
685static void l2cap_sock_cleanup_listen(struct sock *parent)
686{
687 struct sock *sk;
688
689 BT_DBG("parent %p", parent);
690
691 /* Close not yet accepted channels */
692 while ((sk = bt_accept_dequeue(parent, NULL)))
693 l2cap_sock_close(sk);
694
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200695 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 sock_set_flag(parent, SOCK_ZAPPED);
697}
698
699/* Kill socket (only if zapped and orphan)
700 * Must be called on unlocked socket.
701 */
702static void l2cap_sock_kill(struct sock *sk)
703{
704 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
705 return;
706
707 BT_DBG("sk %p state %d", sk, sk->sk_state);
708
709 /* Kill poor orphan */
710 bt_sock_unlink(&l2cap_sk_list, sk);
711 sock_set_flag(sk, SOCK_DEAD);
712 sock_put(sk);
713}
714
715static void __l2cap_sock_close(struct sock *sk, int reason)
716{
717 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
718
719 switch (sk->sk_state) {
720 case BT_LISTEN:
721 l2cap_sock_cleanup_listen(sk);
722 break;
723
724 case BT_CONNECTED:
725 case BT_CONFIG:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300726 if (sk->sk_type == SOCK_SEQPACKET ||
727 sk->sk_type == SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 sk->sk_state = BT_DISCONN;
731 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300732 l2cap_send_disconn_req(conn, sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200733 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 break;
736
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100737 case BT_CONNECT2:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300738 if (sk->sk_type == SOCK_SEQPACKET ||
739 sk->sk_type == SOCK_STREAM) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100740 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
741 struct l2cap_conn_rsp rsp;
742 __u16 result;
743
744 if (bt_sk(sk)->defer_setup)
745 result = L2CAP_CR_SEC_BLOCK;
746 else
747 result = L2CAP_CR_BAD_PSM;
748
749 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
750 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
751 rsp.result = cpu_to_le16(result);
752 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
753 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
754 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
755 } else
756 l2cap_chan_del(sk, reason);
757 break;
758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 case BT_CONNECT:
760 case BT_DISCONN:
761 l2cap_chan_del(sk, reason);
762 break;
763
764 default:
765 sock_set_flag(sk, SOCK_ZAPPED);
766 break;
767 }
768}
769
770/* Must be called on unlocked socket. */
771static void l2cap_sock_close(struct sock *sk)
772{
773 l2cap_sock_clear_timer(sk);
774 lock_sock(sk);
775 __l2cap_sock_close(sk, ECONNRESET);
776 release_sock(sk);
777 l2cap_sock_kill(sk);
778}
779
780static void l2cap_sock_init(struct sock *sk, struct sock *parent)
781{
782 struct l2cap_pinfo *pi = l2cap_pi(sk);
783
784 BT_DBG("sk %p", sk);
785
786 if (parent) {
787 sk->sk_type = parent->sk_type;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100788 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 pi->imtu = l2cap_pi(parent)->imtu;
791 pi->omtu = l2cap_pi(parent)->omtu;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700792 pi->mode = l2cap_pi(parent)->mode;
793 pi->fcs = l2cap_pi(parent)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -0300794 pi->max_tx = l2cap_pi(parent)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -0300795 pi->tx_win = l2cap_pi(parent)->tx_win;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100796 pi->sec_level = l2cap_pi(parent)->sec_level;
797 pi->role_switch = l2cap_pi(parent)->role_switch;
798 pi->force_reliable = l2cap_pi(parent)->force_reliable;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 } else {
800 pi->imtu = L2CAP_DEFAULT_MTU;
801 pi->omtu = 0;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300802 if (enable_ertm && sk->sk_type == SOCK_STREAM)
803 pi->mode = L2CAP_MODE_ERTM;
804 else
805 pi->mode = L2CAP_MODE_BASIC;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -0300806 pi->max_tx = max_transmit;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700807 pi->fcs = L2CAP_FCS_CRC16;
Gustavo F. Padovan369ba302010-05-01 16:15:41 -0300808 pi->tx_win = tx_window;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100809 pi->sec_level = BT_SECURITY_LOW;
810 pi->role_switch = 0;
811 pi->force_reliable = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 }
813
814 /* Default config options */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +0200815 pi->conf_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Dave Young45054dc2009-10-18 20:28:30 +0000817 skb_queue_head_init(TX_QUEUE(sk));
818 skb_queue_head_init(SREJ_QUEUE(sk));
819 INIT_LIST_HEAD(SREJ_LIST(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821
822static struct proto l2cap_proto = {
823 .name = "L2CAP",
824 .owner = THIS_MODULE,
825 .obj_size = sizeof(struct l2cap_pinfo)
826};
827
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700828static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829{
830 struct sock *sk;
831
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700832 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 if (!sk)
834 return NULL;
835
836 sock_init_data(sock, sk);
837 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
838
839 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200840 sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
842 sock_reset_flag(sk, SOCK_ZAPPED);
843
844 sk->sk_protocol = proto;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200845 sk->sk_state = BT_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200847 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
849 bt_sock_link(&l2cap_sk_list, sk);
850 return sk;
851}
852
Eric Paris3f378b62009-11-05 22:18:14 -0800853static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
854 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855{
856 struct sock *sk;
857
858 BT_DBG("sock %p", sock);
859
860 sock->state = SS_UNCONNECTED;
861
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300862 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
864 return -ESOCKTNOSUPPORT;
865
Eric Parisc84b3262009-11-05 20:45:52 -0800866 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 return -EPERM;
868
869 sock->ops = &l2cap_sock_ops;
870
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700871 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 if (!sk)
873 return -ENOMEM;
874
875 l2cap_sock_init(sk, NULL);
876 return 0;
877}
878
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100879static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100882 struct sockaddr_l2 la;
883 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100885 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 if (!addr || addr->sa_family != AF_BLUETOOTH)
888 return -EINVAL;
889
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100890 memset(&la, 0, sizeof(la));
891 len = min_t(unsigned int, sizeof(la), alen);
892 memcpy(&la, addr, len);
893
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100894 if (la.l2_cid)
895 return -EINVAL;
896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 lock_sock(sk);
898
899 if (sk->sk_state != BT_OPEN) {
900 err = -EBADFD;
901 goto done;
902 }
903
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200904 if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
Marcel Holtmann847641d2007-01-22 22:00:45 +0100905 !capable(CAP_NET_BIND_SERVICE)) {
906 err = -EACCES;
907 goto done;
908 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900909
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 write_lock_bh(&l2cap_sk_list.lock);
911
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100912 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 err = -EADDRINUSE;
914 } else {
915 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100916 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
917 l2cap_pi(sk)->psm = la.l2_psm;
918 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100920
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200921 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
922 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100923 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 }
925
926 write_unlock_bh(&l2cap_sk_list.lock);
927
928done:
929 release_sock(sk);
930 return err;
931}
932
933static int l2cap_do_connect(struct sock *sk)
934{
935 bdaddr_t *src = &bt_sk(sk)->src;
936 bdaddr_t *dst = &bt_sk(sk)->dst;
937 struct l2cap_conn *conn;
938 struct hci_conn *hcon;
939 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200940 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200941 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100943 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
944 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300946 hdev = hci_get_route(dst, src);
947 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return -EHOSTUNREACH;
949
950 hci_dev_lock_bh(hdev);
951
952 err = -ENOMEM;
953
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100954 if (sk->sk_type == SOCK_RAW) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100955 switch (l2cap_pi(sk)->sec_level) {
956 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100957 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100958 break;
959 case BT_SECURITY_MEDIUM:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100960 auth_type = HCI_AT_DEDICATED_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100961 break;
962 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100963 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100964 break;
965 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100966 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100967 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200968 auth_type = HCI_AT_NO_BONDING_MITM;
969 else
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200970 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann435fef22009-02-09 03:55:28 +0100971
972 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
973 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100974 } else {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100975 switch (l2cap_pi(sk)->sec_level) {
976 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100977 auth_type = HCI_AT_GENERAL_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100978 break;
979 case BT_SECURITY_MEDIUM:
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200980 auth_type = HCI_AT_GENERAL_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100981 break;
982 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100983 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100984 break;
985 }
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200986 }
987
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100988 hcon = hci_connect(hdev, ACL_LINK, dst,
989 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 if (!hcon)
991 goto done;
992
993 conn = l2cap_conn_add(hcon, 0);
994 if (!conn) {
995 hci_conn_put(hcon);
996 goto done;
997 }
998
999 err = 0;
1000
1001 /* Update source addr of the socket */
1002 bacpy(src, conn->src);
1003
1004 l2cap_chan_add(conn, sk, NULL);
1005
1006 sk->sk_state = BT_CONNECT;
1007 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1008
1009 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001010 if (sk->sk_type != SOCK_SEQPACKET &&
1011 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 l2cap_sock_clear_timer(sk);
1013 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001014 } else
1015 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017
1018done:
1019 hci_dev_unlock_bh(hdev);
1020 hci_dev_put(hdev);
1021 return err;
1022}
1023
1024static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
1025{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001027 struct sockaddr_l2 la;
1028 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 BT_DBG("sk %p", sk);
1031
Changli Gao6503d962010-03-31 22:58:26 +00001032 if (!addr || alen < sizeof(addr->sa_family) ||
1033 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001034 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001036 memset(&la, 0, sizeof(la));
1037 len = min_t(unsigned int, sizeof(la), alen);
1038 memcpy(&la, addr, len);
1039
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001040 if (la.l2_cid)
1041 return -EINVAL;
1042
1043 lock_sock(sk);
1044
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001045 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
1046 && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 err = -EINVAL;
1048 goto done;
1049 }
1050
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001051 switch (l2cap_pi(sk)->mode) {
1052 case L2CAP_MODE_BASIC:
1053 break;
1054 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001055 case L2CAP_MODE_STREAMING:
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001056 if (enable_ertm)
1057 break;
1058 /* fall through */
1059 default:
1060 err = -ENOTSUPP;
1061 goto done;
1062 }
1063
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001064 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 case BT_CONNECT:
1066 case BT_CONNECT2:
1067 case BT_CONFIG:
1068 /* Already connecting */
1069 goto wait;
1070
1071 case BT_CONNECTED:
1072 /* Already connected */
1073 goto done;
1074
1075 case BT_OPEN:
1076 case BT_BOUND:
1077 /* Can connect */
1078 break;
1079
1080 default:
1081 err = -EBADFD;
1082 goto done;
1083 }
1084
1085 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001086 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1087 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001089 err = l2cap_do_connect(sk);
1090 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 goto done;
1092
1093wait:
1094 err = bt_sock_wait_state(sk, BT_CONNECTED,
1095 sock_sndtimeo(sk, flags & O_NONBLOCK));
1096done:
1097 release_sock(sk);
1098 return err;
1099}
1100
1101static int l2cap_sock_listen(struct socket *sock, int backlog)
1102{
1103 struct sock *sk = sock->sk;
1104 int err = 0;
1105
1106 BT_DBG("sk %p backlog %d", sk, backlog);
1107
1108 lock_sock(sk);
1109
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001110 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1111 || sk->sk_state != BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 err = -EBADFD;
1113 goto done;
1114 }
1115
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001116 switch (l2cap_pi(sk)->mode) {
1117 case L2CAP_MODE_BASIC:
1118 break;
1119 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001120 case L2CAP_MODE_STREAMING:
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001121 if (enable_ertm)
1122 break;
1123 /* fall through */
1124 default:
1125 err = -ENOTSUPP;
1126 goto done;
1127 }
1128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 if (!l2cap_pi(sk)->psm) {
1130 bdaddr_t *src = &bt_sk(sk)->src;
1131 u16 psm;
1132
1133 err = -EINVAL;
1134
1135 write_lock_bh(&l2cap_sk_list.lock);
1136
1137 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001138 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1139 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1140 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 err = 0;
1142 break;
1143 }
1144
1145 write_unlock_bh(&l2cap_sk_list.lock);
1146
1147 if (err < 0)
1148 goto done;
1149 }
1150
1151 sk->sk_max_ack_backlog = backlog;
1152 sk->sk_ack_backlog = 0;
1153 sk->sk_state = BT_LISTEN;
1154
1155done:
1156 release_sock(sk);
1157 return err;
1158}
1159
1160static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
1161{
1162 DECLARE_WAITQUEUE(wait, current);
1163 struct sock *sk = sock->sk, *nsk;
1164 long timeo;
1165 int err = 0;
1166
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001167 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
1169 if (sk->sk_state != BT_LISTEN) {
1170 err = -EBADFD;
1171 goto done;
1172 }
1173
1174 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1175
1176 BT_DBG("sk %p timeo %ld", sk, timeo);
1177
1178 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001179 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1181 set_current_state(TASK_INTERRUPTIBLE);
1182 if (!timeo) {
1183 err = -EAGAIN;
1184 break;
1185 }
1186
1187 release_sock(sk);
1188 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001189 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
1191 if (sk->sk_state != BT_LISTEN) {
1192 err = -EBADFD;
1193 break;
1194 }
1195
1196 if (signal_pending(current)) {
1197 err = sock_intr_errno(timeo);
1198 break;
1199 }
1200 }
1201 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001202 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
1204 if (err)
1205 goto done;
1206
1207 newsock->state = SS_CONNECTED;
1208
1209 BT_DBG("new socket %p", nsk);
1210
1211done:
1212 release_sock(sk);
1213 return err;
1214}
1215
1216static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
1217{
1218 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1219 struct sock *sk = sock->sk;
1220
1221 BT_DBG("sock %p, sk %p", sock, sk);
1222
1223 addr->sa_family = AF_BLUETOOTH;
1224 *len = sizeof(struct sockaddr_l2);
1225
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001226 if (peer) {
1227 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001229 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001230 } else {
1231 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001233 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 return 0;
1237}
1238
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001239static void l2cap_monitor_timeout(unsigned long arg)
1240{
1241 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001242
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001243 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001244 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
1245 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001246 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001247 return;
1248 }
1249
1250 l2cap_pi(sk)->retry_count++;
1251 __mod_monitor_timer();
1252
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001253 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001254 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001255}
1256
1257static void l2cap_retrans_timeout(unsigned long arg)
1258{
1259 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001260
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001261 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001262 l2cap_pi(sk)->retry_count = 1;
1263 __mod_monitor_timer();
1264
1265 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1266
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001267 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001268 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001269}
1270
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271static void l2cap_drop_acked_frames(struct sock *sk)
1272{
1273 struct sk_buff *skb;
1274
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001275 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1276 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001277 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1278 break;
1279
1280 skb = skb_dequeue(TX_QUEUE(sk));
1281 kfree_skb(skb);
1282
1283 l2cap_pi(sk)->unacked_frames--;
1284 }
1285
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001286 if (!l2cap_pi(sk)->unacked_frames)
1287 del_timer(&l2cap_pi(sk)->retrans_timer);
1288
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001289 return;
1290}
1291
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001292static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001293{
1294 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295
1296 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1297
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001298 hci_send_acl(pi->conn->hcon, skb, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001299}
1300
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001301static int l2cap_streaming_send(struct sock *sk)
1302{
1303 struct sk_buff *skb, *tx_skb;
1304 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001305 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001306
1307 while ((skb = sk->sk_send_head)) {
1308 tx_skb = skb_clone(skb, GFP_ATOMIC);
1309
1310 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1311 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
1312 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1313
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001314 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001315 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1316 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1317 }
1318
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001319 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001320
1321 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1322
1323 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1324 sk->sk_send_head = NULL;
1325 else
1326 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
1327
1328 skb = skb_dequeue(TX_QUEUE(sk));
1329 kfree_skb(skb);
1330 }
1331 return 0;
1332}
1333
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001334static void l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001335{
1336 struct l2cap_pinfo *pi = l2cap_pi(sk);
1337 struct sk_buff *skb, *tx_skb;
1338 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001339
1340 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001341 if (!skb)
1342 return;
1343
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001344 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001345 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001346 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001347
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001348 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1349 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001350
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001351 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001352
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001353 if (pi->remote_max_tx &&
1354 bt_cb(skb)->retries == pi->remote_max_tx) {
1355 l2cap_send_disconn_req(pi->conn, sk);
1356 return;
1357 }
1358
1359 tx_skb = skb_clone(skb, GFP_ATOMIC);
1360 bt_cb(skb)->retries++;
1361 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1362 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1363 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1364 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1365
1366 if (pi->fcs == L2CAP_FCS_CRC16) {
1367 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1368 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1369 }
1370
1371 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001372}
1373
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001374static int l2cap_ertm_send(struct sock *sk)
1375{
1376 struct sk_buff *skb, *tx_skb;
1377 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001378 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001379 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001381 if (pi->conn_state & L2CAP_CONN_WAIT_F)
1382 return 0;
1383
Joe Perchesf64f9e72009-11-29 16:55:45 -08001384 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001385 !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001387 if (pi->remote_max_tx &&
1388 bt_cb(skb)->retries == pi->remote_max_tx) {
1389 l2cap_send_disconn_req(pi->conn, sk);
1390 break;
1391 }
1392
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001393 tx_skb = skb_clone(skb, GFP_ATOMIC);
1394
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001395 bt_cb(skb)->retries++;
1396
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001397 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001398 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1399 control |= L2CAP_CTRL_FINAL;
1400 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1401 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001402 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001403 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1404 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1405
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001406
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001407 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001408 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1409 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1410 }
1411
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001412 l2cap_do_send(sk, tx_skb);
1413
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001414 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001415
1416 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1417 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1418
1419 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001420 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001421
1422 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1423 sk->sk_send_head = NULL;
1424 else
1425 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001426
1427 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428 }
1429
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001430 return nsent;
1431}
1432
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001433static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001434{
1435 struct sock *sk = (struct sock *)pi;
1436 u16 control = 0;
1437
1438 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1439
1440 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1441 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001442 l2cap_send_sframe(pi, control);
1443 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001444 } else if (l2cap_ertm_send(sk) == 0) {
1445 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001446 l2cap_send_sframe(pi, control);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001447 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448}
1449
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001450static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001451{
1452 struct srej_list *tail;
1453 u16 control;
1454
1455 control = L2CAP_SUPER_SELECT_REJECT;
1456 control |= L2CAP_CTRL_FINAL;
1457
1458 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1459 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1460
1461 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001462}
1463
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001464static 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 -07001465{
1466 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001467 struct sk_buff **frag;
1468 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001470 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473 sent += count;
1474 len -= count;
1475
1476 /* Continuation fragments (no L2CAP header) */
1477 frag = &skb_shinfo(skb)->frag_list;
1478 while (len) {
1479 count = min_t(unsigned int, conn->mtu, len);
1480
1481 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1482 if (!*frag)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483 return -EFAULT;
1484 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1485 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
1487 sent += count;
1488 len -= count;
1489
1490 frag = &(*frag)->next;
1491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001494}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001496static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1497{
1498 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1499 struct sk_buff *skb;
1500 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1501 struct l2cap_hdr *lh;
1502
1503 BT_DBG("sk %p len %d", sk, (int)len);
1504
1505 count = min_t(unsigned int, (conn->mtu - hlen), len);
1506 skb = bt_skb_send_alloc(sk, count + hlen,
1507 msg->msg_flags & MSG_DONTWAIT, &err);
1508 if (!skb)
1509 return ERR_PTR(-ENOMEM);
1510
1511 /* Create L2CAP header */
1512 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1513 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1514 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1515 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1516
1517 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1518 if (unlikely(err < 0)) {
1519 kfree_skb(skb);
1520 return ERR_PTR(err);
1521 }
1522 return skb;
1523}
1524
1525static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1526{
1527 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1528 struct sk_buff *skb;
1529 int err, count, hlen = L2CAP_HDR_SIZE;
1530 struct l2cap_hdr *lh;
1531
1532 BT_DBG("sk %p len %d", sk, (int)len);
1533
1534 count = min_t(unsigned int, (conn->mtu - hlen), len);
1535 skb = bt_skb_send_alloc(sk, count + hlen,
1536 msg->msg_flags & MSG_DONTWAIT, &err);
1537 if (!skb)
1538 return ERR_PTR(-ENOMEM);
1539
1540 /* Create L2CAP header */
1541 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1542 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1543 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1544
1545 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1546 if (unlikely(err < 0)) {
1547 kfree_skb(skb);
1548 return ERR_PTR(err);
1549 }
1550 return skb;
1551}
1552
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001553static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554{
1555 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1556 struct sk_buff *skb;
1557 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1558 struct l2cap_hdr *lh;
1559
1560 BT_DBG("sk %p len %d", sk, (int)len);
1561
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001562 if (!conn)
1563 return ERR_PTR(-ENOTCONN);
1564
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001565 if (sdulen)
1566 hlen += 2;
1567
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001568 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1569 hlen += 2;
1570
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001571 count = min_t(unsigned int, (conn->mtu - hlen), len);
1572 skb = bt_skb_send_alloc(sk, count + hlen,
1573 msg->msg_flags & MSG_DONTWAIT, &err);
1574 if (!skb)
1575 return ERR_PTR(-ENOMEM);
1576
1577 /* Create L2CAP header */
1578 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1579 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1580 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1581 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001582 if (sdulen)
1583 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001584
1585 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1586 if (unlikely(err < 0)) {
1587 kfree_skb(skb);
1588 return ERR_PTR(err);
1589 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001590
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001591 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1592 put_unaligned_le16(0, skb_put(skb, 2));
1593
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001594 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596}
1597
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001598static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1599{
1600 struct l2cap_pinfo *pi = l2cap_pi(sk);
1601 struct sk_buff *skb;
1602 struct sk_buff_head sar_queue;
1603 u16 control;
1604 size_t size = 0;
1605
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001606 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001607 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001608 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001609 if (IS_ERR(skb))
1610 return PTR_ERR(skb);
1611
1612 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001613 len -= pi->remote_mps;
1614 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001615
1616 while (len > 0) {
1617 size_t buflen;
1618
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001619 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001620 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001621 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001622 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001623 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001624 buflen = len;
1625 }
1626
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001627 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001628 if (IS_ERR(skb)) {
1629 skb_queue_purge(&sar_queue);
1630 return PTR_ERR(skb);
1631 }
1632
1633 __skb_queue_tail(&sar_queue, skb);
1634 len -= buflen;
1635 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001636 }
1637 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1638 if (sk->sk_send_head == NULL)
1639 sk->sk_send_head = sar_queue.next;
1640
1641 return size;
1642}
1643
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
1645{
1646 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001647 struct l2cap_pinfo *pi = l2cap_pi(sk);
1648 struct sk_buff *skb;
1649 u16 control;
1650 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
1652 BT_DBG("sock %p, sk %p", sock, sk);
1653
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001654 err = sock_error(sk);
1655 if (err)
1656 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 if (msg->msg_flags & MSG_OOB)
1659 return -EOPNOTSUPP;
1660
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 lock_sock(sk);
1662
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001663 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001665 goto done;
1666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001668 /* Connectionless channel */
1669 if (sk->sk_type == SOCK_DGRAM) {
1670 skb = l2cap_create_connless_pdu(sk, msg, len);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001671 if (IS_ERR(skb)) {
Dan Carpenter477fffb2010-04-21 23:52:01 +00001672 err = PTR_ERR(skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001673 } else {
1674 l2cap_do_send(sk, skb);
1675 err = len;
1676 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001677 goto done;
1678 }
1679
1680 switch (pi->mode) {
1681 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001682 /* Check outgoing MTU */
1683 if (len > pi->omtu) {
1684 err = -EINVAL;
1685 goto done;
1686 }
1687
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001688 /* Create a basic PDU */
1689 skb = l2cap_create_basic_pdu(sk, msg, len);
1690 if (IS_ERR(skb)) {
1691 err = PTR_ERR(skb);
1692 goto done;
1693 }
1694
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001695 l2cap_do_send(sk, skb);
1696 err = len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001697 break;
1698
1699 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001700 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001701 /* Entire SDU fits into one PDU */
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001702 if (len <= pi->remote_mps) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001703 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001704 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001705 if (IS_ERR(skb)) {
1706 err = PTR_ERR(skb);
1707 goto done;
1708 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001709 __skb_queue_tail(TX_QUEUE(sk), skb);
1710 if (sk->sk_send_head == NULL)
1711 sk->sk_send_head = skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001712 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001713 /* Segment SDU into multiples PDUs */
1714 err = l2cap_sar_segment_sdu(sk, msg, len);
1715 if (err < 0)
1716 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001717 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001718
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001719 if (pi->mode == L2CAP_MODE_STREAMING)
1720 err = l2cap_streaming_send(sk);
1721 else
1722 err = l2cap_ertm_send(sk);
1723
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001724 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001725 err = len;
1726 break;
1727
1728 default:
1729 BT_DBG("bad state %1.1x", pi->mode);
1730 err = -EINVAL;
1731 }
1732
1733done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 release_sock(sk);
1735 return err;
1736}
1737
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001738static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1739{
1740 struct sock *sk = sock->sk;
1741
1742 lock_sock(sk);
1743
1744 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1745 struct l2cap_conn_rsp rsp;
1746
1747 sk->sk_state = BT_CONFIG;
1748
1749 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1750 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1751 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1752 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1753 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1754 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1755
1756 release_sock(sk);
1757 return 0;
1758 }
1759
1760 release_sock(sk);
1761
1762 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1763}
1764
David S. Millerb7058842009-09-30 16:12:20 -07001765static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766{
1767 struct sock *sk = sock->sk;
1768 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001769 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 u32 opt;
1771
1772 BT_DBG("sk %p", sk);
1773
1774 lock_sock(sk);
1775
1776 switch (optname) {
1777 case L2CAP_OPTIONS:
Marcel Holtmann0878b662007-05-05 00:35:59 +02001778 opts.imtu = l2cap_pi(sk)->imtu;
1779 opts.omtu = l2cap_pi(sk)->omtu;
1780 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001781 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001782 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001783 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001784 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001785
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 len = min_t(unsigned int, sizeof(opts), optlen);
1787 if (copy_from_user((char *) &opts, optval, len)) {
1788 err = -EFAULT;
1789 break;
1790 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001791
João Paulo Rechi Vita0041ecf2010-05-01 16:15:42 -03001792 l2cap_pi(sk)->mode = opts.mode;
1793 switch (l2cap_pi(sk)->mode) {
1794 case L2CAP_MODE_BASIC:
1795 break;
1796 case L2CAP_MODE_ERTM:
1797 case L2CAP_MODE_STREAMING:
1798 if (enable_ertm)
1799 break;
1800 /* fall through */
1801 default:
1802 err = -EINVAL;
1803 break;
1804 }
1805
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001806 l2cap_pi(sk)->imtu = opts.imtu;
1807 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001808 l2cap_pi(sk)->fcs = opts.fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001809 l2cap_pi(sk)->max_tx = opts.max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001810 l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 break;
1812
1813 case L2CAP_LM:
1814 if (get_user(opt, (u32 __user *) optval)) {
1815 err = -EFAULT;
1816 break;
1817 }
1818
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001819 if (opt & L2CAP_LM_AUTH)
1820 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
1821 if (opt & L2CAP_LM_ENCRYPT)
1822 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
1823 if (opt & L2CAP_LM_SECURE)
1824 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
1825
1826 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
1827 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 break;
1829
1830 default:
1831 err = -ENOPROTOOPT;
1832 break;
1833 }
1834
1835 release_sock(sk);
1836 return err;
1837}
1838
David S. Millerb7058842009-09-30 16:12:20 -07001839static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001840{
1841 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001842 struct bt_security sec;
1843 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001844 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001845
1846 BT_DBG("sk %p", sk);
1847
1848 if (level == SOL_L2CAP)
1849 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
1850
Marcel Holtmann0588d942009-01-16 10:06:13 +01001851 if (level != SOL_BLUETOOTH)
1852 return -ENOPROTOOPT;
1853
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001854 lock_sock(sk);
1855
1856 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001857 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001858 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
1859 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01001860 err = -EINVAL;
1861 break;
1862 }
1863
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001864 sec.level = BT_SECURITY_LOW;
1865
1866 len = min_t(unsigned int, sizeof(sec), optlen);
1867 if (copy_from_user((char *) &sec, optval, len)) {
1868 err = -EFAULT;
1869 break;
1870 }
1871
1872 if (sec.level < BT_SECURITY_LOW ||
1873 sec.level > BT_SECURITY_HIGH) {
1874 err = -EINVAL;
1875 break;
1876 }
1877
1878 l2cap_pi(sk)->sec_level = sec.level;
1879 break;
1880
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001881 case BT_DEFER_SETUP:
1882 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1883 err = -EINVAL;
1884 break;
1885 }
1886
1887 if (get_user(opt, (u32 __user *) optval)) {
1888 err = -EFAULT;
1889 break;
1890 }
1891
1892 bt_sk(sk)->defer_setup = opt;
1893 break;
1894
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001895 default:
1896 err = -ENOPROTOOPT;
1897 break;
1898 }
1899
1900 release_sock(sk);
1901 return err;
1902}
1903
1904static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905{
1906 struct sock *sk = sock->sk;
1907 struct l2cap_options opts;
1908 struct l2cap_conninfo cinfo;
1909 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001910 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
1912 BT_DBG("sk %p", sk);
1913
1914 if (get_user(len, optlen))
1915 return -EFAULT;
1916
1917 lock_sock(sk);
1918
1919 switch (optname) {
1920 case L2CAP_OPTIONS:
1921 opts.imtu = l2cap_pi(sk)->imtu;
1922 opts.omtu = l2cap_pi(sk)->omtu;
1923 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001924 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001925 opts.fcs = l2cap_pi(sk)->fcs;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001926 opts.max_tx = l2cap_pi(sk)->max_tx;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001927 opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
1929 len = min_t(unsigned int, len, sizeof(opts));
1930 if (copy_to_user(optval, (char *) &opts, len))
1931 err = -EFAULT;
1932
1933 break;
1934
1935 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001936 switch (l2cap_pi(sk)->sec_level) {
1937 case BT_SECURITY_LOW:
1938 opt = L2CAP_LM_AUTH;
1939 break;
1940 case BT_SECURITY_MEDIUM:
1941 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
1942 break;
1943 case BT_SECURITY_HIGH:
1944 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
1945 L2CAP_LM_SECURE;
1946 break;
1947 default:
1948 opt = 0;
1949 break;
1950 }
1951
1952 if (l2cap_pi(sk)->role_switch)
1953 opt |= L2CAP_LM_MASTER;
1954
1955 if (l2cap_pi(sk)->force_reliable)
1956 opt |= L2CAP_LM_RELIABLE;
1957
1958 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 err = -EFAULT;
1960 break;
1961
1962 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001963 if (sk->sk_state != BT_CONNECTED &&
1964 !(sk->sk_state == BT_CONNECT2 &&
1965 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 err = -ENOTCONN;
1967 break;
1968 }
1969
1970 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
1971 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
1972
1973 len = min_t(unsigned int, len, sizeof(cinfo));
1974 if (copy_to_user(optval, (char *) &cinfo, len))
1975 err = -EFAULT;
1976
1977 break;
1978
1979 default:
1980 err = -ENOPROTOOPT;
1981 break;
1982 }
1983
1984 release_sock(sk);
1985 return err;
1986}
1987
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001988static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
1989{
1990 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001991 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001992 int len, err = 0;
1993
1994 BT_DBG("sk %p", sk);
1995
1996 if (level == SOL_L2CAP)
1997 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
1998
Marcel Holtmann0588d942009-01-16 10:06:13 +01001999 if (level != SOL_BLUETOOTH)
2000 return -ENOPROTOOPT;
2001
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002002 if (get_user(len, optlen))
2003 return -EFAULT;
2004
2005 lock_sock(sk);
2006
2007 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002008 case BT_SECURITY:
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002009 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
2010 && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01002011 err = -EINVAL;
2012 break;
2013 }
2014
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002015 sec.level = l2cap_pi(sk)->sec_level;
2016
2017 len = min_t(unsigned int, len, sizeof(sec));
2018 if (copy_to_user(optval, (char *) &sec, len))
2019 err = -EFAULT;
2020
2021 break;
2022
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002023 case BT_DEFER_SETUP:
2024 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
2025 err = -EINVAL;
2026 break;
2027 }
2028
2029 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
2030 err = -EFAULT;
2031
2032 break;
2033
Marcel Holtmannd58daf42009-01-15 21:52:14 +01002034 default:
2035 err = -ENOPROTOOPT;
2036 break;
2037 }
2038
2039 release_sock(sk);
2040 return err;
2041}
2042
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043static int l2cap_sock_shutdown(struct socket *sock, int how)
2044{
2045 struct sock *sk = sock->sk;
2046 int err = 0;
2047
2048 BT_DBG("sock %p, sk %p", sock, sk);
2049
2050 if (!sk)
2051 return 0;
2052
2053 lock_sock(sk);
2054 if (!sk->sk_shutdown) {
2055 sk->sk_shutdown = SHUTDOWN_MASK;
2056 l2cap_sock_clear_timer(sk);
2057 __l2cap_sock_close(sk, 0);
2058
2059 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002060 err = bt_sock_wait_state(sk, BT_CLOSED,
2061 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 }
2063 release_sock(sk);
2064 return err;
2065}
2066
2067static int l2cap_sock_release(struct socket *sock)
2068{
2069 struct sock *sk = sock->sk;
2070 int err;
2071
2072 BT_DBG("sock %p, sk %p", sock, sk);
2073
2074 if (!sk)
2075 return 0;
2076
2077 err = l2cap_sock_shutdown(sock, 2);
2078
2079 sock_orphan(sk);
2080 l2cap_sock_kill(sk);
2081 return err;
2082}
2083
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084static void l2cap_chan_ready(struct sock *sk)
2085{
2086 struct sock *parent = bt_sk(sk)->parent;
2087
2088 BT_DBG("sk %p, parent %p", sk, parent);
2089
2090 l2cap_pi(sk)->conf_state = 0;
2091 l2cap_sock_clear_timer(sk);
2092
2093 if (!parent) {
2094 /* Outgoing channel.
2095 * Wake up socket sleeping on connect.
2096 */
2097 sk->sk_state = BT_CONNECTED;
2098 sk->sk_state_change(sk);
2099 } else {
2100 /* Incoming channel.
2101 * Wake up socket sleeping on accept.
2102 */
2103 parent->sk_data_ready(parent, 0);
2104 }
2105}
2106
2107/* Copy frame to all raw sockets on that connection */
2108static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2109{
2110 struct l2cap_chan_list *l = &conn->chan_list;
2111 struct sk_buff *nskb;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002112 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113
2114 BT_DBG("conn %p", conn);
2115
2116 read_lock(&l->lock);
2117 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2118 if (sk->sk_type != SOCK_RAW)
2119 continue;
2120
2121 /* Don't send frame to the socket it came from */
2122 if (skb->sk == sk)
2123 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002124 nskb = skb_clone(skb, GFP_ATOMIC);
2125 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 continue;
2127
2128 if (sock_queue_rcv_skb(sk, nskb))
2129 kfree_skb(nskb);
2130 }
2131 read_unlock(&l->lock);
2132}
2133
2134/* ---- L2CAP signalling commands ---- */
2135static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2136 u8 code, u8 ident, u16 dlen, void *data)
2137{
2138 struct sk_buff *skb, **frag;
2139 struct l2cap_cmd_hdr *cmd;
2140 struct l2cap_hdr *lh;
2141 int len, count;
2142
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002143 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2144 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
2146 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2147 count = min_t(unsigned int, conn->mtu, len);
2148
2149 skb = bt_skb_alloc(count, GFP_ATOMIC);
2150 if (!skb)
2151 return NULL;
2152
2153 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002154 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002155 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
2157 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2158 cmd->code = code;
2159 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002160 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
2162 if (dlen) {
2163 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2164 memcpy(skb_put(skb, count), data, count);
2165 data += count;
2166 }
2167
2168 len -= skb->len;
2169
2170 /* Continuation fragments (no L2CAP header) */
2171 frag = &skb_shinfo(skb)->frag_list;
2172 while (len) {
2173 count = min_t(unsigned int, conn->mtu, len);
2174
2175 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2176 if (!*frag)
2177 goto fail;
2178
2179 memcpy(skb_put(*frag, count), data, count);
2180
2181 len -= count;
2182 data += count;
2183
2184 frag = &(*frag)->next;
2185 }
2186
2187 return skb;
2188
2189fail:
2190 kfree_skb(skb);
2191 return NULL;
2192}
2193
2194static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2195{
2196 struct l2cap_conf_opt *opt = *ptr;
2197 int len;
2198
2199 len = L2CAP_CONF_OPT_SIZE + opt->len;
2200 *ptr += len;
2201
2202 *type = opt->type;
2203 *olen = opt->len;
2204
2205 switch (opt->len) {
2206 case 1:
2207 *val = *((u8 *) opt->val);
2208 break;
2209
2210 case 2:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002211 *val = __le16_to_cpu(*((__le16 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 break;
2213
2214 case 4:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002215 *val = __le32_to_cpu(*((__le32 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 break;
2217
2218 default:
2219 *val = (unsigned long) opt->val;
2220 break;
2221 }
2222
2223 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2224 return len;
2225}
2226
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2228{
2229 struct l2cap_conf_opt *opt = *ptr;
2230
2231 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2232
2233 opt->type = type;
2234 opt->len = len;
2235
2236 switch (len) {
2237 case 1:
2238 *((u8 *) opt->val) = val;
2239 break;
2240
2241 case 2:
Al Viro8e036fc2007-07-29 00:16:36 -07002242 *((__le16 *) opt->val) = cpu_to_le16(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 break;
2244
2245 case 4:
Al Viro8e036fc2007-07-29 00:16:36 -07002246 *((__le32 *) opt->val) = cpu_to_le32(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 break;
2248
2249 default:
2250 memcpy(opt->val, (void *) val, len);
2251 break;
2252 }
2253
2254 *ptr += L2CAP_CONF_OPT_SIZE + len;
2255}
2256
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002257static void l2cap_ack_timeout(unsigned long arg)
2258{
2259 struct sock *sk = (void *) arg;
2260
2261 bh_lock_sock(sk);
2262 l2cap_send_ack(l2cap_pi(sk));
2263 bh_unlock_sock(sk);
2264}
2265
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002266static inline void l2cap_ertm_init(struct sock *sk)
2267{
2268 l2cap_pi(sk)->expected_ack_seq = 0;
2269 l2cap_pi(sk)->unacked_frames = 0;
2270 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002271 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002272 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002273
2274 setup_timer(&l2cap_pi(sk)->retrans_timer,
2275 l2cap_retrans_timeout, (unsigned long) sk);
2276 setup_timer(&l2cap_pi(sk)->monitor_timer,
2277 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002278 setup_timer(&l2cap_pi(sk)->ack_timer,
2279 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002280
2281 __skb_queue_head_init(SREJ_QUEUE(sk));
2282}
2283
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002284static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
2285{
2286 u32 local_feat_mask = l2cap_feat_mask;
2287 if (enable_ertm)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03002288 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002289
2290 switch (mode) {
2291 case L2CAP_MODE_ERTM:
2292 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
2293 case L2CAP_MODE_STREAMING:
2294 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
2295 default:
2296 return 0x00;
2297 }
2298}
2299
2300static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2301{
2302 switch (mode) {
2303 case L2CAP_MODE_STREAMING:
2304 case L2CAP_MODE_ERTM:
2305 if (l2cap_mode_supported(mode, remote_feat_mask))
2306 return mode;
2307 /* fall through */
2308 default:
2309 return L2CAP_MODE_BASIC;
2310 }
2311}
2312
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313static int l2cap_build_conf_req(struct sock *sk, void *data)
2314{
2315 struct l2cap_pinfo *pi = l2cap_pi(sk);
2316 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03002317 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 void *ptr = req->data;
2319
2320 BT_DBG("sk %p", sk);
2321
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002322 if (pi->num_conf_req || pi->num_conf_rsp)
2323 goto done;
2324
2325 switch (pi->mode) {
2326 case L2CAP_MODE_STREAMING:
2327 case L2CAP_MODE_ERTM:
2328 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002329 if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
2330 l2cap_send_disconn_req(pi->conn, sk);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002331 break;
2332 default:
2333 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2334 break;
2335 }
2336
2337done:
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002338 switch (pi->mode) {
2339 case L2CAP_MODE_BASIC:
2340 if (pi->imtu != L2CAP_DEFAULT_MTU)
2341 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
2342 break;
2343
2344 case L2CAP_MODE_ERTM:
2345 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03002346 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03002347 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002348 rfc.retrans_timeout = 0;
2349 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002350 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002351 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002352 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002353
2354 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2355 sizeof(rfc), (unsigned long) &rfc);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002356
2357 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2358 break;
2359
2360 if (pi->fcs == L2CAP_FCS_NONE ||
2361 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2362 pi->fcs = L2CAP_FCS_NONE;
2363 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2364 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002365 break;
2366
2367 case L2CAP_MODE_STREAMING:
2368 rfc.mode = L2CAP_MODE_STREAMING;
2369 rfc.txwin_size = 0;
2370 rfc.max_transmit = 0;
2371 rfc.retrans_timeout = 0;
2372 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002373 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002374 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002375 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002376
2377 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2378 sizeof(rfc), (unsigned long) &rfc);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002379
2380 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2381 break;
2382
2383 if (pi->fcs == L2CAP_FCS_NONE ||
2384 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2385 pi->fcs = L2CAP_FCS_NONE;
2386 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2387 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002388 break;
2389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
2391 /* FIXME: Need actual value of the flush timeout */
2392 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2393 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2394
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002395 req->dcid = cpu_to_le16(pi->dcid);
2396 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
2398 return ptr - data;
2399}
2400
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002401static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402{
2403 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002404 struct l2cap_conf_rsp *rsp = data;
2405 void *ptr = rsp->data;
2406 void *req = pi->conf_req;
2407 int len = pi->conf_len;
2408 int type, hint, olen;
2409 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002410 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002411 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002412 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002414 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002415
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002416 while (len >= L2CAP_CONF_OPT_SIZE) {
2417 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002419 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002420 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002421
2422 switch (type) {
2423 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002424 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002425 break;
2426
2427 case L2CAP_CONF_FLUSH_TO:
2428 pi->flush_to = val;
2429 break;
2430
2431 case L2CAP_CONF_QOS:
2432 break;
2433
Marcel Holtmann6464f352007-10-20 13:39:51 +02002434 case L2CAP_CONF_RFC:
2435 if (olen == sizeof(rfc))
2436 memcpy(&rfc, (void *) val, olen);
2437 break;
2438
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002439 case L2CAP_CONF_FCS:
2440 if (val == L2CAP_FCS_NONE)
2441 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2442
2443 break;
2444
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002445 default:
2446 if (hint)
2447 break;
2448
2449 result = L2CAP_CONF_UNKNOWN;
2450 *((u8 *) ptr++) = type;
2451 break;
2452 }
2453 }
2454
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002455 if (pi->num_conf_rsp || pi->num_conf_req)
2456 goto done;
2457
2458 switch (pi->mode) {
2459 case L2CAP_MODE_STREAMING:
2460 case L2CAP_MODE_ERTM:
2461 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
2462 if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
2463 return -ECONNREFUSED;
2464 break;
2465 default:
2466 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2467 break;
2468 }
2469
2470done:
2471 if (pi->mode != rfc.mode) {
2472 result = L2CAP_CONF_UNACCEPT;
2473 rfc.mode = pi->mode;
2474
2475 if (pi->num_conf_rsp == 1)
2476 return -ECONNREFUSED;
2477
2478 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2479 sizeof(rfc), (unsigned long) &rfc);
2480 }
2481
2482
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002483 if (result == L2CAP_CONF_SUCCESS) {
2484 /* Configure output options and let the other side know
2485 * which ones we don't like. */
2486
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002487 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2488 result = L2CAP_CONF_UNACCEPT;
2489 else {
2490 pi->omtu = mtu;
2491 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2492 }
2493 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002494
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002495 switch (rfc.mode) {
2496 case L2CAP_MODE_BASIC:
2497 pi->fcs = L2CAP_FCS_NONE;
2498 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2499 break;
2500
2501 case L2CAP_MODE_ERTM:
2502 pi->remote_tx_win = rfc.txwin_size;
2503 pi->remote_max_tx = rfc.max_transmit;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002504 if (rfc.max_pdu_size > pi->conn->mtu - 10)
2505 rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
2506
2507 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002508
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002509 rfc.retrans_timeout =
2510 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2511 rfc.monitor_timeout =
2512 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002513
2514 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002515
2516 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2517 sizeof(rfc), (unsigned long) &rfc);
2518
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002519 break;
2520
2521 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002522 if (rfc.max_pdu_size > pi->conn->mtu - 10)
2523 rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
2524
2525 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002526
2527 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002528
2529 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2530 sizeof(rfc), (unsigned long) &rfc);
2531
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002532 break;
2533
2534 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002535 result = L2CAP_CONF_UNACCEPT;
2536
2537 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002538 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002539 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002540
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002541 if (result == L2CAP_CONF_SUCCESS)
2542 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2543 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002544 rsp->scid = cpu_to_le16(pi->dcid);
2545 rsp->result = cpu_to_le16(result);
2546 rsp->flags = cpu_to_le16(0x0000);
2547
2548 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549}
2550
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002551static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2552{
2553 struct l2cap_pinfo *pi = l2cap_pi(sk);
2554 struct l2cap_conf_req *req = data;
2555 void *ptr = req->data;
2556 int type, olen;
2557 unsigned long val;
2558 struct l2cap_conf_rfc rfc;
2559
2560 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2561
2562 while (len >= L2CAP_CONF_OPT_SIZE) {
2563 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2564
2565 switch (type) {
2566 case L2CAP_CONF_MTU:
2567 if (val < L2CAP_DEFAULT_MIN_MTU) {
2568 *result = L2CAP_CONF_UNACCEPT;
2569 pi->omtu = L2CAP_DEFAULT_MIN_MTU;
2570 } else
2571 pi->omtu = val;
2572 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
2573 break;
2574
2575 case L2CAP_CONF_FLUSH_TO:
2576 pi->flush_to = val;
2577 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2578 2, pi->flush_to);
2579 break;
2580
2581 case L2CAP_CONF_RFC:
2582 if (olen == sizeof(rfc))
2583 memcpy(&rfc, (void *)val, olen);
2584
2585 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2586 rfc.mode != pi->mode)
2587 return -ECONNREFUSED;
2588
2589 pi->mode = rfc.mode;
2590 pi->fcs = 0;
2591
2592 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2593 sizeof(rfc), (unsigned long) &rfc);
2594 break;
2595 }
2596 }
2597
2598 if (*result == L2CAP_CONF_SUCCESS) {
2599 switch (rfc.mode) {
2600 case L2CAP_MODE_ERTM:
2601 pi->remote_tx_win = rfc.txwin_size;
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002602 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2603 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002604 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002605 break;
2606 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002607 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002608 }
2609 }
2610
2611 req->dcid = cpu_to_le16(pi->dcid);
2612 req->flags = cpu_to_le16(0x0000);
2613
2614 return ptr - data;
2615}
2616
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002617static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
2619 struct l2cap_conf_rsp *rsp = data;
2620 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002622 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002624 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002625 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002626 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
2628 return ptr - data;
2629}
2630
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002631static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
2632{
2633 struct l2cap_pinfo *pi = l2cap_pi(sk);
2634 int type, olen;
2635 unsigned long val;
2636 struct l2cap_conf_rfc rfc;
2637
2638 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
2639
2640 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
2641 return;
2642
2643 while (len >= L2CAP_CONF_OPT_SIZE) {
2644 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2645
2646 switch (type) {
2647 case L2CAP_CONF_RFC:
2648 if (olen == sizeof(rfc))
2649 memcpy(&rfc, (void *)val, olen);
2650 goto done;
2651 }
2652 }
2653
2654done:
2655 switch (rfc.mode) {
2656 case L2CAP_MODE_ERTM:
2657 pi->remote_tx_win = rfc.txwin_size;
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002658 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2659 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002660 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2661 break;
2662 case L2CAP_MODE_STREAMING:
2663 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2664 }
2665}
2666
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002667static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2668{
2669 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2670
2671 if (rej->reason != 0x0000)
2672 return 0;
2673
2674 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2675 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002676 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002677
2678 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002679 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002680
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002681 l2cap_conn_start(conn);
2682 }
2683
2684 return 0;
2685}
2686
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2688{
2689 struct l2cap_chan_list *list = &conn->chan_list;
2690 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2691 struct l2cap_conn_rsp rsp;
2692 struct sock *sk, *parent;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002693 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694
2695 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002696 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697
2698 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2699
2700 /* Check if we have socket listening on psm */
2701 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2702 if (!parent) {
2703 result = L2CAP_CR_BAD_PSM;
2704 goto sendresp;
2705 }
2706
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002707 /* Check if the ACL is secure enough (if not SDP) */
2708 if (psm != cpu_to_le16(0x0001) &&
2709 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002710 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002711 result = L2CAP_CR_SEC_BLOCK;
2712 goto response;
2713 }
2714
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 result = L2CAP_CR_NO_MEM;
2716
2717 /* Check for backlog size */
2718 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002719 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 goto response;
2721 }
2722
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002723 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 if (!sk)
2725 goto response;
2726
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002727 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
2729 /* Check if we already have channel with that dcid */
2730 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002731 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 sock_set_flag(sk, SOCK_ZAPPED);
2733 l2cap_sock_kill(sk);
2734 goto response;
2735 }
2736
2737 hci_conn_hold(conn->hcon);
2738
2739 l2cap_sock_init(sk, parent);
2740 bacpy(&bt_sk(sk)->src, conn->src);
2741 bacpy(&bt_sk(sk)->dst, conn->dst);
2742 l2cap_pi(sk)->psm = psm;
2743 l2cap_pi(sk)->dcid = scid;
2744
2745 __l2cap_chan_add(conn, sk, parent);
2746 dcid = l2cap_pi(sk)->scid;
2747
2748 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2749
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 l2cap_pi(sk)->ident = cmd->ident;
2751
Marcel Holtmann984947d2009-02-06 23:35:19 +01002752 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002753 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002754 if (bt_sk(sk)->defer_setup) {
2755 sk->sk_state = BT_CONNECT2;
2756 result = L2CAP_CR_PEND;
2757 status = L2CAP_CS_AUTHOR_PEND;
2758 parent->sk_data_ready(parent, 0);
2759 } else {
2760 sk->sk_state = BT_CONFIG;
2761 result = L2CAP_CR_SUCCESS;
2762 status = L2CAP_CS_NO_INFO;
2763 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002764 } else {
2765 sk->sk_state = BT_CONNECT2;
2766 result = L2CAP_CR_PEND;
2767 status = L2CAP_CS_AUTHEN_PEND;
2768 }
2769 } else {
2770 sk->sk_state = BT_CONNECT2;
2771 result = L2CAP_CR_PEND;
2772 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 }
2774
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002775 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
2777response:
2778 bh_unlock_sock(parent);
2779
2780sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002781 rsp.scid = cpu_to_le16(scid);
2782 rsp.dcid = cpu_to_le16(dcid);
2783 rsp.result = cpu_to_le16(result);
2784 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002786
2787 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2788 struct l2cap_info_req info;
2789 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2790
2791 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2792 conn->info_ident = l2cap_get_ident(conn);
2793
2794 mod_timer(&conn->info_timer, jiffies +
2795 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2796
2797 l2cap_send_cmd(conn, conn->info_ident,
2798 L2CAP_INFO_REQ, sizeof(info), &info);
2799 }
2800
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 return 0;
2802}
2803
2804static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2805{
2806 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2807 u16 scid, dcid, result, status;
2808 struct sock *sk;
2809 u8 req[128];
2810
2811 scid = __le16_to_cpu(rsp->scid);
2812 dcid = __le16_to_cpu(rsp->dcid);
2813 result = __le16_to_cpu(rsp->result);
2814 status = __le16_to_cpu(rsp->status);
2815
2816 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2817
2818 if (scid) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002819 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2820 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return 0;
2822 } else {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002823 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2824 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 return 0;
2826 }
2827
2828 switch (result) {
2829 case L2CAP_CR_SUCCESS:
2830 sk->sk_state = BT_CONFIG;
2831 l2cap_pi(sk)->ident = 0;
2832 l2cap_pi(sk)->dcid = dcid;
2833 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2834
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002835 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2836
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2838 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002839 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 break;
2841
2842 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002843 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 break;
2845
2846 default:
2847 l2cap_chan_del(sk, ECONNREFUSED);
2848 break;
2849 }
2850
2851 bh_unlock_sock(sk);
2852 return 0;
2853}
2854
Al Viro88219a02007-07-29 00:17:25 -07002855static 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 -07002856{
2857 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2858 u16 dcid, flags;
2859 u8 rsp[64];
2860 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002861 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
2863 dcid = __le16_to_cpu(req->dcid);
2864 flags = __le16_to_cpu(req->flags);
2865
2866 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2867
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002868 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2869 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 return -ENOENT;
2871
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002872 if (sk->sk_state == BT_DISCONN)
2873 goto unlock;
2874
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002875 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002876 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002877 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2878 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2879 l2cap_build_conf_rsp(sk, rsp,
2880 L2CAP_CONF_REJECT, flags), rsp);
2881 goto unlock;
2882 }
2883
2884 /* Store config. */
2885 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2886 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
2888 if (flags & 0x0001) {
2889 /* Incomplete config. Send empty response. */
2890 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002891 l2cap_build_conf_rsp(sk, rsp,
2892 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 goto unlock;
2894 }
2895
2896 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002897 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002898 if (len < 0) {
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002899 l2cap_send_disconn_req(conn, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002903 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002904 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002905
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002906 /* Reset config buffer. */
2907 l2cap_pi(sk)->conf_len = 0;
2908
Marcel Holtmann876d9482007-10-20 13:35:42 +02002909 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2910 goto unlock;
2911
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Joe Perchesf64f9e72009-11-29 16:55:45 -08002913 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
2914 l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002915 l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
2916
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002918
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002919 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002920 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002921 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002922 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2923 l2cap_ertm_init(sk);
2924
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002926 goto unlock;
2927 }
2928
2929 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002930 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002932 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002933 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 }
2935
2936unlock:
2937 bh_unlock_sock(sk);
2938 return 0;
2939}
2940
2941static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2942{
2943 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2944 u16 scid, flags, result;
2945 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002946 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947
2948 scid = __le16_to_cpu(rsp->scid);
2949 flags = __le16_to_cpu(rsp->flags);
2950 result = __le16_to_cpu(rsp->result);
2951
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002952 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2953 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002955 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2956 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 return 0;
2958
2959 switch (result) {
2960 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002961 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 break;
2963
2964 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002965 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002966 char req[64];
2967
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002968 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
2969 l2cap_send_disconn_req(conn, sk);
2970 goto done;
2971 }
2972
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002973 /* throw out any old stored conf requests */
2974 result = L2CAP_CONF_SUCCESS;
2975 len = l2cap_parse_conf_rsp(sk, rsp->data,
2976 len, req, &result);
2977 if (len < 0) {
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002978 l2cap_send_disconn_req(conn, sk);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002979 goto done;
2980 }
2981
2982 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2983 L2CAP_CONF_REQ, len, req);
2984 l2cap_pi(sk)->num_conf_req++;
2985 if (result != L2CAP_CONF_SUCCESS)
2986 goto done;
2987 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 }
2989
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002990 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 sk->sk_state = BT_DISCONN;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002992 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002994 l2cap_send_disconn_req(conn, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 goto done;
2996 }
2997
2998 if (flags & 0x01)
2999 goto done;
3000
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
3002
3003 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Joe Perchesf64f9e72009-11-29 16:55:45 -08003004 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
3005 l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003006 l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
3007
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003009 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003010 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003011 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003012 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
3013 l2cap_ertm_init(sk);
3014
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 l2cap_chan_ready(sk);
3016 }
3017
3018done:
3019 bh_unlock_sock(sk);
3020 return 0;
3021}
3022
3023static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3024{
3025 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3026 struct l2cap_disconn_rsp rsp;
3027 u16 dcid, scid;
3028 struct sock *sk;
3029
3030 scid = __le16_to_cpu(req->scid);
3031 dcid = __le16_to_cpu(req->dcid);
3032
3033 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3034
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003035 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
3036 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 return 0;
3038
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003039 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3040 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3042
3043 sk->sk_shutdown = SHUTDOWN_MASK;
3044
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003045 skb_queue_purge(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003046
3047 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
3048 skb_queue_purge(SREJ_QUEUE(sk));
3049 del_timer(&l2cap_pi(sk)->retrans_timer);
3050 del_timer(&l2cap_pi(sk)->monitor_timer);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003051 del_timer(&l2cap_pi(sk)->ack_timer);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003052 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003053
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 l2cap_chan_del(sk, ECONNRESET);
3055 bh_unlock_sock(sk);
3056
3057 l2cap_sock_kill(sk);
3058 return 0;
3059}
3060
3061static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3062{
3063 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3064 u16 dcid, scid;
3065 struct sock *sk;
3066
3067 scid = __le16_to_cpu(rsp->scid);
3068 dcid = __le16_to_cpu(rsp->dcid);
3069
3070 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3071
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003072 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
3073 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 return 0;
3075
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003076 skb_queue_purge(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003077
3078 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
3079 skb_queue_purge(SREJ_QUEUE(sk));
3080 del_timer(&l2cap_pi(sk)->retrans_timer);
3081 del_timer(&l2cap_pi(sk)->monitor_timer);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003082 del_timer(&l2cap_pi(sk)->ack_timer);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003083 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003084
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 l2cap_chan_del(sk, 0);
3086 bh_unlock_sock(sk);
3087
3088 l2cap_sock_kill(sk);
3089 return 0;
3090}
3091
3092static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3093{
3094 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 u16 type;
3096
3097 type = __le16_to_cpu(req->type);
3098
3099 BT_DBG("type 0x%4.4x", type);
3100
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003101 if (type == L2CAP_IT_FEAT_MASK) {
3102 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003103 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003104 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3105 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3106 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003107 if (enable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003108 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3109 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003110 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003111 l2cap_send_cmd(conn, cmd->ident,
3112 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003113 } else if (type == L2CAP_IT_FIXED_CHAN) {
3114 u8 buf[12];
3115 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3116 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3117 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3118 memcpy(buf + 4, l2cap_fixed_chan, 8);
3119 l2cap_send_cmd(conn, cmd->ident,
3120 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003121 } else {
3122 struct l2cap_info_rsp rsp;
3123 rsp.type = cpu_to_le16(type);
3124 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3125 l2cap_send_cmd(conn, cmd->ident,
3126 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
3129 return 0;
3130}
3131
3132static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3133{
3134 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3135 u16 type, result;
3136
3137 type = __le16_to_cpu(rsp->type);
3138 result = __le16_to_cpu(rsp->result);
3139
3140 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3141
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003142 del_timer(&conn->info_timer);
3143
Marcel Holtmann984947d2009-02-06 23:35:19 +01003144 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003145 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003146
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003147 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003148 struct l2cap_info_req req;
3149 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3150
3151 conn->info_ident = l2cap_get_ident(conn);
3152
3153 l2cap_send_cmd(conn, conn->info_ident,
3154 L2CAP_INFO_REQ, sizeof(req), &req);
3155 } else {
3156 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3157 conn->info_ident = 0;
3158
3159 l2cap_conn_start(conn);
3160 }
3161 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003162 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003163 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003164
3165 l2cap_conn_start(conn);
3166 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003167
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 return 0;
3169}
3170
3171static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3172{
3173 u8 *data = skb->data;
3174 int len = skb->len;
3175 struct l2cap_cmd_hdr cmd;
3176 int err = 0;
3177
3178 l2cap_raw_recv(conn, skb);
3179
3180 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003181 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3183 data += L2CAP_CMD_HDR_SIZE;
3184 len -= L2CAP_CMD_HDR_SIZE;
3185
Al Viro88219a02007-07-29 00:17:25 -07003186 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Al Viro88219a02007-07-29 00:17:25 -07003188 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 -07003189
Al Viro88219a02007-07-29 00:17:25 -07003190 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 BT_DBG("corrupted command");
3192 break;
3193 }
3194
3195 switch (cmd.code) {
3196 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003197 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 break;
3199
3200 case L2CAP_CONN_REQ:
3201 err = l2cap_connect_req(conn, &cmd, data);
3202 break;
3203
3204 case L2CAP_CONN_RSP:
3205 err = l2cap_connect_rsp(conn, &cmd, data);
3206 break;
3207
3208 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003209 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 break;
3211
3212 case L2CAP_CONF_RSP:
3213 err = l2cap_config_rsp(conn, &cmd, data);
3214 break;
3215
3216 case L2CAP_DISCONN_REQ:
3217 err = l2cap_disconnect_req(conn, &cmd, data);
3218 break;
3219
3220 case L2CAP_DISCONN_RSP:
3221 err = l2cap_disconnect_rsp(conn, &cmd, data);
3222 break;
3223
3224 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003225 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 break;
3227
3228 case L2CAP_ECHO_RSP:
3229 break;
3230
3231 case L2CAP_INFO_REQ:
3232 err = l2cap_information_req(conn, &cmd, data);
3233 break;
3234
3235 case L2CAP_INFO_RSP:
3236 err = l2cap_information_rsp(conn, &cmd, data);
3237 break;
3238
3239 default:
3240 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3241 err = -EINVAL;
3242 break;
3243 }
3244
3245 if (err) {
3246 struct l2cap_cmd_rej rej;
3247 BT_DBG("error %d", err);
3248
3249 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003250 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3252 }
3253
Al Viro88219a02007-07-29 00:17:25 -07003254 data += cmd_len;
3255 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 }
3257
3258 kfree_skb(skb);
3259}
3260
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003261static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3262{
3263 u16 our_fcs, rcv_fcs;
3264 int hdr_size = L2CAP_HDR_SIZE + 2;
3265
3266 if (pi->fcs == L2CAP_FCS_CRC16) {
3267 skb_trim(skb, skb->len - 2);
3268 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3269 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3270
3271 if (our_fcs != rcv_fcs)
3272 return -EINVAL;
3273 }
3274 return 0;
3275}
3276
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003277static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3278{
3279 struct l2cap_pinfo *pi = l2cap_pi(sk);
3280 u16 control = 0;
3281
3282 pi->frames_sent = 0;
3283 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3284
3285 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3286
3287 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3288 control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
3289 l2cap_send_sframe(pi, control);
3290 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
3291 }
3292
3293 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
3294 __mod_retrans_timer();
3295
3296 l2cap_ertm_send(sk);
3297
3298 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3299 pi->frames_sent == 0) {
3300 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003301 l2cap_send_sframe(pi, control);
3302 }
3303}
3304
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003305static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003306{
3307 struct sk_buff *next_skb;
3308
3309 bt_cb(skb)->tx_seq = tx_seq;
3310 bt_cb(skb)->sar = sar;
3311
3312 next_skb = skb_peek(SREJ_QUEUE(sk));
3313 if (!next_skb) {
3314 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003315 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003316 }
3317
3318 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003319 if (bt_cb(next_skb)->tx_seq == tx_seq)
3320 return -EINVAL;
3321
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003322 if (bt_cb(next_skb)->tx_seq > tx_seq) {
3323 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003324 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003325 }
3326
3327 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3328 break;
3329
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003330 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003331
3332 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003333
3334 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335}
3336
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003337static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3338{
3339 struct l2cap_pinfo *pi = l2cap_pi(sk);
3340 struct sk_buff *_skb;
3341 int err = 0;
3342
3343 switch (control & L2CAP_CTRL_SAR) {
3344 case L2CAP_SDU_UNSEGMENTED:
3345 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3346 goto drop;
3347
3348 err = sock_queue_rcv_skb(sk, skb);
3349 if (!err)
3350 return err;
3351
3352 break;
3353
3354 case L2CAP_SDU_START:
3355 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
3356 goto drop;
3357
3358 pi->sdu_len = get_unaligned_le16(skb->data);
3359 skb_pull(skb, 2);
3360
3361 if (pi->sdu_len > pi->imtu)
3362 goto disconnect;
3363
3364 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3365 if (!pi->sdu) {
3366 err = -ENOMEM;
3367 break;
3368 }
3369
3370 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3371
3372 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3373 pi->partial_sdu_len = skb->len;
3374 break;
3375
3376 case L2CAP_SDU_CONTINUE:
3377 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3378 goto disconnect;
3379
3380 if (!pi->sdu)
3381 goto disconnect;
3382
3383 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3384
3385 pi->partial_sdu_len += skb->len;
3386 if (pi->partial_sdu_len > pi->sdu_len)
3387 goto drop;
3388
3389 break;
3390
3391 case L2CAP_SDU_END:
3392 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3393 goto disconnect;
3394
3395 if (!pi->sdu)
3396 goto disconnect;
3397
3398 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3399
3400 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3401 pi->partial_sdu_len += skb->len;
3402
3403 if (pi->partial_sdu_len > pi->imtu)
3404 goto drop;
3405
3406 if (pi->partial_sdu_len != pi->sdu_len)
3407 goto drop;
3408
3409 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3410 err = sock_queue_rcv_skb(sk, _skb);
3411 if (err < 0)
3412 kfree_skb(_skb);
3413
3414 kfree_skb(pi->sdu);
3415 break;
3416 }
3417
3418 kfree_skb(skb);
3419 return err;
3420
3421drop:
3422 kfree_skb(pi->sdu);
3423 pi->sdu = NULL;
3424
3425disconnect:
3426 l2cap_send_disconn_req(pi->conn, sk);
3427 kfree_skb(skb);
3428 return 0;
3429}
3430
3431static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003432{
3433 struct l2cap_pinfo *pi = l2cap_pi(sk);
3434 struct sk_buff *_skb;
3435 int err = -EINVAL;
3436
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003437 /*
3438 * TODO: We have to notify the userland if some data is lost with the
3439 * Streaming Mode.
3440 */
3441
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003442 switch (control & L2CAP_CTRL_SAR) {
3443 case L2CAP_SDU_UNSEGMENTED:
3444 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3445 kfree_skb(pi->sdu);
3446 break;
3447 }
3448
3449 err = sock_queue_rcv_skb(sk, skb);
3450 if (!err)
3451 return 0;
3452
3453 break;
3454
3455 case L2CAP_SDU_START:
3456 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3457 kfree_skb(pi->sdu);
3458 break;
3459 }
3460
3461 pi->sdu_len = get_unaligned_le16(skb->data);
3462 skb_pull(skb, 2);
3463
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003464 if (pi->sdu_len > pi->imtu) {
3465 err = -EMSGSIZE;
3466 break;
3467 }
3468
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003469 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3470 if (!pi->sdu) {
3471 err = -ENOMEM;
3472 break;
3473 }
3474
3475 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3476
3477 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3478 pi->partial_sdu_len = skb->len;
3479 err = 0;
3480 break;
3481
3482 case L2CAP_SDU_CONTINUE:
3483 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3484 break;
3485
3486 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3487
3488 pi->partial_sdu_len += skb->len;
3489 if (pi->partial_sdu_len > pi->sdu_len)
3490 kfree_skb(pi->sdu);
3491 else
3492 err = 0;
3493
3494 break;
3495
3496 case L2CAP_SDU_END:
3497 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3498 break;
3499
3500 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3501
3502 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3503 pi->partial_sdu_len += skb->len;
3504
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003505 if (pi->partial_sdu_len > pi->imtu)
3506 goto drop;
3507
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003508 if (pi->partial_sdu_len == pi->sdu_len) {
3509 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3510 err = sock_queue_rcv_skb(sk, _skb);
3511 if (err < 0)
3512 kfree_skb(_skb);
3513 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003514 err = 0;
3515
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003516drop:
3517 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003518 break;
3519 }
3520
3521 kfree_skb(skb);
3522 return err;
3523}
3524
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003525static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3526{
3527 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003528 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003530 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003531 if (bt_cb(skb)->tx_seq != tx_seq)
3532 break;
3533
3534 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003535 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003536 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003537 l2cap_pi(sk)->buffer_seq_srej =
3538 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
3539 tx_seq++;
3540 }
3541}
3542
3543static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3544{
3545 struct l2cap_pinfo *pi = l2cap_pi(sk);
3546 struct srej_list *l, *tmp;
3547 u16 control;
3548
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003549 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003550 if (l->tx_seq == tx_seq) {
3551 list_del(&l->list);
3552 kfree(l);
3553 return;
3554 }
3555 control = L2CAP_SUPER_SELECT_REJECT;
3556 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3557 l2cap_send_sframe(pi, control);
3558 list_del(&l->list);
3559 list_add_tail(&l->list, SREJ_LIST(sk));
3560 }
3561}
3562
3563static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3564{
3565 struct l2cap_pinfo *pi = l2cap_pi(sk);
3566 struct srej_list *new;
3567 u16 control;
3568
3569 while (tx_seq != pi->expected_tx_seq) {
3570 control = L2CAP_SUPER_SELECT_REJECT;
3571 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3572 l2cap_send_sframe(pi, control);
3573
3574 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
3575 new->tx_seq = pi->expected_tx_seq++;
3576 list_add_tail(&new->list, SREJ_LIST(sk));
3577 }
3578 pi->expected_tx_seq++;
3579}
3580
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003581static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3582{
3583 struct l2cap_pinfo *pi = l2cap_pi(sk);
3584 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003585 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003586 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003587 u8 tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003588 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003589 int err = 0;
3590
3591 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3592
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003593 if (L2CAP_CTRL_FINAL & rx_control &&
3594 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003595 del_timer(&pi->monitor_timer);
3596 if (pi->unacked_frames > 0)
3597 __mod_retrans_timer();
3598 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3599 }
3600
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003601 pi->expected_ack_seq = req_seq;
3602 l2cap_drop_acked_frames(sk);
3603
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003604 if (tx_seq == pi->expected_tx_seq)
3605 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003606
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003607 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3608 if (tx_seq_offset < 0)
3609 tx_seq_offset += 64;
3610
3611 /* invalid tx_seq */
3612 if (tx_seq_offset >= pi->tx_win) {
3613 l2cap_send_disconn_req(pi->conn, sk);
3614 goto drop;
3615 }
3616
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003617 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3618 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003619
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003620 first = list_first_entry(SREJ_LIST(sk),
3621 struct srej_list, list);
3622 if (tx_seq == first->tx_seq) {
3623 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3624 l2cap_check_srej_gap(sk, tx_seq);
3625
3626 list_del(&first->list);
3627 kfree(first);
3628
3629 if (list_empty(SREJ_LIST(sk))) {
3630 pi->buffer_seq = pi->buffer_seq_srej;
3631 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003632 l2cap_send_ack(pi);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003633 }
3634 } else {
3635 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003636
3637 /* duplicated tx_seq */
3638 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3639 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003640
3641 list_for_each_entry(l, SREJ_LIST(sk), list) {
3642 if (l->tx_seq == tx_seq) {
3643 l2cap_resend_srejframe(sk, tx_seq);
3644 return 0;
3645 }
3646 }
3647 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003648 }
3649 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003650 expected_tx_seq_offset =
3651 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3652 if (expected_tx_seq_offset < 0)
3653 expected_tx_seq_offset += 64;
3654
3655 /* duplicated tx_seq */
3656 if (tx_seq_offset < expected_tx_seq_offset)
3657 goto drop;
3658
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003659 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003660
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003661 INIT_LIST_HEAD(SREJ_LIST(sk));
3662 pi->buffer_seq_srej = pi->buffer_seq;
3663
3664 __skb_queue_head_init(SREJ_QUEUE(sk));
3665 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3666
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003667 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3668
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003669 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003670 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003671 return 0;
3672
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003673expected:
3674 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3675
3676 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003677 bt_cb(skb)->tx_seq = tx_seq;
3678 bt_cb(skb)->sar = sar;
3679 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003680 return 0;
3681 }
3682
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003683 if (rx_control & L2CAP_CTRL_FINAL) {
3684 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3685 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3686 else {
Gustavo F. Padovanf6e6b162010-05-01 16:15:41 -03003687 if (!skb_queue_empty(TX_QUEUE(sk)))
3688 sk->sk_send_head = TX_QUEUE(sk)->next;
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003689 pi->next_tx_seq = pi->expected_ack_seq;
3690 l2cap_ertm_send(sk);
3691 }
3692 }
3693
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003694 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3695
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003696 err = l2cap_ertm_reassembly_sdu(sk, skb, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003697 if (err < 0)
3698 return err;
3699
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003700 __mod_ack_timer();
3701
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003702 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3703 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003704 l2cap_send_ack(pi);
3705
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003706 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003707
3708drop:
3709 kfree_skb(skb);
3710 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003711}
3712
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003713static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003714{
3715 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003716
3717 pi->expected_ack_seq = __get_reqseq(rx_control);
3718 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003719
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003720 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003721 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3722 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3723 (pi->unacked_frames > 0))
3724 __mod_retrans_timer();
3725
3726 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3727 l2cap_send_srejtail(sk);
3728 } else {
3729 l2cap_send_i_or_rr_or_rnr(sk);
3730 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3731 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003732
3733 } else if (rx_control & L2CAP_CTRL_FINAL) {
3734 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003735
3736 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3737 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3738 else {
Gustavo F. Padovanf6e6b162010-05-01 16:15:41 -03003739 if (!skb_queue_empty(TX_QUEUE(sk)))
3740 sk->sk_send_head = TX_QUEUE(sk)->next;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003741 pi->next_tx_seq = pi->expected_ack_seq;
3742 l2cap_ertm_send(sk);
3743 }
3744
3745 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003746 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3747 (pi->unacked_frames > 0))
3748 __mod_retrans_timer();
3749
3750 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3751 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
3752 l2cap_send_ack(pi);
3753 else
3754 l2cap_ertm_send(sk);
3755 }
3756}
3757
3758static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3759{
3760 struct l2cap_pinfo *pi = l2cap_pi(sk);
3761 u8 tx_seq = __get_reqseq(rx_control);
3762
3763 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3764
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003765 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003766 l2cap_drop_acked_frames(sk);
3767
3768 if (rx_control & L2CAP_CTRL_FINAL) {
3769 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3770 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3771 else {
Gustavo F. Padovanf6e6b162010-05-01 16:15:41 -03003772 if (!skb_queue_empty(TX_QUEUE(sk)))
3773 sk->sk_send_head = TX_QUEUE(sk)->next;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003774 pi->next_tx_seq = pi->expected_ack_seq;
3775 l2cap_ertm_send(sk);
3776 }
3777 } else {
Gustavo F. Padovanf6e6b162010-05-01 16:15:41 -03003778 if (!skb_queue_empty(TX_QUEUE(sk)))
3779 sk->sk_send_head = TX_QUEUE(sk)->next;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003780 pi->next_tx_seq = pi->expected_ack_seq;
3781 l2cap_ertm_send(sk);
3782
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003783 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003784 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003785 }
3786}
3787static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3788{
3789 struct l2cap_pinfo *pi = l2cap_pi(sk);
3790 u8 tx_seq = __get_reqseq(rx_control);
3791
3792 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3793
3794 if (rx_control & L2CAP_CTRL_POLL) {
3795 pi->expected_ack_seq = tx_seq;
3796 l2cap_drop_acked_frames(sk);
3797 l2cap_retransmit_frame(sk, tx_seq);
3798 l2cap_ertm_send(sk);
3799 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3800 pi->srej_save_reqseq = tx_seq;
3801 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3802 }
3803 } else if (rx_control & L2CAP_CTRL_FINAL) {
3804 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3805 pi->srej_save_reqseq == tx_seq)
3806 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3807 else
3808 l2cap_retransmit_frame(sk, tx_seq);
3809 } else {
3810 l2cap_retransmit_frame(sk, tx_seq);
3811 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3812 pi->srej_save_reqseq = tx_seq;
3813 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3814 }
3815 }
3816}
3817
3818static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3819{
3820 struct l2cap_pinfo *pi = l2cap_pi(sk);
3821 u8 tx_seq = __get_reqseq(rx_control);
3822
3823 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3824 pi->expected_ack_seq = tx_seq;
3825 l2cap_drop_acked_frames(sk);
3826
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003827 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3828 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003829 if (rx_control & L2CAP_CTRL_POLL)
3830 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003831 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003832 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003833
3834 if (rx_control & L2CAP_CTRL_POLL)
3835 l2cap_send_srejtail(sk);
3836 else
3837 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003838}
3839
3840static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3841{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003842 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3843
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003844 if (L2CAP_CTRL_FINAL & rx_control &&
3845 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003846 del_timer(&l2cap_pi(sk)->monitor_timer);
3847 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003848 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003849 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003850 }
3851
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003852 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3853 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003854 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003855 break;
3856
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003857 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003858 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003859 break;
3860
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003861 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003862 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003863 break;
3864
3865 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003866 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003867 break;
3868 }
3869
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003870 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003871 return 0;
3872}
3873
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3875{
3876 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003877 struct l2cap_pinfo *pi;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003878 u16 control, len;
João Paulo Rechi Vita01760bd2010-05-01 16:15:43 -03003879 u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
3881 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3882 if (!sk) {
3883 BT_DBG("unknown cid 0x%4.4x", cid);
3884 goto drop;
3885 }
3886
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003887 pi = l2cap_pi(sk);
3888
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 BT_DBG("sk %p, len %d", sk, skb->len);
3890
3891 if (sk->sk_state != BT_CONNECTED)
3892 goto drop;
3893
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003894 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003895 case L2CAP_MODE_BASIC:
3896 /* If socket recv buffers overflows we drop data here
3897 * which is *bad* because L2CAP has to be reliable.
3898 * But we don't have any other choice. L2CAP doesn't
3899 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003901 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003902 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003904 if (!sock_queue_rcv_skb(sk, skb))
3905 goto done;
3906 break;
3907
3908 case L2CAP_MODE_ERTM:
3909 control = get_unaligned_le16(skb->data);
3910 skb_pull(skb, 2);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003911 len = skb->len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003912
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003913 if (__is_sar_start(control))
3914 len -= 2;
3915
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003916 if (pi->fcs == L2CAP_FCS_CRC16)
3917 len -= 2;
3918
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003919 /*
3920 * We can just drop the corrupted I-frame here.
3921 * Receiver will miss it and start proper recovery
3922 * procedures and ask retransmission.
3923 */
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003924 if (len > pi->mps) {
3925 l2cap_send_disconn_req(pi->conn, sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003926 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003927 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003928
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003929 if (l2cap_check_fcs(pi, skb))
3930 goto drop;
3931
João Paulo Rechi Vita01760bd2010-05-01 16:15:43 -03003932 req_seq = __get_reqseq(control);
3933 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3934 if (req_seq_offset < 0)
3935 req_seq_offset += 64;
3936
3937 next_tx_seq_offset =
3938 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3939 if (next_tx_seq_offset < 0)
3940 next_tx_seq_offset += 64;
3941
3942 /* check for invalid req-seq */
3943 if (req_seq_offset > next_tx_seq_offset) {
3944 l2cap_send_disconn_req(pi->conn, sk);
3945 goto drop;
3946 }
3947
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003948 if (__is_iframe(control)) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003949 if (len < 4) {
3950 l2cap_send_disconn_req(pi->conn, sk);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003951 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003952 }
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003953
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003954 l2cap_data_channel_iframe(sk, control, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003955 } else {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003956 if (len != 0) {
3957 l2cap_send_disconn_req(pi->conn, sk);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003958 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003959 }
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003960
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003961 l2cap_data_channel_sframe(sk, control, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003962 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003963
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003964 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003965
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003966 case L2CAP_MODE_STREAMING:
3967 control = get_unaligned_le16(skb->data);
3968 skb_pull(skb, 2);
3969 len = skb->len;
3970
3971 if (__is_sar_start(control))
3972 len -= 2;
3973
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003974 if (pi->fcs == L2CAP_FCS_CRC16)
3975 len -= 2;
3976
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03003977 if (len > pi->mps || len < 4 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003978 goto drop;
3979
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003980 if (l2cap_check_fcs(pi, skb))
3981 goto drop;
3982
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003983 tx_seq = __get_txseq(control);
3984
3985 if (pi->expected_tx_seq == tx_seq)
3986 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3987 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003988 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003989
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003990 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003991
3992 goto done;
3993
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003994 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003995 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003996 break;
3997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
3999drop:
4000 kfree_skb(skb);
4001
4002done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004003 if (sk)
4004 bh_unlock_sock(sk);
4005
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 return 0;
4007}
4008
Al Viro8e036fc2007-07-29 00:16:36 -07004009static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010{
4011 struct sock *sk;
4012
4013 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
4014 if (!sk)
4015 goto drop;
4016
4017 BT_DBG("sk %p, len %d", sk, skb->len);
4018
4019 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4020 goto drop;
4021
4022 if (l2cap_pi(sk)->imtu < skb->len)
4023 goto drop;
4024
4025 if (!sock_queue_rcv_skb(sk, skb))
4026 goto done;
4027
4028drop:
4029 kfree_skb(skb);
4030
4031done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004032 if (sk)
4033 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 return 0;
4035}
4036
4037static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4038{
4039 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004040 u16 cid, len;
4041 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
4043 skb_pull(skb, L2CAP_HDR_SIZE);
4044 cid = __le16_to_cpu(lh->cid);
4045 len = __le16_to_cpu(lh->len);
4046
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004047 if (len != skb->len) {
4048 kfree_skb(skb);
4049 return;
4050 }
4051
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4053
4054 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004055 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 l2cap_sig_channel(conn, skb);
4057 break;
4058
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004059 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004060 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 skb_pull(skb, 2);
4062 l2cap_conless_channel(conn, psm, skb);
4063 break;
4064
4065 default:
4066 l2cap_data_channel(conn, cid, skb);
4067 break;
4068 }
4069}
4070
4071/* ---- L2CAP interface with lower layer (HCI) ---- */
4072
4073static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4074{
4075 int exact = 0, lm1 = 0, lm2 = 0;
4076 register struct sock *sk;
4077 struct hlist_node *node;
4078
4079 if (type != ACL_LINK)
4080 return 0;
4081
4082 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4083
4084 /* Find listening sockets and check their link_mode */
4085 read_lock(&l2cap_sk_list.lock);
4086 sk_for_each(sk, node, &l2cap_sk_list.head) {
4087 if (sk->sk_state != BT_LISTEN)
4088 continue;
4089
4090 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004091 lm1 |= HCI_LM_ACCEPT;
4092 if (l2cap_pi(sk)->role_switch)
4093 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004095 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4096 lm2 |= HCI_LM_ACCEPT;
4097 if (l2cap_pi(sk)->role_switch)
4098 lm2 |= HCI_LM_MASTER;
4099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 }
4101 read_unlock(&l2cap_sk_list.lock);
4102
4103 return exact ? lm1 : lm2;
4104}
4105
4106static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4107{
Marcel Holtmann01394182006-07-03 10:02:46 +02004108 struct l2cap_conn *conn;
4109
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4111
4112 if (hcon->type != ACL_LINK)
4113 return 0;
4114
4115 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 conn = l2cap_conn_add(hcon, status);
4117 if (conn)
4118 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004119 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 l2cap_conn_del(hcon, bt_err(status));
4121
4122 return 0;
4123}
4124
Marcel Holtmann2950f212009-02-12 14:02:50 +01004125static int l2cap_disconn_ind(struct hci_conn *hcon)
4126{
4127 struct l2cap_conn *conn = hcon->l2cap_data;
4128
4129 BT_DBG("hcon %p", hcon);
4130
4131 if (hcon->type != ACL_LINK || !conn)
4132 return 0x13;
4133
4134 return conn->disc_reason;
4135}
4136
4137static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
4139 BT_DBG("hcon %p reason %d", hcon, reason);
4140
4141 if (hcon->type != ACL_LINK)
4142 return 0;
4143
4144 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004145
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 return 0;
4147}
4148
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004149static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
4150{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004151 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004152 return;
4153
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004154 if (encrypt == 0x00) {
4155 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
4156 l2cap_sock_clear_timer(sk);
4157 l2cap_sock_set_timer(sk, HZ * 5);
4158 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
4159 __l2cap_sock_close(sk, ECONNREFUSED);
4160 } else {
4161 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
4162 l2cap_sock_clear_timer(sk);
4163 }
4164}
4165
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004166static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167{
4168 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02004169 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171
Marcel Holtmann01394182006-07-03 10:02:46 +02004172 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004174
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 l = &conn->chan_list;
4176
4177 BT_DBG("conn %p", conn);
4178
4179 read_lock(&l->lock);
4180
4181 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
4182 bh_lock_sock(sk);
4183
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004184 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
4185 bh_unlock_sock(sk);
4186 continue;
4187 }
4188
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004189 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004190 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004191 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004192 bh_unlock_sock(sk);
4193 continue;
4194 }
4195
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004196 if (sk->sk_state == BT_CONNECT) {
4197 if (!status) {
4198 struct l2cap_conn_req req;
4199 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
4200 req.psm = l2cap_pi(sk)->psm;
4201
4202 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
4203
4204 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4205 L2CAP_CONN_REQ, sizeof(req), &req);
4206 } else {
4207 l2cap_sock_clear_timer(sk);
4208 l2cap_sock_set_timer(sk, HZ / 10);
4209 }
4210 } else if (sk->sk_state == BT_CONNECT2) {
4211 struct l2cap_conn_rsp rsp;
4212 __u16 result;
4213
4214 if (!status) {
4215 sk->sk_state = BT_CONFIG;
4216 result = L2CAP_CR_SUCCESS;
4217 } else {
4218 sk->sk_state = BT_DISCONN;
4219 l2cap_sock_set_timer(sk, HZ / 10);
4220 result = L2CAP_CR_SEC_BLOCK;
4221 }
4222
4223 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
4224 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
4225 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004226 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004227 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
4228 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 }
4230
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 bh_unlock_sock(sk);
4232 }
4233
4234 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004235
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236 return 0;
4237}
4238
4239static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4240{
4241 struct l2cap_conn *conn = hcon->l2cap_data;
4242
4243 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
4244 goto drop;
4245
4246 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4247
4248 if (flags & ACL_START) {
4249 struct l2cap_hdr *hdr;
4250 int len;
4251
4252 if (conn->rx_len) {
4253 BT_ERR("Unexpected start frame (len %d)", skb->len);
4254 kfree_skb(conn->rx_skb);
4255 conn->rx_skb = NULL;
4256 conn->rx_len = 0;
4257 l2cap_conn_unreliable(conn, ECOMM);
4258 }
4259
4260 if (skb->len < 2) {
4261 BT_ERR("Frame is too short (len %d)", skb->len);
4262 l2cap_conn_unreliable(conn, ECOMM);
4263 goto drop;
4264 }
4265
4266 hdr = (struct l2cap_hdr *) skb->data;
4267 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
4268
4269 if (len == skb->len) {
4270 /* Complete frame received */
4271 l2cap_recv_frame(conn, skb);
4272 return 0;
4273 }
4274
4275 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4276
4277 if (skb->len > len) {
4278 BT_ERR("Frame is too long (len %d, expected len %d)",
4279 skb->len, len);
4280 l2cap_conn_unreliable(conn, ECOMM);
4281 goto drop;
4282 }
4283
4284 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004285 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4286 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 goto drop;
4288
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004289 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004290 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291 conn->rx_len = len - skb->len;
4292 } else {
4293 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4294
4295 if (!conn->rx_len) {
4296 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4297 l2cap_conn_unreliable(conn, ECOMM);
4298 goto drop;
4299 }
4300
4301 if (skb->len > conn->rx_len) {
4302 BT_ERR("Fragment is too long (len %d, expected %d)",
4303 skb->len, conn->rx_len);
4304 kfree_skb(conn->rx_skb);
4305 conn->rx_skb = NULL;
4306 conn->rx_len = 0;
4307 l2cap_conn_unreliable(conn, ECOMM);
4308 goto drop;
4309 }
4310
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004311 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004312 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 conn->rx_len -= skb->len;
4314
4315 if (!conn->rx_len) {
4316 /* Complete frame received */
4317 l2cap_recv_frame(conn, conn->rx_skb);
4318 conn->rx_skb = NULL;
4319 }
4320 }
4321
4322drop:
4323 kfree_skb(skb);
4324 return 0;
4325}
4326
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004327static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328{
4329 struct sock *sk;
4330 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331
4332 read_lock_bh(&l2cap_sk_list.lock);
4333
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004334 sk_for_each(sk, node, &l2cap_sk_list.head) {
4335 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004337 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4338 batostr(&bt_sk(sk)->src),
4339 batostr(&bt_sk(sk)->dst),
4340 sk->sk_state, __le16_to_cpu(pi->psm),
4341 pi->scid, pi->dcid,
4342 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004343 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004346
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004347 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348}
4349
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004350static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4351{
4352 return single_open(file, l2cap_debugfs_show, inode->i_private);
4353}
4354
4355static const struct file_operations l2cap_debugfs_fops = {
4356 .open = l2cap_debugfs_open,
4357 .read = seq_read,
4358 .llseek = seq_lseek,
4359 .release = single_release,
4360};
4361
4362static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004364static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 .family = PF_BLUETOOTH,
4366 .owner = THIS_MODULE,
4367 .release = l2cap_sock_release,
4368 .bind = l2cap_sock_bind,
4369 .connect = l2cap_sock_connect,
4370 .listen = l2cap_sock_listen,
4371 .accept = l2cap_sock_accept,
4372 .getname = l2cap_sock_getname,
4373 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004374 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004376 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 .mmap = sock_no_mmap,
4378 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379 .shutdown = l2cap_sock_shutdown,
4380 .setsockopt = l2cap_sock_setsockopt,
4381 .getsockopt = l2cap_sock_getsockopt
4382};
4383
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004384static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 .family = PF_BLUETOOTH,
4386 .owner = THIS_MODULE,
4387 .create = l2cap_sock_create,
4388};
4389
4390static struct hci_proto l2cap_hci_proto = {
4391 .name = "L2CAP",
4392 .id = HCI_PROTO_L2CAP,
4393 .connect_ind = l2cap_connect_ind,
4394 .connect_cfm = l2cap_connect_cfm,
4395 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004396 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004397 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 .recv_acldata = l2cap_recv_acldata
4399};
4400
4401static int __init l2cap_init(void)
4402{
4403 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004404
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 err = proto_register(&l2cap_proto, 0);
4406 if (err < 0)
4407 return err;
4408
4409 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4410 if (err < 0) {
4411 BT_ERR("L2CAP socket registration failed");
4412 goto error;
4413 }
4414
4415 err = hci_register_proto(&l2cap_hci_proto);
4416 if (err < 0) {
4417 BT_ERR("L2CAP protocol registration failed");
4418 bt_sock_unregister(BTPROTO_L2CAP);
4419 goto error;
4420 }
4421
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004422 if (bt_debugfs) {
4423 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4424 bt_debugfs, NULL, &l2cap_debugfs_fops);
4425 if (!l2cap_debugfs)
4426 BT_ERR("Failed to create L2CAP debug file");
4427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
4429 BT_INFO("L2CAP ver %s", VERSION);
4430 BT_INFO("L2CAP socket layer initialized");
4431
4432 return 0;
4433
4434error:
4435 proto_unregister(&l2cap_proto);
4436 return err;
4437}
4438
4439static void __exit l2cap_exit(void)
4440{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004441 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
4443 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4444 BT_ERR("L2CAP socket unregistration failed");
4445
4446 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4447 BT_ERR("L2CAP protocol unregistration failed");
4448
4449 proto_unregister(&l2cap_proto);
4450}
4451
4452void l2cap_load(void)
4453{
4454 /* Dummy function to trigger automatic L2CAP module loading by
4455 * other modules that use L2CAP sockets but don't use any other
4456 * symbols from it. */
4457 return;
4458}
4459EXPORT_SYMBOL(l2cap_load);
4460
4461module_init(l2cap_init);
4462module_exit(l2cap_exit);
4463
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004464module_param(enable_ertm, bool, 0644);
4465MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
4466
Marcel Holtmann5fbcd3d2009-10-05 11:35:43 +02004467module_param(max_transmit, uint, 0644);
4468MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)");
4469
Gustavo F. Padovan369ba302010-05-01 16:15:41 -03004470module_param(tx_window, uint, 0644);
4471MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)");
4472
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004473MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4475MODULE_VERSION(VERSION);
4476MODULE_LICENSE("GPL");
4477MODULE_ALIAS("bt-proto-0");