blob: 0a739ef167c23a6a2b8dff615293b01beff2f937 [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
58static int enable_ertm = 0;
Marcel Holtmann5fbcd3d2009-10-05 11:35:43 +020059static int max_transmit = L2CAP_DEFAULT_MAX_TX;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010062static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Eric Dumazet90ddc4f2005-12-22 12:49:22 -080064static const struct proto_ops l2cap_sock_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
66static struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070067 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068};
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static void __l2cap_sock_close(struct sock *sk, int reason);
71static void l2cap_sock_close(struct sock *sk);
72static void l2cap_sock_kill(struct sock *sk);
73
74static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
75 u8 code, u8 ident, u16 dlen, void *data);
76
77/* ---- L2CAP timers ---- */
78static void l2cap_sock_timeout(unsigned long arg)
79{
80 struct sock *sk = (struct sock *) arg;
Marcel Holtmannb1235d72008-07-14 20:13:54 +020081 int reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83 BT_DBG("sock %p state %d", sk, sk->sk_state);
84
85 bh_lock_sock(sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +020086
Marcel Holtmannf62e4322009-01-15 21:58:44 +010087 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
88 reason = ECONNREFUSED;
89 else if (sk->sk_state == BT_CONNECT &&
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +010090 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
Marcel Holtmannb1235d72008-07-14 20:13:54 +020091 reason = ECONNREFUSED;
92 else
93 reason = ETIMEDOUT;
94
95 __l2cap_sock_close(sk, reason);
96
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 bh_unlock_sock(sk);
98
99 l2cap_sock_kill(sk);
100 sock_put(sk);
101}
102
103static void l2cap_sock_set_timer(struct sock *sk, long timeout)
104{
105 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
106 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
107}
108
109static void l2cap_sock_clear_timer(struct sock *sk)
110{
111 BT_DBG("sock %p state %d", sk, sk->sk_state);
112 sk_stop_timer(sk, &sk->sk_timer);
113}
114
Marcel Holtmann01394182006-07-03 10:02:46 +0200115/* ---- L2CAP channels ---- */
116static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
117{
118 struct sock *s;
119 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
120 if (l2cap_pi(s)->dcid == cid)
121 break;
122 }
123 return s;
124}
125
126static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
127{
128 struct sock *s;
129 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
130 if (l2cap_pi(s)->scid == cid)
131 break;
132 }
133 return s;
134}
135
136/* Find channel with given SCID.
137 * Returns locked socket */
138static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
139{
140 struct sock *s;
141 read_lock(&l->lock);
142 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300143 if (s)
144 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200145 read_unlock(&l->lock);
146 return s;
147}
148
149static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
150{
151 struct sock *s;
152 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
153 if (l2cap_pi(s)->ident == ident)
154 break;
155 }
156 return s;
157}
158
159static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
160{
161 struct sock *s;
162 read_lock(&l->lock);
163 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300164 if (s)
165 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200166 read_unlock(&l->lock);
167 return s;
168}
169
170static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
171{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300172 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200173
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300174 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300175 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200176 return cid;
177 }
178
179 return 0;
180}
181
182static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
183{
184 sock_hold(sk);
185
186 if (l->head)
187 l2cap_pi(l->head)->prev_c = sk;
188
189 l2cap_pi(sk)->next_c = l->head;
190 l2cap_pi(sk)->prev_c = NULL;
191 l->head = sk;
192}
193
194static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
195{
196 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
197
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200198 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200199 if (sk == l->head)
200 l->head = next;
201
202 if (next)
203 l2cap_pi(next)->prev_c = prev;
204 if (prev)
205 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200206 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200207
208 __sock_put(sk);
209}
210
211static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
212{
213 struct l2cap_chan_list *l = &conn->chan_list;
214
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300215 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
216 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200217
Marcel Holtmann2950f212009-02-12 14:02:50 +0100218 conn->disc_reason = 0x13;
219
Marcel Holtmann01394182006-07-03 10:02:46 +0200220 l2cap_pi(sk)->conn = conn;
221
222 if (sk->sk_type == SOCK_SEQPACKET) {
223 /* Alloc CID for connection-oriented socket */
224 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
225 } else if (sk->sk_type == SOCK_DGRAM) {
226 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300227 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
228 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200229 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
230 } else {
231 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300232 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
233 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200234 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
235 }
236
237 __l2cap_chan_link(l, sk);
238
239 if (parent)
240 bt_accept_enqueue(parent, sk);
241}
242
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900243/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200244 * Must be called on the locked socket. */
245static void l2cap_chan_del(struct sock *sk, int err)
246{
247 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
248 struct sock *parent = bt_sk(sk)->parent;
249
250 l2cap_sock_clear_timer(sk);
251
252 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
253
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900254 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200255 /* Unlink from channel list */
256 l2cap_chan_unlink(&conn->chan_list, sk);
257 l2cap_pi(sk)->conn = NULL;
258 hci_conn_put(conn->hcon);
259 }
260
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200261 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200262 sock_set_flag(sk, SOCK_ZAPPED);
263
264 if (err)
265 sk->sk_err = err;
266
267 if (parent) {
268 bt_accept_unlink(sk);
269 parent->sk_data_ready(parent, 0);
270 } else
271 sk->sk_state_change(sk);
272}
273
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200274/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100275static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200276{
277 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100278 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200279
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100280 if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
281 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
282 auth_type = HCI_AT_NO_BONDING_MITM;
283 else
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300284 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann00ae4af2009-02-12 16:19:45 +0100285
286 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
287 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
288 } else {
289 switch (l2cap_pi(sk)->sec_level) {
290 case BT_SECURITY_HIGH:
291 auth_type = HCI_AT_GENERAL_BONDING_MITM;
292 break;
293 case BT_SECURITY_MEDIUM:
294 auth_type = HCI_AT_GENERAL_BONDING;
295 break;
296 default:
297 auth_type = HCI_AT_NO_BONDING;
298 break;
299 }
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 }
301
302 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
303 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200304}
305
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200306static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
307{
308 u8 id;
309
310 /* Get next available identificator.
311 * 1 - 128 are used by kernel.
312 * 129 - 199 are reserved.
313 * 200 - 254 are used by utilities like l2ping, etc.
314 */
315
316 spin_lock_bh(&conn->lock);
317
318 if (++conn->tx_ident > 128)
319 conn->tx_ident = 1;
320
321 id = conn->tx_ident;
322
323 spin_unlock_bh(&conn->lock);
324
325 return id;
326}
327
328static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
329{
330 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
331
332 BT_DBG("code 0x%2.2x", code);
333
334 if (!skb)
335 return -ENOMEM;
336
337 return hci_send_acl(conn->hcon, skb, 0);
338}
339
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300340static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
341{
342 struct sk_buff *skb;
343 struct l2cap_hdr *lh;
344 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300345 int count, hlen = L2CAP_HDR_SIZE + 2;
346
347 if (pi->fcs == L2CAP_FCS_CRC16)
348 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300349
350 BT_DBG("pi %p, control 0x%2.2x", pi, control);
351
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300352 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300353 control |= L2CAP_CTRL_FRAME_TYPE;
354
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300355 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
356 control |= L2CAP_CTRL_FINAL;
357 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
358 }
359
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300360 skb = bt_skb_alloc(count, GFP_ATOMIC);
361 if (!skb)
362 return -ENOMEM;
363
364 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300365 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300366 lh->cid = cpu_to_le16(pi->dcid);
367 put_unaligned_le16(control, skb_put(skb, 2));
368
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300369 if (pi->fcs == L2CAP_FCS_CRC16) {
370 u16 fcs = crc16(0, (u8 *)lh, count - 2);
371 put_unaligned_le16(fcs, skb_put(skb, 2));
372 }
373
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374 return hci_send_acl(pi->conn->hcon, skb, 0);
375}
376
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300377static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
378{
379 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY)
380 control |= L2CAP_SUPER_RCV_NOT_READY;
381 else
382 control |= L2CAP_SUPER_RCV_READY;
383
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300384 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
385
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300386 return l2cap_send_sframe(pi, control);
387}
388
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200389static void l2cap_do_start(struct sock *sk)
390{
391 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
392
393 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100394 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
395 return;
396
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100397 if (l2cap_check_security(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200398 struct l2cap_conn_req req;
399 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
400 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200401
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200402 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200403
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200404 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200405 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200406 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200407 } else {
408 struct l2cap_info_req req;
409 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
410
411 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
412 conn->info_ident = l2cap_get_ident(conn);
413
414 mod_timer(&conn->info_timer, jiffies +
415 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
416
417 l2cap_send_cmd(conn, conn->info_ident,
418 L2CAP_INFO_REQ, sizeof(req), &req);
419 }
420}
421
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300422static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
423{
424 struct l2cap_disconn_req req;
425
426 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
427 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
428 l2cap_send_cmd(conn, l2cap_get_ident(conn),
429 L2CAP_DISCONN_REQ, sizeof(req), &req);
430}
431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200433static void l2cap_conn_start(struct l2cap_conn *conn)
434{
435 struct l2cap_chan_list *l = &conn->chan_list;
436 struct sock *sk;
437
438 BT_DBG("conn %p", conn);
439
440 read_lock(&l->lock);
441
442 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
443 bh_lock_sock(sk);
444
445 if (sk->sk_type != SOCK_SEQPACKET) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200446 bh_unlock_sock(sk);
447 continue;
448 }
449
450 if (sk->sk_state == BT_CONNECT) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100451 if (l2cap_check_security(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200452 struct l2cap_conn_req req;
453 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
454 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200455
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200456 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200457
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200458 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200459 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200460 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200461 } else if (sk->sk_state == BT_CONNECT2) {
462 struct l2cap_conn_rsp rsp;
463 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
464 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
465
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100466 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100467 if (bt_sk(sk)->defer_setup) {
468 struct sock *parent = bt_sk(sk)->parent;
469 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
470 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
471 parent->sk_data_ready(parent, 0);
472
473 } else {
474 sk->sk_state = BT_CONFIG;
475 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
476 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
477 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200478 } else {
479 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
480 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
481 }
482
483 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
484 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
485 }
486
487 bh_unlock_sock(sk);
488 }
489
490 read_unlock(&l->lock);
491}
492
493static void l2cap_conn_ready(struct l2cap_conn *conn)
494{
495 struct l2cap_chan_list *l = &conn->chan_list;
496 struct sock *sk;
497
498 BT_DBG("conn %p", conn);
499
500 read_lock(&l->lock);
501
502 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
503 bh_lock_sock(sk);
504
505 if (sk->sk_type != SOCK_SEQPACKET) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200506 l2cap_sock_clear_timer(sk);
507 sk->sk_state = BT_CONNECTED;
508 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200509 } else if (sk->sk_state == BT_CONNECT)
510 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200511
512 bh_unlock_sock(sk);
513 }
514
515 read_unlock(&l->lock);
516}
517
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200518/* Notify sockets that we cannot guaranty reliability anymore */
519static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
520{
521 struct l2cap_chan_list *l = &conn->chan_list;
522 struct sock *sk;
523
524 BT_DBG("conn %p", conn);
525
526 read_lock(&l->lock);
527
528 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100529 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200530 sk->sk_err = err;
531 }
532
533 read_unlock(&l->lock);
534}
535
536static void l2cap_info_timeout(unsigned long arg)
537{
538 struct l2cap_conn *conn = (void *) arg;
539
Marcel Holtmann984947d2009-02-06 23:35:19 +0100540 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100541 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100542
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200543 l2cap_conn_start(conn);
544}
545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
547{
Marcel Holtmann01394182006-07-03 10:02:46 +0200548 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Marcel Holtmann01394182006-07-03 10:02:46 +0200550 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 return conn;
552
Marcel Holtmann01394182006-07-03 10:02:46 +0200553 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
554 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
557 hcon->l2cap_data = conn;
558 conn->hcon = hcon;
559
Marcel Holtmann01394182006-07-03 10:02:46 +0200560 BT_DBG("hcon %p conn %p", hcon, conn);
561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 conn->mtu = hcon->hdev->acl_mtu;
563 conn->src = &hcon->hdev->bdaddr;
564 conn->dst = &hcon->dst;
565
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200566 conn->feat_mask = 0;
567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 spin_lock_init(&conn->lock);
569 rwlock_init(&conn->chan_list.lock);
570
Dave Young45054dc2009-10-18 20:28:30 +0000571 setup_timer(&conn->info_timer, l2cap_info_timeout,
572 (unsigned long) conn);
573
Marcel Holtmann2950f212009-02-12 14:02:50 +0100574 conn->disc_reason = 0x13;
575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 return conn;
577}
578
Marcel Holtmann01394182006-07-03 10:02:46 +0200579static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Marcel Holtmann01394182006-07-03 10:02:46 +0200581 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 struct sock *sk;
583
Marcel Holtmann01394182006-07-03 10:02:46 +0200584 if (!conn)
585 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
587 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
588
Wei Yongjun7585b972009-02-25 18:29:52 +0800589 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 /* Kill channels */
592 while ((sk = conn->chan_list.head)) {
593 bh_lock_sock(sk);
594 l2cap_chan_del(sk, err);
595 bh_unlock_sock(sk);
596 l2cap_sock_kill(sk);
597 }
598
Dave Young8e8440f2008-03-03 12:18:55 -0800599 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
600 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800601
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 hcon->l2cap_data = NULL;
603 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604}
605
606static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
607{
608 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200609 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200611 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612}
613
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614/* ---- Socket interface ---- */
Al Viro8e036fc2007-07-29 00:16:36 -0700615static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616{
617 struct sock *sk;
618 struct hlist_node *node;
619 sk_for_each(sk, node, &l2cap_sk_list.head)
620 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
621 goto found;
622 sk = NULL;
623found:
624 return sk;
625}
626
627/* Find socket with psm and source bdaddr.
628 * Returns closest match.
629 */
Al Viro8e036fc2007-07-29 00:16:36 -0700630static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
632 struct sock *sk = NULL, *sk1 = NULL;
633 struct hlist_node *node;
634
635 sk_for_each(sk, node, &l2cap_sk_list.head) {
636 if (state && sk->sk_state != state)
637 continue;
638
639 if (l2cap_pi(sk)->psm == psm) {
640 /* Exact match. */
641 if (!bacmp(&bt_sk(sk)->src, src))
642 break;
643
644 /* Closest match */
645 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
646 sk1 = sk;
647 }
648 }
649 return node ? sk : sk1;
650}
651
652/* Find socket with given address (psm, src).
653 * Returns locked socket */
Al Viro8e036fc2007-07-29 00:16:36 -0700654static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
656 struct sock *s;
657 read_lock(&l2cap_sk_list.lock);
658 s = __l2cap_get_sock_by_psm(state, psm, src);
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300659 if (s)
660 bh_lock_sock(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 read_unlock(&l2cap_sk_list.lock);
662 return s;
663}
664
665static void l2cap_sock_destruct(struct sock *sk)
666{
667 BT_DBG("sk %p", sk);
668
669 skb_queue_purge(&sk->sk_receive_queue);
670 skb_queue_purge(&sk->sk_write_queue);
671}
672
673static void l2cap_sock_cleanup_listen(struct sock *parent)
674{
675 struct sock *sk;
676
677 BT_DBG("parent %p", parent);
678
679 /* Close not yet accepted channels */
680 while ((sk = bt_accept_dequeue(parent, NULL)))
681 l2cap_sock_close(sk);
682
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200683 parent->sk_state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 sock_set_flag(parent, SOCK_ZAPPED);
685}
686
687/* Kill socket (only if zapped and orphan)
688 * Must be called on unlocked socket.
689 */
690static void l2cap_sock_kill(struct sock *sk)
691{
692 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
693 return;
694
695 BT_DBG("sk %p state %d", sk, sk->sk_state);
696
697 /* Kill poor orphan */
698 bt_sock_unlink(&l2cap_sk_list, sk);
699 sock_set_flag(sk, SOCK_DEAD);
700 sock_put(sk);
701}
702
703static void __l2cap_sock_close(struct sock *sk, int reason)
704{
705 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
706
707 switch (sk->sk_state) {
708 case BT_LISTEN:
709 l2cap_sock_cleanup_listen(sk);
710 break;
711
712 case BT_CONNECTED:
713 case BT_CONFIG:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 if (sk->sk_type == SOCK_SEQPACKET) {
715 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717 sk->sk_state = BT_DISCONN;
718 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300719 l2cap_send_disconn_req(conn, sk);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200720 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 l2cap_chan_del(sk, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 break;
723
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100724 case BT_CONNECT2:
725 if (sk->sk_type == SOCK_SEQPACKET) {
726 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
727 struct l2cap_conn_rsp rsp;
728 __u16 result;
729
730 if (bt_sk(sk)->defer_setup)
731 result = L2CAP_CR_SEC_BLOCK;
732 else
733 result = L2CAP_CR_BAD_PSM;
734
735 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
736 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
737 rsp.result = cpu_to_le16(result);
738 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
739 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
740 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
741 } else
742 l2cap_chan_del(sk, reason);
743 break;
744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 case BT_CONNECT:
746 case BT_DISCONN:
747 l2cap_chan_del(sk, reason);
748 break;
749
750 default:
751 sock_set_flag(sk, SOCK_ZAPPED);
752 break;
753 }
754}
755
756/* Must be called on unlocked socket. */
757static void l2cap_sock_close(struct sock *sk)
758{
759 l2cap_sock_clear_timer(sk);
760 lock_sock(sk);
761 __l2cap_sock_close(sk, ECONNRESET);
762 release_sock(sk);
763 l2cap_sock_kill(sk);
764}
765
766static void l2cap_sock_init(struct sock *sk, struct sock *parent)
767{
768 struct l2cap_pinfo *pi = l2cap_pi(sk);
769
770 BT_DBG("sk %p", sk);
771
772 if (parent) {
773 sk->sk_type = parent->sk_type;
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100774 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 pi->imtu = l2cap_pi(parent)->imtu;
777 pi->omtu = l2cap_pi(parent)->omtu;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700778 pi->mode = l2cap_pi(parent)->mode;
779 pi->fcs = l2cap_pi(parent)->fcs;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100780 pi->sec_level = l2cap_pi(parent)->sec_level;
781 pi->role_switch = l2cap_pi(parent)->role_switch;
782 pi->force_reliable = l2cap_pi(parent)->force_reliable;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 } else {
784 pi->imtu = L2CAP_DEFAULT_MTU;
785 pi->omtu = 0;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -0700786 pi->mode = L2CAP_MODE_BASIC;
787 pi->fcs = L2CAP_FCS_CRC16;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100788 pi->sec_level = BT_SECURITY_LOW;
789 pi->role_switch = 0;
790 pi->force_reliable = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 }
792
793 /* Default config options */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +0200794 pi->conf_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Dave Young45054dc2009-10-18 20:28:30 +0000796 skb_queue_head_init(TX_QUEUE(sk));
797 skb_queue_head_init(SREJ_QUEUE(sk));
798 INIT_LIST_HEAD(SREJ_LIST(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799}
800
801static struct proto l2cap_proto = {
802 .name = "L2CAP",
803 .owner = THIS_MODULE,
804 .obj_size = sizeof(struct l2cap_pinfo)
805};
806
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700807static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
809 struct sock *sk;
810
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700811 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 if (!sk)
813 return NULL;
814
815 sock_init_data(sock, sk);
816 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
817
818 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200819 sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821 sock_reset_flag(sk, SOCK_ZAPPED);
822
823 sk->sk_protocol = proto;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200824 sk->sk_state = BT_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200826 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
828 bt_sock_link(&l2cap_sk_list, sk);
829 return sk;
830}
831
Eric Paris3f378b62009-11-05 22:18:14 -0800832static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
833 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834{
835 struct sock *sk;
836
837 BT_DBG("sock %p", sock);
838
839 sock->state = SS_UNCONNECTED;
840
841 if (sock->type != SOCK_SEQPACKET &&
842 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
843 return -ESOCKTNOSUPPORT;
844
Eric Parisc84b3262009-11-05 20:45:52 -0800845 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 return -EPERM;
847
848 sock->ops = &l2cap_sock_ops;
849
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700850 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 if (!sk)
852 return -ENOMEM;
853
854 l2cap_sock_init(sk, NULL);
855 return 0;
856}
857
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100858static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100861 struct sockaddr_l2 la;
862 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100864 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
866 if (!addr || addr->sa_family != AF_BLUETOOTH)
867 return -EINVAL;
868
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100869 memset(&la, 0, sizeof(la));
870 len = min_t(unsigned int, sizeof(la), alen);
871 memcpy(&la, addr, len);
872
Marcel Holtmann2a517ca2009-02-16 03:20:31 +0100873 if (la.l2_cid)
874 return -EINVAL;
875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 lock_sock(sk);
877
878 if (sk->sk_state != BT_OPEN) {
879 err = -EBADFD;
880 goto done;
881 }
882
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200883 if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
Marcel Holtmann847641d2007-01-22 22:00:45 +0100884 !capable(CAP_NET_BIND_SERVICE)) {
885 err = -EACCES;
886 goto done;
887 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 write_lock_bh(&l2cap_sk_list.lock);
890
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100891 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 err = -EADDRINUSE;
893 } else {
894 /* Save source address */
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100895 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
896 l2cap_pi(sk)->psm = la.l2_psm;
897 l2cap_pi(sk)->sport = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 sk->sk_state = BT_BOUND;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100899
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200900 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
901 __le16_to_cpu(la.l2_psm) == 0x0003)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100902 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
904
905 write_unlock_bh(&l2cap_sk_list.lock);
906
907done:
908 release_sock(sk);
909 return err;
910}
911
912static int l2cap_do_connect(struct sock *sk)
913{
914 bdaddr_t *src = &bt_sk(sk)->src;
915 bdaddr_t *dst = &bt_sk(sk)->dst;
916 struct l2cap_conn *conn;
917 struct hci_conn *hcon;
918 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200919 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200920 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100922 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
923 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300925 hdev = hci_get_route(dst, src);
926 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 return -EHOSTUNREACH;
928
929 hci_dev_lock_bh(hdev);
930
931 err = -ENOMEM;
932
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100933 if (sk->sk_type == SOCK_RAW) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100934 switch (l2cap_pi(sk)->sec_level) {
935 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100936 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100937 break;
938 case BT_SECURITY_MEDIUM:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100939 auth_type = HCI_AT_DEDICATED_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100940 break;
941 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100942 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100943 break;
944 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100945 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100946 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200947 auth_type = HCI_AT_NO_BONDING_MITM;
948 else
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200949 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann435fef22009-02-09 03:55:28 +0100950
951 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
952 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100953 } else {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100954 switch (l2cap_pi(sk)->sec_level) {
955 case BT_SECURITY_HIGH:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100956 auth_type = HCI_AT_GENERAL_BONDING_MITM;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100957 break;
958 case BT_SECURITY_MEDIUM:
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200959 auth_type = HCI_AT_GENERAL_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100960 break;
961 default:
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100962 auth_type = HCI_AT_NO_BONDING;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100963 break;
964 }
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200965 }
966
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100967 hcon = hci_connect(hdev, ACL_LINK, dst,
968 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 if (!hcon)
970 goto done;
971
972 conn = l2cap_conn_add(hcon, 0);
973 if (!conn) {
974 hci_conn_put(hcon);
975 goto done;
976 }
977
978 err = 0;
979
980 /* Update source addr of the socket */
981 bacpy(src, conn->src);
982
983 l2cap_chan_add(conn, sk, NULL);
984
985 sk->sk_state = BT_CONNECT;
986 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
987
988 if (hcon->state == BT_CONNECTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200989 if (sk->sk_type != SOCK_SEQPACKET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 l2cap_sock_clear_timer(sk);
991 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200992 } else
993 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
995
996done:
997 hci_dev_unlock_bh(hdev);
998 hci_dev_put(hdev);
999 return err;
1000}
1001
1002static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
1003{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 struct sock *sk = sock->sk;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001005 struct sockaddr_l2 la;
1006 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 BT_DBG("sk %p", sk);
1009
Changli Gao6503d962010-03-31 22:58:26 +00001010 if (!addr || alen < sizeof(addr->sa_family) ||
1011 addr->sa_family != AF_BLUETOOTH)
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001012 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001014 memset(&la, 0, sizeof(la));
1015 len = min_t(unsigned int, sizeof(la), alen);
1016 memcpy(&la, addr, len);
1017
Marcel Holtmann2a517ca2009-02-16 03:20:31 +01001018 if (la.l2_cid)
1019 return -EINVAL;
1020
1021 lock_sock(sk);
1022
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001023 if (sk->sk_type == SOCK_SEQPACKET && !la.l2_psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 err = -EINVAL;
1025 goto done;
1026 }
1027
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001028 switch (l2cap_pi(sk)->mode) {
1029 case L2CAP_MODE_BASIC:
1030 break;
1031 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001032 case L2CAP_MODE_STREAMING:
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001033 if (enable_ertm)
1034 break;
1035 /* fall through */
1036 default:
1037 err = -ENOTSUPP;
1038 goto done;
1039 }
1040
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001041 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 case BT_CONNECT:
1043 case BT_CONNECT2:
1044 case BT_CONFIG:
1045 /* Already connecting */
1046 goto wait;
1047
1048 case BT_CONNECTED:
1049 /* Already connected */
1050 goto done;
1051
1052 case BT_OPEN:
1053 case BT_BOUND:
1054 /* Can connect */
1055 break;
1056
1057 default:
1058 err = -EBADFD;
1059 goto done;
1060 }
1061
1062 /* Set destination address and psm */
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001063 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
1064 l2cap_pi(sk)->psm = la.l2_psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001066 err = l2cap_do_connect(sk);
1067 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 goto done;
1069
1070wait:
1071 err = bt_sock_wait_state(sk, BT_CONNECTED,
1072 sock_sndtimeo(sk, flags & O_NONBLOCK));
1073done:
1074 release_sock(sk);
1075 return err;
1076}
1077
1078static int l2cap_sock_listen(struct socket *sock, int backlog)
1079{
1080 struct sock *sk = sock->sk;
1081 int err = 0;
1082
1083 BT_DBG("sk %p backlog %d", sk, backlog);
1084
1085 lock_sock(sk);
1086
1087 if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) {
1088 err = -EBADFD;
1089 goto done;
1090 }
1091
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001092 switch (l2cap_pi(sk)->mode) {
1093 case L2CAP_MODE_BASIC:
1094 break;
1095 case L2CAP_MODE_ERTM:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001096 case L2CAP_MODE_STREAMING:
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001097 if (enable_ertm)
1098 break;
1099 /* fall through */
1100 default:
1101 err = -ENOTSUPP;
1102 goto done;
1103 }
1104
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 if (!l2cap_pi(sk)->psm) {
1106 bdaddr_t *src = &bt_sk(sk)->src;
1107 u16 psm;
1108
1109 err = -EINVAL;
1110
1111 write_lock_bh(&l2cap_sk_list.lock);
1112
1113 for (psm = 0x1001; psm < 0x1100; psm += 2)
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001114 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
1115 l2cap_pi(sk)->psm = cpu_to_le16(psm);
1116 l2cap_pi(sk)->sport = cpu_to_le16(psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 err = 0;
1118 break;
1119 }
1120
1121 write_unlock_bh(&l2cap_sk_list.lock);
1122
1123 if (err < 0)
1124 goto done;
1125 }
1126
1127 sk->sk_max_ack_backlog = backlog;
1128 sk->sk_ack_backlog = 0;
1129 sk->sk_state = BT_LISTEN;
1130
1131done:
1132 release_sock(sk);
1133 return err;
1134}
1135
1136static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
1137{
1138 DECLARE_WAITQUEUE(wait, current);
1139 struct sock *sk = sock->sk, *nsk;
1140 long timeo;
1141 int err = 0;
1142
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001143 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 if (sk->sk_state != BT_LISTEN) {
1146 err = -EBADFD;
1147 goto done;
1148 }
1149
1150 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1151
1152 BT_DBG("sk %p timeo %ld", sk, timeo);
1153
1154 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +00001155 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
1157 set_current_state(TASK_INTERRUPTIBLE);
1158 if (!timeo) {
1159 err = -EAGAIN;
1160 break;
1161 }
1162
1163 release_sock(sk);
1164 timeo = schedule_timeout(timeo);
Peter Zijlstrafcc70d52006-11-08 22:44:35 -08001165 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
1167 if (sk->sk_state != BT_LISTEN) {
1168 err = -EBADFD;
1169 break;
1170 }
1171
1172 if (signal_pending(current)) {
1173 err = sock_intr_errno(timeo);
1174 break;
1175 }
1176 }
1177 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +00001178 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
1180 if (err)
1181 goto done;
1182
1183 newsock->state = SS_CONNECTED;
1184
1185 BT_DBG("new socket %p", nsk);
1186
1187done:
1188 release_sock(sk);
1189 return err;
1190}
1191
1192static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
1193{
1194 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
1195 struct sock *sk = sock->sk;
1196
1197 BT_DBG("sock %p, sk %p", sock, sk);
1198
1199 addr->sa_family = AF_BLUETOOTH;
1200 *len = sizeof(struct sockaddr_l2);
1201
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001202 if (peer) {
1203 la->l2_psm = l2cap_pi(sk)->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001205 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001206 } else {
1207 la->l2_psm = l2cap_pi(sk)->sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001209 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return 0;
1213}
1214
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001215static void l2cap_monitor_timeout(unsigned long arg)
1216{
1217 struct sock *sk = (void *) arg;
1218 u16 control;
1219
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001220 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001221 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
1222 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001223 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224 return;
1225 }
1226
1227 l2cap_pi(sk)->retry_count++;
1228 __mod_monitor_timer();
1229
1230 control = L2CAP_CTRL_POLL;
Gustavo F. Padovan7e743092009-08-26 04:04:03 -03001231 l2cap_send_rr_or_rnr(l2cap_pi(sk), control);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001232 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001233}
1234
1235static void l2cap_retrans_timeout(unsigned long arg)
1236{
1237 struct sock *sk = (void *) arg;
1238 u16 control;
1239
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001240 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001241 l2cap_pi(sk)->retry_count = 1;
1242 __mod_monitor_timer();
1243
1244 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1245
1246 control = L2CAP_CTRL_POLL;
Gustavo F. Padovan7e743092009-08-26 04:04:03 -03001247 l2cap_send_rr_or_rnr(l2cap_pi(sk), control);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001248 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001249}
1250
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251static void l2cap_drop_acked_frames(struct sock *sk)
1252{
1253 struct sk_buff *skb;
1254
1255 while ((skb = skb_peek(TX_QUEUE(sk)))) {
1256 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1257 break;
1258
1259 skb = skb_dequeue(TX_QUEUE(sk));
1260 kfree_skb(skb);
1261
1262 l2cap_pi(sk)->unacked_frames--;
1263 }
1264
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001265 if (!l2cap_pi(sk)->unacked_frames)
1266 del_timer(&l2cap_pi(sk)->retrans_timer);
1267
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001268 return;
1269}
1270
1271static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb)
1272{
1273 struct l2cap_pinfo *pi = l2cap_pi(sk);
1274 int err;
1275
1276 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1277
1278 err = hci_send_acl(pi->conn->hcon, skb, 0);
1279 if (err < 0)
1280 kfree_skb(skb);
1281
1282 return err;
1283}
1284
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001285static int l2cap_streaming_send(struct sock *sk)
1286{
1287 struct sk_buff *skb, *tx_skb;
1288 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001289 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001290 int err;
1291
1292 while ((skb = sk->sk_send_head)) {
1293 tx_skb = skb_clone(skb, GFP_ATOMIC);
1294
1295 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1296 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
1297 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1298
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001299 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001300 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1301 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1302 }
1303
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001304 err = l2cap_do_send(sk, tx_skb);
1305 if (err < 0) {
1306 l2cap_send_disconn_req(pi->conn, sk);
1307 return err;
1308 }
1309
1310 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1311
1312 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1313 sk->sk_send_head = NULL;
1314 else
1315 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
1316
1317 skb = skb_dequeue(TX_QUEUE(sk));
1318 kfree_skb(skb);
1319 }
1320 return 0;
1321}
1322
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001323static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
1324{
1325 struct l2cap_pinfo *pi = l2cap_pi(sk);
1326 struct sk_buff *skb, *tx_skb;
1327 u16 control, fcs;
1328 int err;
1329
1330 skb = skb_peek(TX_QUEUE(sk));
1331 do {
1332 if (bt_cb(skb)->tx_seq != tx_seq) {
1333 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1334 break;
1335 skb = skb_queue_next(TX_QUEUE(sk), skb);
1336 continue;
1337 }
1338
1339 if (pi->remote_max_tx &&
1340 bt_cb(skb)->retries == pi->remote_max_tx) {
1341 l2cap_send_disconn_req(pi->conn, sk);
1342 break;
1343 }
1344
1345 tx_skb = skb_clone(skb, GFP_ATOMIC);
1346 bt_cb(skb)->retries++;
1347 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001348 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001349 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1350 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1351
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001352 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001353 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1354 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1355 }
1356
1357 err = l2cap_do_send(sk, tx_skb);
1358 if (err < 0) {
1359 l2cap_send_disconn_req(pi->conn, sk);
1360 return err;
1361 }
1362 break;
1363 } while(1);
1364 return 0;
1365}
1366
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001367static int l2cap_ertm_send(struct sock *sk)
1368{
1369 struct sk_buff *skb, *tx_skb;
1370 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001371 u16 control, fcs;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001372 int err, nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001374 if (pi->conn_state & L2CAP_CONN_WAIT_F)
1375 return 0;
1376
Joe Perchesf64f9e72009-11-29 16:55:45 -08001377 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
1378 !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001379
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001380 if (pi->remote_max_tx &&
1381 bt_cb(skb)->retries == pi->remote_max_tx) {
1382 l2cap_send_disconn_req(pi->conn, sk);
1383 break;
1384 }
1385
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001386 tx_skb = skb_clone(skb, GFP_ATOMIC);
1387
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001388 bt_cb(skb)->retries++;
1389
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001390 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001391 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1392 control |= L2CAP_CTRL_FINAL;
1393 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1394 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001395 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001396 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1397 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1398
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001399
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001400 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001401 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1402 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1403 }
1404
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405 err = l2cap_do_send(sk, tx_skb);
1406 if (err < 0) {
1407 l2cap_send_disconn_req(pi->conn, sk);
1408 return err;
1409 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001410 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001411
1412 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1413 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1414
1415 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001416 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001417
1418 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1419 sk->sk_send_head = NULL;
1420 else
1421 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001422
1423 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001424 }
1425
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001426 return nsent;
1427}
1428
1429static int l2cap_send_ack(struct l2cap_pinfo *pi)
1430{
1431 struct sock *sk = (struct sock *)pi;
1432 u16 control = 0;
1433
1434 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1435
1436 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1437 control |= L2CAP_SUPER_RCV_NOT_READY;
1438 return l2cap_send_sframe(pi, control);
1439 } else if (l2cap_ertm_send(sk) == 0) {
1440 control |= L2CAP_SUPER_RCV_READY;
1441 return l2cap_send_sframe(pi, control);
1442 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001443 return 0;
1444}
1445
1446static 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 -07001447{
1448 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001449 struct sk_buff **frag;
1450 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001453 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
1455
1456 sent += count;
1457 len -= count;
1458
1459 /* Continuation fragments (no L2CAP header) */
1460 frag = &skb_shinfo(skb)->frag_list;
1461 while (len) {
1462 count = min_t(unsigned int, conn->mtu, len);
1463
1464 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1465 if (!*frag)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466 return -EFAULT;
1467 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1468 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
1470 sent += count;
1471 len -= count;
1472
1473 frag = &(*frag)->next;
1474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001477}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001479static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1480{
1481 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1482 struct sk_buff *skb;
1483 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1484 struct l2cap_hdr *lh;
1485
1486 BT_DBG("sk %p len %d", sk, (int)len);
1487
1488 count = min_t(unsigned int, (conn->mtu - hlen), len);
1489 skb = bt_skb_send_alloc(sk, count + hlen,
1490 msg->msg_flags & MSG_DONTWAIT, &err);
1491 if (!skb)
1492 return ERR_PTR(-ENOMEM);
1493
1494 /* Create L2CAP header */
1495 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1496 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1497 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1498 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1499
1500 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1501 if (unlikely(err < 0)) {
1502 kfree_skb(skb);
1503 return ERR_PTR(err);
1504 }
1505 return skb;
1506}
1507
1508static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
1509{
1510 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1511 struct sk_buff *skb;
1512 int err, count, hlen = L2CAP_HDR_SIZE;
1513 struct l2cap_hdr *lh;
1514
1515 BT_DBG("sk %p len %d", sk, (int)len);
1516
1517 count = min_t(unsigned int, (conn->mtu - hlen), len);
1518 skb = bt_skb_send_alloc(sk, count + hlen,
1519 msg->msg_flags & MSG_DONTWAIT, &err);
1520 if (!skb)
1521 return ERR_PTR(-ENOMEM);
1522
1523 /* Create L2CAP header */
1524 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1525 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1526 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1527
1528 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1529 if (unlikely(err < 0)) {
1530 kfree_skb(skb);
1531 return ERR_PTR(err);
1532 }
1533 return skb;
1534}
1535
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001536static 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 -03001537{
1538 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1539 struct sk_buff *skb;
1540 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1541 struct l2cap_hdr *lh;
1542
1543 BT_DBG("sk %p len %d", sk, (int)len);
1544
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001545 if (sdulen)
1546 hlen += 2;
1547
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001548 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1549 hlen += 2;
1550
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001551 count = min_t(unsigned int, (conn->mtu - hlen), len);
1552 skb = bt_skb_send_alloc(sk, count + hlen,
1553 msg->msg_flags & MSG_DONTWAIT, &err);
1554 if (!skb)
1555 return ERR_PTR(-ENOMEM);
1556
1557 /* Create L2CAP header */
1558 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1559 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1560 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1561 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001562 if (sdulen)
1563 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001564
1565 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1566 if (unlikely(err < 0)) {
1567 kfree_skb(skb);
1568 return ERR_PTR(err);
1569 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001570
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001571 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1572 put_unaligned_le16(0, skb_put(skb, 2));
1573
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001574 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001575 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576}
1577
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001578static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
1579{
1580 struct l2cap_pinfo *pi = l2cap_pi(sk);
1581 struct sk_buff *skb;
1582 struct sk_buff_head sar_queue;
1583 u16 control;
1584 size_t size = 0;
1585
1586 __skb_queue_head_init(&sar_queue);
1587 control = L2CAP_SDU_START;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001588 skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001589 if (IS_ERR(skb))
1590 return PTR_ERR(skb);
1591
1592 __skb_queue_tail(&sar_queue, skb);
1593 len -= pi->max_pdu_size;
1594 size +=pi->max_pdu_size;
1595 control = 0;
1596
1597 while (len > 0) {
1598 size_t buflen;
1599
1600 if (len > pi->max_pdu_size) {
1601 control |= L2CAP_SDU_CONTINUE;
1602 buflen = pi->max_pdu_size;
1603 } else {
1604 control |= L2CAP_SDU_END;
1605 buflen = len;
1606 }
1607
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001608 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001609 if (IS_ERR(skb)) {
1610 skb_queue_purge(&sar_queue);
1611 return PTR_ERR(skb);
1612 }
1613
1614 __skb_queue_tail(&sar_queue, skb);
1615 len -= buflen;
1616 size += buflen;
1617 control = 0;
1618 }
1619 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1620 if (sk->sk_send_head == NULL)
1621 sk->sk_send_head = sar_queue.next;
1622
1623 return size;
1624}
1625
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
1627{
1628 struct sock *sk = sock->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001629 struct l2cap_pinfo *pi = l2cap_pi(sk);
1630 struct sk_buff *skb;
1631 u16 control;
1632 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
1634 BT_DBG("sock %p, sk %p", sock, sk);
1635
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -08001636 err = sock_error(sk);
1637 if (err)
1638 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
1640 if (msg->msg_flags & MSG_OOB)
1641 return -EOPNOTSUPP;
1642
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 lock_sock(sk);
1644
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001645 if (sk->sk_state != BT_CONNECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 err = -ENOTCONN;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001647 goto done;
1648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001650 /* Connectionless channel */
1651 if (sk->sk_type == SOCK_DGRAM) {
1652 skb = l2cap_create_connless_pdu(sk, msg, len);
Dan Carpenter477fffb2010-04-21 23:52:01 +00001653 if (IS_ERR(skb))
1654 err = PTR_ERR(skb);
1655 else
1656 err = l2cap_do_send(sk, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001657 goto done;
1658 }
1659
1660 switch (pi->mode) {
1661 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc69163e2010-05-01 16:15:35 -03001662 /* Check outgoing MTU */
1663 if (len > pi->omtu) {
1664 err = -EINVAL;
1665 goto done;
1666 }
1667
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001668 /* Create a basic PDU */
1669 skb = l2cap_create_basic_pdu(sk, msg, len);
1670 if (IS_ERR(skb)) {
1671 err = PTR_ERR(skb);
1672 goto done;
1673 }
1674
1675 err = l2cap_do_send(sk, skb);
1676 if (!err)
1677 err = len;
1678 break;
1679
1680 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001681 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001682 /* Entire SDU fits into one PDU */
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001683 if (len <= pi->max_pdu_size) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001684 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001685 skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001686 if (IS_ERR(skb)) {
1687 err = PTR_ERR(skb);
1688 goto done;
1689 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001690 __skb_queue_tail(TX_QUEUE(sk), skb);
1691 if (sk->sk_send_head == NULL)
1692 sk->sk_send_head = skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001693 } else {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001694 /* Segment SDU into multiples PDUs */
1695 err = l2cap_sar_segment_sdu(sk, msg, len);
1696 if (err < 0)
1697 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001698 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001699
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001700 if (pi->mode == L2CAP_MODE_STREAMING)
1701 err = l2cap_streaming_send(sk);
1702 else
1703 err = l2cap_ertm_send(sk);
1704
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001705 if (err >= 0)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001706 err = len;
1707 break;
1708
1709 default:
1710 BT_DBG("bad state %1.1x", pi->mode);
1711 err = -EINVAL;
1712 }
1713
1714done:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 release_sock(sk);
1716 return err;
1717}
1718
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001719static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1720{
1721 struct sock *sk = sock->sk;
1722
1723 lock_sock(sk);
1724
1725 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1726 struct l2cap_conn_rsp rsp;
1727
1728 sk->sk_state = BT_CONFIG;
1729
1730 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1731 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1732 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1733 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1734 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1735 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1736
1737 release_sock(sk);
1738 return 0;
1739 }
1740
1741 release_sock(sk);
1742
1743 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1744}
1745
David S. Millerb7058842009-09-30 16:12:20 -07001746static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747{
1748 struct sock *sk = sock->sk;
1749 struct l2cap_options opts;
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001750 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 u32 opt;
1752
1753 BT_DBG("sk %p", sk);
1754
1755 lock_sock(sk);
1756
1757 switch (optname) {
1758 case L2CAP_OPTIONS:
Marcel Holtmann0878b662007-05-05 00:35:59 +02001759 opts.imtu = l2cap_pi(sk)->imtu;
1760 opts.omtu = l2cap_pi(sk)->omtu;
1761 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001762 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001763 opts.fcs = l2cap_pi(sk)->fcs;
Marcel Holtmann0878b662007-05-05 00:35:59 +02001764
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 len = min_t(unsigned int, sizeof(opts), optlen);
1766 if (copy_from_user((char *) &opts, optval, len)) {
1767 err = -EFAULT;
1768 break;
1769 }
Marcel Holtmann0878b662007-05-05 00:35:59 +02001770
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001771 l2cap_pi(sk)->imtu = opts.imtu;
1772 l2cap_pi(sk)->omtu = opts.omtu;
1773 l2cap_pi(sk)->mode = opts.mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001774 l2cap_pi(sk)->fcs = opts.fcs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 break;
1776
1777 case L2CAP_LM:
1778 if (get_user(opt, (u32 __user *) optval)) {
1779 err = -EFAULT;
1780 break;
1781 }
1782
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001783 if (opt & L2CAP_LM_AUTH)
1784 l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
1785 if (opt & L2CAP_LM_ENCRYPT)
1786 l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
1787 if (opt & L2CAP_LM_SECURE)
1788 l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
1789
1790 l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
1791 l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 break;
1793
1794 default:
1795 err = -ENOPROTOOPT;
1796 break;
1797 }
1798
1799 release_sock(sk);
1800 return err;
1801}
1802
David S. Millerb7058842009-09-30 16:12:20 -07001803static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001804{
1805 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001806 struct bt_security sec;
1807 int len, err = 0;
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001808 u32 opt;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001809
1810 BT_DBG("sk %p", sk);
1811
1812 if (level == SOL_L2CAP)
1813 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
1814
Marcel Holtmann0588d942009-01-16 10:06:13 +01001815 if (level != SOL_BLUETOOTH)
1816 return -ENOPROTOOPT;
1817
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001818 lock_sock(sk);
1819
1820 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001821 case BT_SECURITY:
Marcel Holtmann2526d3d2009-02-20 20:54:06 +01001822 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01001823 err = -EINVAL;
1824 break;
1825 }
1826
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001827 sec.level = BT_SECURITY_LOW;
1828
1829 len = min_t(unsigned int, sizeof(sec), optlen);
1830 if (copy_from_user((char *) &sec, optval, len)) {
1831 err = -EFAULT;
1832 break;
1833 }
1834
1835 if (sec.level < BT_SECURITY_LOW ||
1836 sec.level > BT_SECURITY_HIGH) {
1837 err = -EINVAL;
1838 break;
1839 }
1840
1841 l2cap_pi(sk)->sec_level = sec.level;
1842 break;
1843
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001844 case BT_DEFER_SETUP:
1845 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1846 err = -EINVAL;
1847 break;
1848 }
1849
1850 if (get_user(opt, (u32 __user *) optval)) {
1851 err = -EFAULT;
1852 break;
1853 }
1854
1855 bt_sk(sk)->defer_setup = opt;
1856 break;
1857
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001858 default:
1859 err = -ENOPROTOOPT;
1860 break;
1861 }
1862
1863 release_sock(sk);
1864 return err;
1865}
1866
1867static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868{
1869 struct sock *sk = sock->sk;
1870 struct l2cap_options opts;
1871 struct l2cap_conninfo cinfo;
1872 int len, err = 0;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001873 u32 opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
1875 BT_DBG("sk %p", sk);
1876
1877 if (get_user(len, optlen))
1878 return -EFAULT;
1879
1880 lock_sock(sk);
1881
1882 switch (optname) {
1883 case L2CAP_OPTIONS:
1884 opts.imtu = l2cap_pi(sk)->imtu;
1885 opts.omtu = l2cap_pi(sk)->omtu;
1886 opts.flush_to = l2cap_pi(sk)->flush_to;
Marcel Holtmannc6b03cf2009-05-02 22:31:10 -07001887 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001888 opts.fcs = l2cap_pi(sk)->fcs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
1890 len = min_t(unsigned int, len, sizeof(opts));
1891 if (copy_to_user(optval, (char *) &opts, len))
1892 err = -EFAULT;
1893
1894 break;
1895
1896 case L2CAP_LM:
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001897 switch (l2cap_pi(sk)->sec_level) {
1898 case BT_SECURITY_LOW:
1899 opt = L2CAP_LM_AUTH;
1900 break;
1901 case BT_SECURITY_MEDIUM:
1902 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
1903 break;
1904 case BT_SECURITY_HIGH:
1905 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
1906 L2CAP_LM_SECURE;
1907 break;
1908 default:
1909 opt = 0;
1910 break;
1911 }
1912
1913 if (l2cap_pi(sk)->role_switch)
1914 opt |= L2CAP_LM_MASTER;
1915
1916 if (l2cap_pi(sk)->force_reliable)
1917 opt |= L2CAP_LM_RELIABLE;
1918
1919 if (put_user(opt, (u32 __user *) optval))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 err = -EFAULT;
1921 break;
1922
1923 case L2CAP_CONNINFO:
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001924 if (sk->sk_state != BT_CONNECTED &&
1925 !(sk->sk_state == BT_CONNECT2 &&
1926 bt_sk(sk)->defer_setup)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 err = -ENOTCONN;
1928 break;
1929 }
1930
1931 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
1932 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
1933
1934 len = min_t(unsigned int, len, sizeof(cinfo));
1935 if (copy_to_user(optval, (char *) &cinfo, len))
1936 err = -EFAULT;
1937
1938 break;
1939
1940 default:
1941 err = -ENOPROTOOPT;
1942 break;
1943 }
1944
1945 release_sock(sk);
1946 return err;
1947}
1948
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001949static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
1950{
1951 struct sock *sk = sock->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001952 struct bt_security sec;
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001953 int len, err = 0;
1954
1955 BT_DBG("sk %p", sk);
1956
1957 if (level == SOL_L2CAP)
1958 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
1959
Marcel Holtmann0588d942009-01-16 10:06:13 +01001960 if (level != SOL_BLUETOOTH)
1961 return -ENOPROTOOPT;
1962
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001963 if (get_user(len, optlen))
1964 return -EFAULT;
1965
1966 lock_sock(sk);
1967
1968 switch (optname) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001969 case BT_SECURITY:
Marcel Holtmann2526d3d2009-02-20 20:54:06 +01001970 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) {
Marcel Holtmann0588d942009-01-16 10:06:13 +01001971 err = -EINVAL;
1972 break;
1973 }
1974
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001975 sec.level = l2cap_pi(sk)->sec_level;
1976
1977 len = min_t(unsigned int, len, sizeof(sec));
1978 if (copy_to_user(optval, (char *) &sec, len))
1979 err = -EFAULT;
1980
1981 break;
1982
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001983 case BT_DEFER_SETUP:
1984 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1985 err = -EINVAL;
1986 break;
1987 }
1988
1989 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
1990 err = -EFAULT;
1991
1992 break;
1993
Marcel Holtmannd58daf42009-01-15 21:52:14 +01001994 default:
1995 err = -ENOPROTOOPT;
1996 break;
1997 }
1998
1999 release_sock(sk);
2000 return err;
2001}
2002
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003static int l2cap_sock_shutdown(struct socket *sock, int how)
2004{
2005 struct sock *sk = sock->sk;
2006 int err = 0;
2007
2008 BT_DBG("sock %p, sk %p", sock, sk);
2009
2010 if (!sk)
2011 return 0;
2012
2013 lock_sock(sk);
2014 if (!sk->sk_shutdown) {
2015 sk->sk_shutdown = SHUTDOWN_MASK;
2016 l2cap_sock_clear_timer(sk);
2017 __l2cap_sock_close(sk, 0);
2018
2019 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002020 err = bt_sock_wait_state(sk, BT_CLOSED,
2021 sk->sk_lingertime);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 }
2023 release_sock(sk);
2024 return err;
2025}
2026
2027static int l2cap_sock_release(struct socket *sock)
2028{
2029 struct sock *sk = sock->sk;
2030 int err;
2031
2032 BT_DBG("sock %p, sk %p", sock, sk);
2033
2034 if (!sk)
2035 return 0;
2036
2037 err = l2cap_sock_shutdown(sock, 2);
2038
2039 sock_orphan(sk);
2040 l2cap_sock_kill(sk);
2041 return err;
2042}
2043
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044static void l2cap_chan_ready(struct sock *sk)
2045{
2046 struct sock *parent = bt_sk(sk)->parent;
2047
2048 BT_DBG("sk %p, parent %p", sk, parent);
2049
2050 l2cap_pi(sk)->conf_state = 0;
2051 l2cap_sock_clear_timer(sk);
2052
2053 if (!parent) {
2054 /* Outgoing channel.
2055 * Wake up socket sleeping on connect.
2056 */
2057 sk->sk_state = BT_CONNECTED;
2058 sk->sk_state_change(sk);
2059 } else {
2060 /* Incoming channel.
2061 * Wake up socket sleeping on accept.
2062 */
2063 parent->sk_data_ready(parent, 0);
2064 }
2065}
2066
2067/* Copy frame to all raw sockets on that connection */
2068static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2069{
2070 struct l2cap_chan_list *l = &conn->chan_list;
2071 struct sk_buff *nskb;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002072 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
2074 BT_DBG("conn %p", conn);
2075
2076 read_lock(&l->lock);
2077 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2078 if (sk->sk_type != SOCK_RAW)
2079 continue;
2080
2081 /* Don't send frame to the socket it came from */
2082 if (skb->sk == sk)
2083 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002084 nskb = skb_clone(skb, GFP_ATOMIC);
2085 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 continue;
2087
2088 if (sock_queue_rcv_skb(sk, nskb))
2089 kfree_skb(nskb);
2090 }
2091 read_unlock(&l->lock);
2092}
2093
2094/* ---- L2CAP signalling commands ---- */
2095static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2096 u8 code, u8 ident, u16 dlen, void *data)
2097{
2098 struct sk_buff *skb, **frag;
2099 struct l2cap_cmd_hdr *cmd;
2100 struct l2cap_hdr *lh;
2101 int len, count;
2102
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002103 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2104 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
2106 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2107 count = min_t(unsigned int, conn->mtu, len);
2108
2109 skb = bt_skb_alloc(count, GFP_ATOMIC);
2110 if (!skb)
2111 return NULL;
2112
2113 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002114 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03002115 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
2117 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2118 cmd->code = code;
2119 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002120 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
2122 if (dlen) {
2123 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2124 memcpy(skb_put(skb, count), data, count);
2125 data += count;
2126 }
2127
2128 len -= skb->len;
2129
2130 /* Continuation fragments (no L2CAP header) */
2131 frag = &skb_shinfo(skb)->frag_list;
2132 while (len) {
2133 count = min_t(unsigned int, conn->mtu, len);
2134
2135 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2136 if (!*frag)
2137 goto fail;
2138
2139 memcpy(skb_put(*frag, count), data, count);
2140
2141 len -= count;
2142 data += count;
2143
2144 frag = &(*frag)->next;
2145 }
2146
2147 return skb;
2148
2149fail:
2150 kfree_skb(skb);
2151 return NULL;
2152}
2153
2154static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2155{
2156 struct l2cap_conf_opt *opt = *ptr;
2157 int len;
2158
2159 len = L2CAP_CONF_OPT_SIZE + opt->len;
2160 *ptr += len;
2161
2162 *type = opt->type;
2163 *olen = opt->len;
2164
2165 switch (opt->len) {
2166 case 1:
2167 *val = *((u8 *) opt->val);
2168 break;
2169
2170 case 2:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002171 *val = __le16_to_cpu(*((__le16 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 break;
2173
2174 case 4:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002175 *val = __le32_to_cpu(*((__le32 *) opt->val));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 break;
2177
2178 default:
2179 *val = (unsigned long) opt->val;
2180 break;
2181 }
2182
2183 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2184 return len;
2185}
2186
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2188{
2189 struct l2cap_conf_opt *opt = *ptr;
2190
2191 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2192
2193 opt->type = type;
2194 opt->len = len;
2195
2196 switch (len) {
2197 case 1:
2198 *((u8 *) opt->val) = val;
2199 break;
2200
2201 case 2:
Al Viro8e036fc2007-07-29 00:16:36 -07002202 *((__le16 *) opt->val) = cpu_to_le16(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 break;
2204
2205 case 4:
Al Viro8e036fc2007-07-29 00:16:36 -07002206 *((__le32 *) opt->val) = cpu_to_le32(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 break;
2208
2209 default:
2210 memcpy(opt->val, (void *) val, len);
2211 break;
2212 }
2213
2214 *ptr += L2CAP_CONF_OPT_SIZE + len;
2215}
2216
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002217static inline void l2cap_ertm_init(struct sock *sk)
2218{
2219 l2cap_pi(sk)->expected_ack_seq = 0;
2220 l2cap_pi(sk)->unacked_frames = 0;
2221 l2cap_pi(sk)->buffer_seq = 0;
2222 l2cap_pi(sk)->num_to_ack = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002223 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002224
2225 setup_timer(&l2cap_pi(sk)->retrans_timer,
2226 l2cap_retrans_timeout, (unsigned long) sk);
2227 setup_timer(&l2cap_pi(sk)->monitor_timer,
2228 l2cap_monitor_timeout, (unsigned long) sk);
2229
2230 __skb_queue_head_init(SREJ_QUEUE(sk));
2231}
2232
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002233static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
2234{
2235 u32 local_feat_mask = l2cap_feat_mask;
2236 if (enable_ertm)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03002237 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002238
2239 switch (mode) {
2240 case L2CAP_MODE_ERTM:
2241 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
2242 case L2CAP_MODE_STREAMING:
2243 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
2244 default:
2245 return 0x00;
2246 }
2247}
2248
2249static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2250{
2251 switch (mode) {
2252 case L2CAP_MODE_STREAMING:
2253 case L2CAP_MODE_ERTM:
2254 if (l2cap_mode_supported(mode, remote_feat_mask))
2255 return mode;
2256 /* fall through */
2257 default:
2258 return L2CAP_MODE_BASIC;
2259 }
2260}
2261
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262static int l2cap_build_conf_req(struct sock *sk, void *data)
2263{
2264 struct l2cap_pinfo *pi = l2cap_pi(sk);
2265 struct l2cap_conf_req *req = data;
Gustavo F. Padovana0e55a32009-09-29 01:42:23 -03002266 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 void *ptr = req->data;
2268
2269 BT_DBG("sk %p", sk);
2270
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002271 if (pi->num_conf_req || pi->num_conf_rsp)
2272 goto done;
2273
2274 switch (pi->mode) {
2275 case L2CAP_MODE_STREAMING:
2276 case L2CAP_MODE_ERTM:
2277 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002278 if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
2279 l2cap_send_disconn_req(pi->conn, sk);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002280 break;
2281 default:
2282 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2283 break;
2284 }
2285
2286done:
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002287 switch (pi->mode) {
2288 case L2CAP_MODE_BASIC:
2289 if (pi->imtu != L2CAP_DEFAULT_MTU)
2290 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
2291 break;
2292
2293 case L2CAP_MODE_ERTM:
2294 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002295 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
Marcel Holtmann5fbcd3d2009-10-05 11:35:43 +02002296 rfc.max_transmit = max_transmit;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002297 rfc.retrans_timeout = 0;
2298 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002299 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002300 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
2301 rfc.max_pdu_size = pi->conn->mtu - 10;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002302
2303 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2304 sizeof(rfc), (unsigned long) &rfc);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002305
2306 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2307 break;
2308
2309 if (pi->fcs == L2CAP_FCS_NONE ||
2310 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2311 pi->fcs = L2CAP_FCS_NONE;
2312 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2313 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002314 break;
2315
2316 case L2CAP_MODE_STREAMING:
2317 rfc.mode = L2CAP_MODE_STREAMING;
2318 rfc.txwin_size = 0;
2319 rfc.max_transmit = 0;
2320 rfc.retrans_timeout = 0;
2321 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002322 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03002323 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
2324 rfc.max_pdu_size = pi->conn->mtu - 10;
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002325
2326 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2327 sizeof(rfc), (unsigned long) &rfc);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002328
2329 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
2330 break;
2331
2332 if (pi->fcs == L2CAP_FCS_NONE ||
2333 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
2334 pi->fcs = L2CAP_FCS_NONE;
2335 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
2336 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002337 break;
2338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
2340 /* FIXME: Need actual value of the flush timeout */
2341 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
2342 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
2343
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002344 req->dcid = cpu_to_le16(pi->dcid);
2345 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346
2347 return ptr - data;
2348}
2349
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002350static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351{
2352 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002353 struct l2cap_conf_rsp *rsp = data;
2354 void *ptr = rsp->data;
2355 void *req = pi->conf_req;
2356 int len = pi->conf_len;
2357 int type, hint, olen;
2358 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002359 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002360 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002361 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002363 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002364
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002365 while (len >= L2CAP_CONF_OPT_SIZE) {
2366 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002368 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002369 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002370
2371 switch (type) {
2372 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002373 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002374 break;
2375
2376 case L2CAP_CONF_FLUSH_TO:
2377 pi->flush_to = val;
2378 break;
2379
2380 case L2CAP_CONF_QOS:
2381 break;
2382
Marcel Holtmann6464f352007-10-20 13:39:51 +02002383 case L2CAP_CONF_RFC:
2384 if (olen == sizeof(rfc))
2385 memcpy(&rfc, (void *) val, olen);
2386 break;
2387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002388 case L2CAP_CONF_FCS:
2389 if (val == L2CAP_FCS_NONE)
2390 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
2391
2392 break;
2393
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002394 default:
2395 if (hint)
2396 break;
2397
2398 result = L2CAP_CONF_UNKNOWN;
2399 *((u8 *) ptr++) = type;
2400 break;
2401 }
2402 }
2403
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002404 if (pi->num_conf_rsp || pi->num_conf_req)
2405 goto done;
2406
2407 switch (pi->mode) {
2408 case L2CAP_MODE_STREAMING:
2409 case L2CAP_MODE_ERTM:
2410 pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
2411 if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
2412 return -ECONNREFUSED;
2413 break;
2414 default:
2415 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
2416 break;
2417 }
2418
2419done:
2420 if (pi->mode != rfc.mode) {
2421 result = L2CAP_CONF_UNACCEPT;
2422 rfc.mode = pi->mode;
2423
2424 if (pi->num_conf_rsp == 1)
2425 return -ECONNREFUSED;
2426
2427 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2428 sizeof(rfc), (unsigned long) &rfc);
2429 }
2430
2431
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002432 if (result == L2CAP_CONF_SUCCESS) {
2433 /* Configure output options and let the other side know
2434 * which ones we don't like. */
2435
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002436 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2437 result = L2CAP_CONF_UNACCEPT;
2438 else {
2439 pi->omtu = mtu;
2440 pi->conf_state |= L2CAP_CONF_MTU_DONE;
2441 }
2442 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002443
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002444 switch (rfc.mode) {
2445 case L2CAP_MODE_BASIC:
2446 pi->fcs = L2CAP_FCS_NONE;
2447 pi->conf_state |= L2CAP_CONF_MODE_DONE;
2448 break;
2449
2450 case L2CAP_MODE_ERTM:
2451 pi->remote_tx_win = rfc.txwin_size;
2452 pi->remote_max_tx = rfc.max_transmit;
2453 pi->max_pdu_size = rfc.max_pdu_size;
2454
2455 rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
2456 rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
2457
2458 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002459
2460 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2461 sizeof(rfc), (unsigned long) &rfc);
2462
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002463 break;
2464
2465 case L2CAP_MODE_STREAMING:
2466 pi->remote_tx_win = rfc.txwin_size;
2467 pi->max_pdu_size = rfc.max_pdu_size;
2468
2469 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002470
2471 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2472 sizeof(rfc), (unsigned long) &rfc);
2473
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002474 break;
2475
2476 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002477 result = L2CAP_CONF_UNACCEPT;
2478
2479 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002480 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002481 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002482
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002483 if (result == L2CAP_CONF_SUCCESS)
2484 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
2485 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002486 rsp->scid = cpu_to_le16(pi->dcid);
2487 rsp->result = cpu_to_le16(result);
2488 rsp->flags = cpu_to_le16(0x0000);
2489
2490 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491}
2492
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002493static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
2494{
2495 struct l2cap_pinfo *pi = l2cap_pi(sk);
2496 struct l2cap_conf_req *req = data;
2497 void *ptr = req->data;
2498 int type, olen;
2499 unsigned long val;
2500 struct l2cap_conf_rfc rfc;
2501
2502 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
2503
2504 while (len >= L2CAP_CONF_OPT_SIZE) {
2505 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2506
2507 switch (type) {
2508 case L2CAP_CONF_MTU:
2509 if (val < L2CAP_DEFAULT_MIN_MTU) {
2510 *result = L2CAP_CONF_UNACCEPT;
2511 pi->omtu = L2CAP_DEFAULT_MIN_MTU;
2512 } else
2513 pi->omtu = val;
2514 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
2515 break;
2516
2517 case L2CAP_CONF_FLUSH_TO:
2518 pi->flush_to = val;
2519 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
2520 2, pi->flush_to);
2521 break;
2522
2523 case L2CAP_CONF_RFC:
2524 if (olen == sizeof(rfc))
2525 memcpy(&rfc, (void *)val, olen);
2526
2527 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
2528 rfc.mode != pi->mode)
2529 return -ECONNREFUSED;
2530
2531 pi->mode = rfc.mode;
2532 pi->fcs = 0;
2533
2534 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2535 sizeof(rfc), (unsigned long) &rfc);
2536 break;
2537 }
2538 }
2539
2540 if (*result == L2CAP_CONF_SUCCESS) {
2541 switch (rfc.mode) {
2542 case L2CAP_MODE_ERTM:
2543 pi->remote_tx_win = rfc.txwin_size;
2544 pi->retrans_timeout = rfc.retrans_timeout;
2545 pi->monitor_timeout = rfc.monitor_timeout;
2546 pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size);
2547 break;
2548 case L2CAP_MODE_STREAMING:
2549 pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size);
2550 break;
2551 }
2552 }
2553
2554 req->dcid = cpu_to_le16(pi->dcid);
2555 req->flags = cpu_to_le16(0x0000);
2556
2557 return ptr - data;
2558}
2559
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002560static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561{
2562 struct l2cap_conf_rsp *rsp = data;
2563 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002565 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002567 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002568 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002569 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
2571 return ptr - data;
2572}
2573
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002574static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2575{
2576 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2577
2578 if (rej->reason != 0x0000)
2579 return 0;
2580
2581 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2582 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002583 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002584
2585 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002586 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002587
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002588 l2cap_conn_start(conn);
2589 }
2590
2591 return 0;
2592}
2593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2595{
2596 struct l2cap_chan_list *list = &conn->chan_list;
2597 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2598 struct l2cap_conn_rsp rsp;
2599 struct sock *sk, *parent;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002600 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
2602 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002603 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
2605 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2606
2607 /* Check if we have socket listening on psm */
2608 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2609 if (!parent) {
2610 result = L2CAP_CR_BAD_PSM;
2611 goto sendresp;
2612 }
2613
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002614 /* Check if the ACL is secure enough (if not SDP) */
2615 if (psm != cpu_to_le16(0x0001) &&
2616 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002617 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002618 result = L2CAP_CR_SEC_BLOCK;
2619 goto response;
2620 }
2621
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 result = L2CAP_CR_NO_MEM;
2623
2624 /* Check for backlog size */
2625 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002626 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 goto response;
2628 }
2629
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002630 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 if (!sk)
2632 goto response;
2633
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002634 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636 /* Check if we already have channel with that dcid */
2637 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002638 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 sock_set_flag(sk, SOCK_ZAPPED);
2640 l2cap_sock_kill(sk);
2641 goto response;
2642 }
2643
2644 hci_conn_hold(conn->hcon);
2645
2646 l2cap_sock_init(sk, parent);
2647 bacpy(&bt_sk(sk)->src, conn->src);
2648 bacpy(&bt_sk(sk)->dst, conn->dst);
2649 l2cap_pi(sk)->psm = psm;
2650 l2cap_pi(sk)->dcid = scid;
2651
2652 __l2cap_chan_add(conn, sk, parent);
2653 dcid = l2cap_pi(sk)->scid;
2654
2655 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2656
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 l2cap_pi(sk)->ident = cmd->ident;
2658
Marcel Holtmann984947d2009-02-06 23:35:19 +01002659 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002660 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002661 if (bt_sk(sk)->defer_setup) {
2662 sk->sk_state = BT_CONNECT2;
2663 result = L2CAP_CR_PEND;
2664 status = L2CAP_CS_AUTHOR_PEND;
2665 parent->sk_data_ready(parent, 0);
2666 } else {
2667 sk->sk_state = BT_CONFIG;
2668 result = L2CAP_CR_SUCCESS;
2669 status = L2CAP_CS_NO_INFO;
2670 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002671 } else {
2672 sk->sk_state = BT_CONNECT2;
2673 result = L2CAP_CR_PEND;
2674 status = L2CAP_CS_AUTHEN_PEND;
2675 }
2676 } else {
2677 sk->sk_state = BT_CONNECT2;
2678 result = L2CAP_CR_PEND;
2679 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 }
2681
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002682 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
2684response:
2685 bh_unlock_sock(parent);
2686
2687sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002688 rsp.scid = cpu_to_le16(scid);
2689 rsp.dcid = cpu_to_le16(dcid);
2690 rsp.result = cpu_to_le16(result);
2691 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002693
2694 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2695 struct l2cap_info_req info;
2696 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2697
2698 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2699 conn->info_ident = l2cap_get_ident(conn);
2700
2701 mod_timer(&conn->info_timer, jiffies +
2702 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2703
2704 l2cap_send_cmd(conn, conn->info_ident,
2705 L2CAP_INFO_REQ, sizeof(info), &info);
2706 }
2707
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 return 0;
2709}
2710
2711static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2712{
2713 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2714 u16 scid, dcid, result, status;
2715 struct sock *sk;
2716 u8 req[128];
2717
2718 scid = __le16_to_cpu(rsp->scid);
2719 dcid = __le16_to_cpu(rsp->dcid);
2720 result = __le16_to_cpu(rsp->result);
2721 status = __le16_to_cpu(rsp->status);
2722
2723 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2724
2725 if (scid) {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002726 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2727 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 return 0;
2729 } else {
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002730 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2731 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 return 0;
2733 }
2734
2735 switch (result) {
2736 case L2CAP_CR_SUCCESS:
2737 sk->sk_state = BT_CONFIG;
2738 l2cap_pi(sk)->ident = 0;
2739 l2cap_pi(sk)->dcid = dcid;
2740 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2741
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002742 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2743
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2745 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002746 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 break;
2748
2749 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002750 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 break;
2752
2753 default:
2754 l2cap_chan_del(sk, ECONNREFUSED);
2755 break;
2756 }
2757
2758 bh_unlock_sock(sk);
2759 return 0;
2760}
2761
Al Viro88219a02007-07-29 00:17:25 -07002762static 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 -07002763{
2764 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2765 u16 dcid, flags;
2766 u8 rsp[64];
2767 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002768 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
2770 dcid = __le16_to_cpu(req->dcid);
2771 flags = __le16_to_cpu(req->flags);
2772
2773 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2774
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002775 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2776 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 return -ENOENT;
2778
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002779 if (sk->sk_state == BT_DISCONN)
2780 goto unlock;
2781
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002782 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002783 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002784 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2785 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2786 l2cap_build_conf_rsp(sk, rsp,
2787 L2CAP_CONF_REJECT, flags), rsp);
2788 goto unlock;
2789 }
2790
2791 /* Store config. */
2792 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2793 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
2795 if (flags & 0x0001) {
2796 /* Incomplete config. Send empty response. */
2797 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002798 l2cap_build_conf_rsp(sk, rsp,
2799 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 goto unlock;
2801 }
2802
2803 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002804 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002805 if (len < 0) {
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002806 l2cap_send_disconn_req(conn, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002810 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002811 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002812
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002813 /* Reset config buffer. */
2814 l2cap_pi(sk)->conf_len = 0;
2815
Marcel Holtmann876d9482007-10-20 13:35:42 +02002816 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2817 goto unlock;
2818
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Joe Perchesf64f9e72009-11-29 16:55:45 -08002820 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
2821 l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002822 l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
2823
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002825
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002826 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002827 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002828 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002829 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2830 l2cap_ertm_init(sk);
2831
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002833 goto unlock;
2834 }
2835
2836 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002837 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002839 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002840 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 }
2842
2843unlock:
2844 bh_unlock_sock(sk);
2845 return 0;
2846}
2847
2848static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2849{
2850 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2851 u16 scid, flags, result;
2852 struct sock *sk;
2853
2854 scid = __le16_to_cpu(rsp->scid);
2855 flags = __le16_to_cpu(rsp->flags);
2856 result = __le16_to_cpu(rsp->result);
2857
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002858 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2859 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002861 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2862 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 return 0;
2864
2865 switch (result) {
2866 case L2CAP_CONF_SUCCESS:
2867 break;
2868
2869 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002870 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
2871 int len = cmd->len - sizeof(*rsp);
2872 char req[64];
2873
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002874 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
2875 l2cap_send_disconn_req(conn, sk);
2876 goto done;
2877 }
2878
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002879 /* throw out any old stored conf requests */
2880 result = L2CAP_CONF_SUCCESS;
2881 len = l2cap_parse_conf_rsp(sk, rsp->data,
2882 len, req, &result);
2883 if (len < 0) {
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002884 l2cap_send_disconn_req(conn, sk);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002885 goto done;
2886 }
2887
2888 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2889 L2CAP_CONF_REQ, len, req);
2890 l2cap_pi(sk)->num_conf_req++;
2891 if (result != L2CAP_CONF_SUCCESS)
2892 goto done;
2893 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 }
2895
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002896 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 sk->sk_state = BT_DISCONN;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002898 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03002900 l2cap_send_disconn_req(conn, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 goto done;
2902 }
2903
2904 if (flags & 0x01)
2905 goto done;
2906
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2908
2909 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Joe Perchesf64f9e72009-11-29 16:55:45 -08002910 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
2911 l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002912 l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
2913
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002915 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002916 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002917 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002918 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2919 l2cap_ertm_init(sk);
2920
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 l2cap_chan_ready(sk);
2922 }
2923
2924done:
2925 bh_unlock_sock(sk);
2926 return 0;
2927}
2928
2929static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2930{
2931 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2932 struct l2cap_disconn_rsp rsp;
2933 u16 dcid, scid;
2934 struct sock *sk;
2935
2936 scid = __le16_to_cpu(req->scid);
2937 dcid = __le16_to_cpu(req->dcid);
2938
2939 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2940
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002941 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2942 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 return 0;
2944
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002945 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2946 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2948
2949 sk->sk_shutdown = SHUTDOWN_MASK;
2950
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002951 skb_queue_purge(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002952
2953 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
2954 skb_queue_purge(SREJ_QUEUE(sk));
2955 del_timer(&l2cap_pi(sk)->retrans_timer);
2956 del_timer(&l2cap_pi(sk)->monitor_timer);
2957 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002958
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 l2cap_chan_del(sk, ECONNRESET);
2960 bh_unlock_sock(sk);
2961
2962 l2cap_sock_kill(sk);
2963 return 0;
2964}
2965
2966static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2967{
2968 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2969 u16 dcid, scid;
2970 struct sock *sk;
2971
2972 scid = __le16_to_cpu(rsp->scid);
2973 dcid = __le16_to_cpu(rsp->dcid);
2974
2975 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2976
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002977 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2978 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 return 0;
2980
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002981 skb_queue_purge(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002982
2983 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
2984 skb_queue_purge(SREJ_QUEUE(sk));
2985 del_timer(&l2cap_pi(sk)->retrans_timer);
2986 del_timer(&l2cap_pi(sk)->monitor_timer);
2987 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002988
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 l2cap_chan_del(sk, 0);
2990 bh_unlock_sock(sk);
2991
2992 l2cap_sock_kill(sk);
2993 return 0;
2994}
2995
2996static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2997{
2998 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 u16 type;
3000
3001 type = __le16_to_cpu(req->type);
3002
3003 BT_DBG("type 0x%4.4x", type);
3004
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003005 if (type == L2CAP_IT_FEAT_MASK) {
3006 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003007 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003008 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3009 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3010 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003011 if (enable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003012 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3013 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003014 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003015 l2cap_send_cmd(conn, cmd->ident,
3016 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003017 } else if (type == L2CAP_IT_FIXED_CHAN) {
3018 u8 buf[12];
3019 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3020 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3021 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3022 memcpy(buf + 4, l2cap_fixed_chan, 8);
3023 l2cap_send_cmd(conn, cmd->ident,
3024 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003025 } else {
3026 struct l2cap_info_rsp rsp;
3027 rsp.type = cpu_to_le16(type);
3028 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3029 l2cap_send_cmd(conn, cmd->ident,
3030 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
3033 return 0;
3034}
3035
3036static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3037{
3038 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3039 u16 type, result;
3040
3041 type = __le16_to_cpu(rsp->type);
3042 result = __le16_to_cpu(rsp->result);
3043
3044 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3045
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003046 del_timer(&conn->info_timer);
3047
Marcel Holtmann984947d2009-02-06 23:35:19 +01003048 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003049 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003050
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003051 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003052 struct l2cap_info_req req;
3053 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3054
3055 conn->info_ident = l2cap_get_ident(conn);
3056
3057 l2cap_send_cmd(conn, conn->info_ident,
3058 L2CAP_INFO_REQ, sizeof(req), &req);
3059 } else {
3060 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3061 conn->info_ident = 0;
3062
3063 l2cap_conn_start(conn);
3064 }
3065 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003066 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003067 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003068
3069 l2cap_conn_start(conn);
3070 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003071
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 return 0;
3073}
3074
3075static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
3076{
3077 u8 *data = skb->data;
3078 int len = skb->len;
3079 struct l2cap_cmd_hdr cmd;
3080 int err = 0;
3081
3082 l2cap_raw_recv(conn, skb);
3083
3084 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003085 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3087 data += L2CAP_CMD_HDR_SIZE;
3088 len -= L2CAP_CMD_HDR_SIZE;
3089
Al Viro88219a02007-07-29 00:17:25 -07003090 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091
Al Viro88219a02007-07-29 00:17:25 -07003092 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 -07003093
Al Viro88219a02007-07-29 00:17:25 -07003094 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 BT_DBG("corrupted command");
3096 break;
3097 }
3098
3099 switch (cmd.code) {
3100 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003101 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 break;
3103
3104 case L2CAP_CONN_REQ:
3105 err = l2cap_connect_req(conn, &cmd, data);
3106 break;
3107
3108 case L2CAP_CONN_RSP:
3109 err = l2cap_connect_rsp(conn, &cmd, data);
3110 break;
3111
3112 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003113 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 break;
3115
3116 case L2CAP_CONF_RSP:
3117 err = l2cap_config_rsp(conn, &cmd, data);
3118 break;
3119
3120 case L2CAP_DISCONN_REQ:
3121 err = l2cap_disconnect_req(conn, &cmd, data);
3122 break;
3123
3124 case L2CAP_DISCONN_RSP:
3125 err = l2cap_disconnect_rsp(conn, &cmd, data);
3126 break;
3127
3128 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07003129 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 break;
3131
3132 case L2CAP_ECHO_RSP:
3133 break;
3134
3135 case L2CAP_INFO_REQ:
3136 err = l2cap_information_req(conn, &cmd, data);
3137 break;
3138
3139 case L2CAP_INFO_RSP:
3140 err = l2cap_information_rsp(conn, &cmd, data);
3141 break;
3142
3143 default:
3144 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
3145 err = -EINVAL;
3146 break;
3147 }
3148
3149 if (err) {
3150 struct l2cap_cmd_rej rej;
3151 BT_DBG("error %d", err);
3152
3153 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003154 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3156 }
3157
Al Viro88219a02007-07-29 00:17:25 -07003158 data += cmd_len;
3159 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 }
3161
3162 kfree_skb(skb);
3163}
3164
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003165static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3166{
3167 u16 our_fcs, rcv_fcs;
3168 int hdr_size = L2CAP_HDR_SIZE + 2;
3169
3170 if (pi->fcs == L2CAP_FCS_CRC16) {
3171 skb_trim(skb, skb->len - 2);
3172 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3173 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3174
3175 if (our_fcs != rcv_fcs)
3176 return -EINVAL;
3177 }
3178 return 0;
3179}
3180
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003181static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3182{
3183 struct l2cap_pinfo *pi = l2cap_pi(sk);
3184 u16 control = 0;
3185
3186 pi->frames_sent = 0;
3187 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3188
3189 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3190
3191 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3192 control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
3193 l2cap_send_sframe(pi, control);
3194 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
3195 }
3196
3197 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
3198 __mod_retrans_timer();
3199
3200 l2cap_ertm_send(sk);
3201
3202 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3203 pi->frames_sent == 0) {
3204 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003205 l2cap_send_sframe(pi, control);
3206 }
3207}
3208
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003209static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
3210{
3211 struct sk_buff *next_skb;
3212
3213 bt_cb(skb)->tx_seq = tx_seq;
3214 bt_cb(skb)->sar = sar;
3215
3216 next_skb = skb_peek(SREJ_QUEUE(sk));
3217 if (!next_skb) {
3218 __skb_queue_tail(SREJ_QUEUE(sk), skb);
3219 return;
3220 }
3221
3222 do {
3223 if (bt_cb(next_skb)->tx_seq > tx_seq) {
3224 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
3225 return;
3226 }
3227
3228 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
3229 break;
3230
3231 } while((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
3232
3233 __skb_queue_tail(SREJ_QUEUE(sk), skb);
3234}
3235
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003236static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3237{
3238 struct l2cap_pinfo *pi = l2cap_pi(sk);
3239 struct sk_buff *_skb;
3240 int err = -EINVAL;
3241
3242 switch (control & L2CAP_CTRL_SAR) {
3243 case L2CAP_SDU_UNSEGMENTED:
3244 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3245 kfree_skb(pi->sdu);
3246 break;
3247 }
3248
3249 err = sock_queue_rcv_skb(sk, skb);
3250 if (!err)
3251 return 0;
3252
3253 break;
3254
3255 case L2CAP_SDU_START:
3256 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3257 kfree_skb(pi->sdu);
3258 break;
3259 }
3260
3261 pi->sdu_len = get_unaligned_le16(skb->data);
3262 skb_pull(skb, 2);
3263
3264 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3265 if (!pi->sdu) {
3266 err = -ENOMEM;
3267 break;
3268 }
3269
3270 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3271
3272 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3273 pi->partial_sdu_len = skb->len;
3274 err = 0;
3275 break;
3276
3277 case L2CAP_SDU_CONTINUE:
3278 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3279 break;
3280
3281 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3282
3283 pi->partial_sdu_len += skb->len;
3284 if (pi->partial_sdu_len > pi->sdu_len)
3285 kfree_skb(pi->sdu);
3286 else
3287 err = 0;
3288
3289 break;
3290
3291 case L2CAP_SDU_END:
3292 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3293 break;
3294
3295 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3296
3297 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3298 pi->partial_sdu_len += skb->len;
3299
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003300 if (pi->partial_sdu_len > pi->imtu)
3301 goto drop;
3302
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003303 if (pi->partial_sdu_len == pi->sdu_len) {
3304 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3305 err = sock_queue_rcv_skb(sk, _skb);
3306 if (err < 0)
3307 kfree_skb(_skb);
3308 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003309 err = 0;
3310
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003311drop:
3312 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003313 break;
3314 }
3315
3316 kfree_skb(skb);
3317 return err;
3318}
3319
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003320static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3321{
3322 struct sk_buff *skb;
3323 u16 control = 0;
3324
3325 while((skb = skb_peek(SREJ_QUEUE(sk)))) {
3326 if (bt_cb(skb)->tx_seq != tx_seq)
3327 break;
3328
3329 skb = skb_dequeue(SREJ_QUEUE(sk));
3330 control |= bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3331 l2cap_sar_reassembly_sdu(sk, skb, control);
3332 l2cap_pi(sk)->buffer_seq_srej =
3333 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
3334 tx_seq++;
3335 }
3336}
3337
3338static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3339{
3340 struct l2cap_pinfo *pi = l2cap_pi(sk);
3341 struct srej_list *l, *tmp;
3342 u16 control;
3343
3344 list_for_each_entry_safe(l,tmp, SREJ_LIST(sk), list) {
3345 if (l->tx_seq == tx_seq) {
3346 list_del(&l->list);
3347 kfree(l);
3348 return;
3349 }
3350 control = L2CAP_SUPER_SELECT_REJECT;
3351 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3352 l2cap_send_sframe(pi, control);
3353 list_del(&l->list);
3354 list_add_tail(&l->list, SREJ_LIST(sk));
3355 }
3356}
3357
3358static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3359{
3360 struct l2cap_pinfo *pi = l2cap_pi(sk);
3361 struct srej_list *new;
3362 u16 control;
3363
3364 while (tx_seq != pi->expected_tx_seq) {
3365 control = L2CAP_SUPER_SELECT_REJECT;
3366 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003367 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
3368 control |= L2CAP_CTRL_POLL;
3369 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
3370 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003371 l2cap_send_sframe(pi, control);
3372
3373 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
3374 new->tx_seq = pi->expected_tx_seq++;
3375 list_add_tail(&new->list, SREJ_LIST(sk));
3376 }
3377 pi->expected_tx_seq++;
3378}
3379
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3381{
3382 struct l2cap_pinfo *pi = l2cap_pi(sk);
3383 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003384 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003385 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003386 int err = 0;
3387
3388 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3389
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003390 if (L2CAP_CTRL_FINAL & rx_control) {
3391 del_timer(&pi->monitor_timer);
3392 if (pi->unacked_frames > 0)
3393 __mod_retrans_timer();
3394 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3395 }
3396
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003397 pi->expected_ack_seq = req_seq;
3398 l2cap_drop_acked_frames(sk);
3399
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003400 if (tx_seq == pi->expected_tx_seq)
3401 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003402
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003403 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3404 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003405
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003406 first = list_first_entry(SREJ_LIST(sk),
3407 struct srej_list, list);
3408 if (tx_seq == first->tx_seq) {
3409 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3410 l2cap_check_srej_gap(sk, tx_seq);
3411
3412 list_del(&first->list);
3413 kfree(first);
3414
3415 if (list_empty(SREJ_LIST(sk))) {
3416 pi->buffer_seq = pi->buffer_seq_srej;
3417 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3418 }
3419 } else {
3420 struct srej_list *l;
3421 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3422
3423 list_for_each_entry(l, SREJ_LIST(sk), list) {
3424 if (l->tx_seq == tx_seq) {
3425 l2cap_resend_srejframe(sk, tx_seq);
3426 return 0;
3427 }
3428 }
3429 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003430 }
3431 } else {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003432 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003433
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003434 INIT_LIST_HEAD(SREJ_LIST(sk));
3435 pi->buffer_seq_srej = pi->buffer_seq;
3436
3437 __skb_queue_head_init(SREJ_QUEUE(sk));
3438 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3439
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003440 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3441
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003442 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003443 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003444 return 0;
3445
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003446expected:
3447 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3448
3449 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3450 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3451 return 0;
3452 }
3453
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003454 if (rx_control & L2CAP_CTRL_FINAL) {
3455 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3456 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3457 else {
3458 sk->sk_send_head = TX_QUEUE(sk)->next;
3459 pi->next_tx_seq = pi->expected_ack_seq;
3460 l2cap_ertm_send(sk);
3461 }
3462 }
3463
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003464 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3465
3466 err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
3467 if (err < 0)
3468 return err;
3469
3470 pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003471 if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
3472 l2cap_send_ack(pi);
3473
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003474 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003475}
3476
3477static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3478{
3479 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003480 u8 tx_seq = __get_reqseq(rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003481
3482 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3483
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003484 if (L2CAP_CTRL_FINAL & rx_control) {
3485 del_timer(&pi->monitor_timer);
3486 if (pi->unacked_frames > 0)
3487 __mod_retrans_timer();
3488 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3489 }
3490
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003491 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3492 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03003493 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003494 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003495 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3496
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03003497 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003498 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovanca42a612009-08-26 04:04:01 -03003499 pi->expected_ack_seq = tx_seq;
3500 l2cap_drop_acked_frames(sk);
3501
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003502 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3503 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3504 else {
3505 sk->sk_send_head = TX_QUEUE(sk)->next;
3506 pi->next_tx_seq = pi->expected_ack_seq;
3507 l2cap_ertm_send(sk);
3508 }
3509
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03003510 } else {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003511 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03003512 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003513
Joe Perchesf64f9e72009-11-29 16:55:45 -08003514 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3515 (pi->unacked_frames > 0))
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03003516 __mod_retrans_timer();
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003517
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003518 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan186de9a2009-12-15 15:56:34 -02003519 l2cap_ertm_send(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03003520 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003521 break;
3522
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003524 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3525
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003526 pi->expected_ack_seq = __get_reqseq(rx_control);
3527 l2cap_drop_acked_frames(sk);
3528
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003529 if (rx_control & L2CAP_CTRL_FINAL) {
3530 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3531 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3532 else {
3533 sk->sk_send_head = TX_QUEUE(sk)->next;
3534 pi->next_tx_seq = pi->expected_ack_seq;
3535 l2cap_ertm_send(sk);
3536 }
3537 } else {
3538 sk->sk_send_head = TX_QUEUE(sk)->next;
3539 pi->next_tx_seq = pi->expected_ack_seq;
3540 l2cap_ertm_send(sk);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003541
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003542 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3543 pi->srej_save_reqseq = tx_seq;
3544 pi->conn_state |= L2CAP_CONN_REJ_ACT;
3545 }
3546 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003547
3548 break;
3549
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003550 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003551 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3552
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003553 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003554 pi->expected_ack_seq = tx_seq;
3555 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan186ee8c2009-12-15 20:13:27 -02003556 l2cap_retransmit_frame(sk, tx_seq);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003557 l2cap_ertm_send(sk);
3558 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3559 pi->srej_save_reqseq = tx_seq;
3560 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3561 }
3562 } else if (rx_control & L2CAP_CTRL_FINAL) {
3563 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3564 pi->srej_save_reqseq == tx_seq)
Gustavo F. Padovan889a3ca2009-10-03 02:34:37 -03003565 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003566 else
3567 l2cap_retransmit_frame(sk, tx_seq);
3568 }
3569 else {
3570 l2cap_retransmit_frame(sk, tx_seq);
3571 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3572 pi->srej_save_reqseq = tx_seq;
3573 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3574 }
3575 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003576 break;
3577
3578 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003579 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3580 pi->expected_ack_seq = tx_seq;
3581 l2cap_drop_acked_frames(sk);
3582
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003583 del_timer(&pi->retrans_timer);
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003584 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -03003585 u16 control = L2CAP_CTRL_FINAL;
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003586 l2cap_send_rr_or_rnr(pi, control);
Gustavo F. Padovan2246b2f2009-08-26 04:04:02 -03003587 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003588 break;
3589 }
3590
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003591 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003592 return 0;
3593}
3594
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3596{
3597 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003598 struct l2cap_pinfo *pi;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003599 u16 control, len;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003600 u8 tx_seq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601
3602 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3603 if (!sk) {
3604 BT_DBG("unknown cid 0x%4.4x", cid);
3605 goto drop;
3606 }
3607
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003608 pi = l2cap_pi(sk);
3609
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610 BT_DBG("sk %p, len %d", sk, skb->len);
3611
3612 if (sk->sk_state != BT_CONNECTED)
3613 goto drop;
3614
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003615 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003616 case L2CAP_MODE_BASIC:
3617 /* If socket recv buffers overflows we drop data here
3618 * which is *bad* because L2CAP has to be reliable.
3619 * But we don't have any other choice. L2CAP doesn't
3620 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003622 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003623 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003625 if (!sock_queue_rcv_skb(sk, skb))
3626 goto done;
3627 break;
3628
3629 case L2CAP_MODE_ERTM:
3630 control = get_unaligned_le16(skb->data);
3631 skb_pull(skb, 2);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003632 len = skb->len;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003633
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003634 if (__is_sar_start(control))
3635 len -= 2;
3636
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003637 if (pi->fcs == L2CAP_FCS_CRC16)
3638 len -= 2;
3639
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003640 /*
3641 * We can just drop the corrupted I-frame here.
3642 * Receiver will miss it and start proper recovery
3643 * procedures and ask retransmission.
3644 */
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003645 if (len > L2CAP_DEFAULT_MAX_PDU_SIZE)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003646 goto drop;
3647
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003648 if (l2cap_check_fcs(pi, skb))
3649 goto drop;
3650
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003651 if (__is_iframe(control)) {
3652 if (len < 4)
3653 goto drop;
3654
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003655 l2cap_data_channel_iframe(sk, control, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003656 } else {
3657 if (len != 0)
3658 goto drop;
3659
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003660 l2cap_data_channel_sframe(sk, control, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003661 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003662
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003663 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003664
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665 case L2CAP_MODE_STREAMING:
3666 control = get_unaligned_le16(skb->data);
3667 skb_pull(skb, 2);
3668 len = skb->len;
3669
3670 if (__is_sar_start(control))
3671 len -= 2;
3672
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003673 if (pi->fcs == L2CAP_FCS_CRC16)
3674 len -= 2;
3675
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003676 if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || len < 4
3677 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003678 goto drop;
3679
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003680 if (l2cap_check_fcs(pi, skb))
3681 goto drop;
3682
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003683 tx_seq = __get_txseq(control);
3684
3685 if (pi->expected_tx_seq == tx_seq)
3686 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3687 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003688 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003689
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003690 l2cap_sar_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003691
3692 goto done;
3693
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003694 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003695 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003696 break;
3697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
3699drop:
3700 kfree_skb(skb);
3701
3702done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003703 if (sk)
3704 bh_unlock_sock(sk);
3705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 return 0;
3707}
3708
Al Viro8e036fc2007-07-29 00:16:36 -07003709static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710{
3711 struct sock *sk;
3712
3713 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3714 if (!sk)
3715 goto drop;
3716
3717 BT_DBG("sk %p, len %d", sk, skb->len);
3718
3719 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3720 goto drop;
3721
3722 if (l2cap_pi(sk)->imtu < skb->len)
3723 goto drop;
3724
3725 if (!sock_queue_rcv_skb(sk, skb))
3726 goto done;
3727
3728drop:
3729 kfree_skb(skb);
3730
3731done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003732 if (sk)
3733 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 return 0;
3735}
3736
3737static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3738{
3739 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003740 u16 cid, len;
3741 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
3743 skb_pull(skb, L2CAP_HDR_SIZE);
3744 cid = __le16_to_cpu(lh->cid);
3745 len = __le16_to_cpu(lh->len);
3746
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003747 if (len != skb->len) {
3748 kfree_skb(skb);
3749 return;
3750 }
3751
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3753
3754 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003755 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 l2cap_sig_channel(conn, skb);
3757 break;
3758
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003759 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003760 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 skb_pull(skb, 2);
3762 l2cap_conless_channel(conn, psm, skb);
3763 break;
3764
3765 default:
3766 l2cap_data_channel(conn, cid, skb);
3767 break;
3768 }
3769}
3770
3771/* ---- L2CAP interface with lower layer (HCI) ---- */
3772
3773static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3774{
3775 int exact = 0, lm1 = 0, lm2 = 0;
3776 register struct sock *sk;
3777 struct hlist_node *node;
3778
3779 if (type != ACL_LINK)
3780 return 0;
3781
3782 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3783
3784 /* Find listening sockets and check their link_mode */
3785 read_lock(&l2cap_sk_list.lock);
3786 sk_for_each(sk, node, &l2cap_sk_list.head) {
3787 if (sk->sk_state != BT_LISTEN)
3788 continue;
3789
3790 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003791 lm1 |= HCI_LM_ACCEPT;
3792 if (l2cap_pi(sk)->role_switch)
3793 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003795 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3796 lm2 |= HCI_LM_ACCEPT;
3797 if (l2cap_pi(sk)->role_switch)
3798 lm2 |= HCI_LM_MASTER;
3799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 }
3801 read_unlock(&l2cap_sk_list.lock);
3802
3803 return exact ? lm1 : lm2;
3804}
3805
3806static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3807{
Marcel Holtmann01394182006-07-03 10:02:46 +02003808 struct l2cap_conn *conn;
3809
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3811
3812 if (hcon->type != ACL_LINK)
3813 return 0;
3814
3815 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 conn = l2cap_conn_add(hcon, status);
3817 if (conn)
3818 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003819 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 l2cap_conn_del(hcon, bt_err(status));
3821
3822 return 0;
3823}
3824
Marcel Holtmann2950f212009-02-12 14:02:50 +01003825static int l2cap_disconn_ind(struct hci_conn *hcon)
3826{
3827 struct l2cap_conn *conn = hcon->l2cap_data;
3828
3829 BT_DBG("hcon %p", hcon);
3830
3831 if (hcon->type != ACL_LINK || !conn)
3832 return 0x13;
3833
3834 return conn->disc_reason;
3835}
3836
3837static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838{
3839 BT_DBG("hcon %p reason %d", hcon, reason);
3840
3841 if (hcon->type != ACL_LINK)
3842 return 0;
3843
3844 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003845
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 return 0;
3847}
3848
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003849static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3850{
Marcel Holtmann255c7602009-02-04 21:07:19 +01003851 if (sk->sk_type != SOCK_SEQPACKET)
3852 return;
3853
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003854 if (encrypt == 0x00) {
3855 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3856 l2cap_sock_clear_timer(sk);
3857 l2cap_sock_set_timer(sk, HZ * 5);
3858 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3859 __l2cap_sock_close(sk, ECONNREFUSED);
3860 } else {
3861 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3862 l2cap_sock_clear_timer(sk);
3863 }
3864}
3865
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003866static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867{
3868 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003869 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
Marcel Holtmann01394182006-07-03 10:02:46 +02003872 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003874
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 l = &conn->chan_list;
3876
3877 BT_DBG("conn %p", conn);
3878
3879 read_lock(&l->lock);
3880
3881 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3882 bh_lock_sock(sk);
3883
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003884 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3885 bh_unlock_sock(sk);
3886 continue;
3887 }
3888
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003889 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003890 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003891 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003892 bh_unlock_sock(sk);
3893 continue;
3894 }
3895
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003896 if (sk->sk_state == BT_CONNECT) {
3897 if (!status) {
3898 struct l2cap_conn_req req;
3899 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3900 req.psm = l2cap_pi(sk)->psm;
3901
3902 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
3903
3904 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3905 L2CAP_CONN_REQ, sizeof(req), &req);
3906 } else {
3907 l2cap_sock_clear_timer(sk);
3908 l2cap_sock_set_timer(sk, HZ / 10);
3909 }
3910 } else if (sk->sk_state == BT_CONNECT2) {
3911 struct l2cap_conn_rsp rsp;
3912 __u16 result;
3913
3914 if (!status) {
3915 sk->sk_state = BT_CONFIG;
3916 result = L2CAP_CR_SUCCESS;
3917 } else {
3918 sk->sk_state = BT_DISCONN;
3919 l2cap_sock_set_timer(sk, HZ / 10);
3920 result = L2CAP_CR_SEC_BLOCK;
3921 }
3922
3923 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3924 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3925 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003926 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003927 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3928 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 }
3930
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 bh_unlock_sock(sk);
3932 }
3933
3934 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003935
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 return 0;
3937}
3938
3939static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3940{
3941 struct l2cap_conn *conn = hcon->l2cap_data;
3942
3943 if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
3944 goto drop;
3945
3946 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3947
3948 if (flags & ACL_START) {
3949 struct l2cap_hdr *hdr;
3950 int len;
3951
3952 if (conn->rx_len) {
3953 BT_ERR("Unexpected start frame (len %d)", skb->len);
3954 kfree_skb(conn->rx_skb);
3955 conn->rx_skb = NULL;
3956 conn->rx_len = 0;
3957 l2cap_conn_unreliable(conn, ECOMM);
3958 }
3959
3960 if (skb->len < 2) {
3961 BT_ERR("Frame is too short (len %d)", skb->len);
3962 l2cap_conn_unreliable(conn, ECOMM);
3963 goto drop;
3964 }
3965
3966 hdr = (struct l2cap_hdr *) skb->data;
3967 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
3968
3969 if (len == skb->len) {
3970 /* Complete frame received */
3971 l2cap_recv_frame(conn, skb);
3972 return 0;
3973 }
3974
3975 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3976
3977 if (skb->len > len) {
3978 BT_ERR("Frame is too long (len %d, expected len %d)",
3979 skb->len, len);
3980 l2cap_conn_unreliable(conn, ECOMM);
3981 goto drop;
3982 }
3983
3984 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003985 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3986 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 goto drop;
3988
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003989 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003990 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 conn->rx_len = len - skb->len;
3992 } else {
3993 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3994
3995 if (!conn->rx_len) {
3996 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3997 l2cap_conn_unreliable(conn, ECOMM);
3998 goto drop;
3999 }
4000
4001 if (skb->len > conn->rx_len) {
4002 BT_ERR("Fragment is too long (len %d, expected %d)",
4003 skb->len, conn->rx_len);
4004 kfree_skb(conn->rx_skb);
4005 conn->rx_skb = NULL;
4006 conn->rx_len = 0;
4007 l2cap_conn_unreliable(conn, ECOMM);
4008 goto drop;
4009 }
4010
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004011 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004012 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 conn->rx_len -= skb->len;
4014
4015 if (!conn->rx_len) {
4016 /* Complete frame received */
4017 l2cap_recv_frame(conn, conn->rx_skb);
4018 conn->rx_skb = NULL;
4019 }
4020 }
4021
4022drop:
4023 kfree_skb(skb);
4024 return 0;
4025}
4026
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004027static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028{
4029 struct sock *sk;
4030 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
4032 read_lock_bh(&l2cap_sk_list.lock);
4033
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004034 sk_for_each(sk, node, &l2cap_sk_list.head) {
4035 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004037 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
4038 batostr(&bt_sk(sk)->src),
4039 batostr(&bt_sk(sk)->dst),
4040 sk->sk_state, __le16_to_cpu(pi->psm),
4041 pi->scid, pi->dcid,
4042 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004046
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004047 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048}
4049
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004050static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4051{
4052 return single_open(file, l2cap_debugfs_show, inode->i_private);
4053}
4054
4055static const struct file_operations l2cap_debugfs_fops = {
4056 .open = l2cap_debugfs_open,
4057 .read = seq_read,
4058 .llseek = seq_lseek,
4059 .release = single_release,
4060};
4061
4062static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08004064static const struct proto_ops l2cap_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 .family = PF_BLUETOOTH,
4066 .owner = THIS_MODULE,
4067 .release = l2cap_sock_release,
4068 .bind = l2cap_sock_bind,
4069 .connect = l2cap_sock_connect,
4070 .listen = l2cap_sock_listen,
4071 .accept = l2cap_sock_accept,
4072 .getname = l2cap_sock_getname,
4073 .sendmsg = l2cap_sock_sendmsg,
Marcel Holtmannf66dc812009-01-15 21:57:00 +01004074 .recvmsg = l2cap_sock_recvmsg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02004076 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 .mmap = sock_no_mmap,
4078 .socketpair = sock_no_socketpair,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 .shutdown = l2cap_sock_shutdown,
4080 .setsockopt = l2cap_sock_setsockopt,
4081 .getsockopt = l2cap_sock_getsockopt
4082};
4083
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00004084static const struct net_proto_family l2cap_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 .family = PF_BLUETOOTH,
4086 .owner = THIS_MODULE,
4087 .create = l2cap_sock_create,
4088};
4089
4090static struct hci_proto l2cap_hci_proto = {
4091 .name = "L2CAP",
4092 .id = HCI_PROTO_L2CAP,
4093 .connect_ind = l2cap_connect_ind,
4094 .connect_cfm = l2cap_connect_cfm,
4095 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004096 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004097 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 .recv_acldata = l2cap_recv_acldata
4099};
4100
4101static int __init l2cap_init(void)
4102{
4103 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004104
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 err = proto_register(&l2cap_proto, 0);
4106 if (err < 0)
4107 return err;
4108
4109 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4110 if (err < 0) {
4111 BT_ERR("L2CAP socket registration failed");
4112 goto error;
4113 }
4114
4115 err = hci_register_proto(&l2cap_hci_proto);
4116 if (err < 0) {
4117 BT_ERR("L2CAP protocol registration failed");
4118 bt_sock_unregister(BTPROTO_L2CAP);
4119 goto error;
4120 }
4121
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004122 if (bt_debugfs) {
4123 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4124 bt_debugfs, NULL, &l2cap_debugfs_fops);
4125 if (!l2cap_debugfs)
4126 BT_ERR("Failed to create L2CAP debug file");
4127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
4129 BT_INFO("L2CAP ver %s", VERSION);
4130 BT_INFO("L2CAP socket layer initialized");
4131
4132 return 0;
4133
4134error:
4135 proto_unregister(&l2cap_proto);
4136 return err;
4137}
4138
4139static void __exit l2cap_exit(void)
4140{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004141 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142
4143 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4144 BT_ERR("L2CAP socket unregistration failed");
4145
4146 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4147 BT_ERR("L2CAP protocol unregistration failed");
4148
4149 proto_unregister(&l2cap_proto);
4150}
4151
4152void l2cap_load(void)
4153{
4154 /* Dummy function to trigger automatic L2CAP module loading by
4155 * other modules that use L2CAP sockets but don't use any other
4156 * symbols from it. */
4157 return;
4158}
4159EXPORT_SYMBOL(l2cap_load);
4160
4161module_init(l2cap_init);
4162module_exit(l2cap_exit);
4163
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07004164module_param(enable_ertm, bool, 0644);
4165MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
4166
Marcel Holtmann5fbcd3d2009-10-05 11:35:43 +02004167module_param(max_transmit, uint, 0644);
4168MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)");
4169
Marcel Holtmann63fbd242008-08-18 13:23:53 +02004170MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
4172MODULE_VERSION(VERSION);
4173MODULE_LICENSE("GPL");
4174MODULE_ALIAS("bt-proto-0");