blob: f5d9573285458b5dba2ff61a680e8aec812356e0 [file] [log] [blame]
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
4 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
5 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
18 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
25 SOFTWARE IS DISCLAIMED.
26*/
27
28/* Bluetooth L2CAP sockets. */
29
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040030#include <linux/export.h>
Paul Moore6230c9b2011-10-07 09:40:59 +000031
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020032#include <net/bluetooth/bluetooth.h>
Gustavo F. Padovan33575df2011-02-04 02:48:48 -020033#include <net/bluetooth/hci_core.h>
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020034#include <net/bluetooth/l2cap.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
36#include "smp.h"
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020037
Masatake YAMATO5b28d952012-07-26 01:29:25 +090038static struct bt_sock_list l2cap_sk_list = {
39 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
40};
41
Gustavo F. Padovancf2f90f2011-04-27 18:40:39 -030042static const struct proto_ops l2cap_sock_ops;
Gustavo F. Padovan80808e42011-05-16 17:24:37 -030043static void l2cap_sock_init(struct sock *sk, struct sock *parent);
Gustavo Padovan2d792812012-10-06 10:07:01 +010044static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
45 int proto, gfp_t prio);
Gustavo F. Padovancf2f90f2011-04-27 18:40:39 -030046
David Herrmannb3916db2013-04-05 14:57:34 +020047bool l2cap_is_socket(struct socket *sock)
48{
49 return sock && sock->ops == &l2cap_sock_ops;
50}
51EXPORT_SYMBOL(l2cap_is_socket);
52
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -020053static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
54{
55 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -030056 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -020057 struct sockaddr_l2 la;
58 int len, err = 0;
59
60 BT_DBG("sk %p", sk);
61
62 if (!addr || addr->sa_family != AF_BLUETOOTH)
63 return -EINVAL;
64
65 memset(&la, 0, sizeof(la));
66 len = min_t(unsigned int, sizeof(la), alen);
67 memcpy(&la, addr, len);
68
Ville Tervob62f3282011-02-10 22:38:50 -030069 if (la.l2_cid && la.l2_psm)
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -020070 return -EINVAL;
71
72 lock_sock(sk);
73
74 if (sk->sk_state != BT_OPEN) {
75 err = -EBADFD;
76 goto done;
77 }
78
79 if (la.l2_psm) {
80 __u16 psm = __le16_to_cpu(la.l2_psm);
81
82 /* PSM must be odd and lsb of upper byte must be 0 */
83 if ((psm & 0x0101) != 0x0001) {
84 err = -EINVAL;
85 goto done;
86 }
87
88 /* Restrict usage of well-known PSMs */
89 if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
90 err = -EACCES;
91 goto done;
92 }
93 }
94
Ville Tervob62f3282011-02-10 22:38:50 -030095 if (la.l2_cid)
Santosh Nayak6e4aff12012-03-01 22:46:36 +053096 err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid));
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -030097 else
98 err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
Ville Tervob62f3282011-02-10 22:38:50 -030099
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300100 if (err < 0)
101 goto done;
102
Marcel Holtmann6a974b52013-10-12 07:19:31 -0700103 switch (chan->chan_type) {
Marcel Holtmann3124b842013-10-12 07:19:32 -0700104 case L2CAP_CHAN_CONN_LESS:
105 if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_3DSP)
106 chan->sec_level = BT_SECURITY_SDP;
107 break;
Marcel Holtmann6a974b52013-10-12 07:19:31 -0700108 case L2CAP_CHAN_CONN_ORIENTED:
109 if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP ||
110 __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
111 chan->sec_level = BT_SECURITY_SDP;
112 break;
113 }
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300114
Marcel Holtmann7eafc592013-10-13 08:12:47 -0700115 bacpy(&chan->src, &la.l2_bdaddr);
Marcel Holtmann4f1654e2013-10-13 08:50:41 -0700116 chan->src_type = la.l2_bdaddr_type;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300117
118 chan->state = BT_BOUND;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300119 sk->sk_state = BT_BOUND;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200120
121done:
122 release_sock(sk);
123 return err;
124}
125
Gustavo Padovan2d792812012-10-06 10:07:01 +0100126static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
127 int alen, int flags)
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200128{
129 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300130 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200131 struct sockaddr_l2 la;
132 int len, err = 0;
133
134 BT_DBG("sk %p", sk);
135
136 if (!addr || alen < sizeof(addr->sa_family) ||
137 addr->sa_family != AF_BLUETOOTH)
138 return -EINVAL;
139
140 memset(&la, 0, sizeof(la));
141 len = min_t(unsigned int, sizeof(la), alen);
142 memcpy(&la, addr, len);
143
Ville Tervoacd7d372011-02-10 22:38:49 -0300144 if (la.l2_cid && la.l2_psm)
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200145 return -EINVAL;
146
Santosh Nayak6e4aff12012-03-01 22:46:36 +0530147 err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
Andre Guedes8e9f9892012-04-24 21:02:55 -0300148 &la.l2_bdaddr, la.l2_bdaddr_type);
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200149 if (err)
Andrei Emeltchenkob3fb6112012-02-22 17:11:57 +0200150 return err;
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200151
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200152 lock_sock(sk);
153
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200154 err = bt_sock_wait_state(sk, BT_CONNECTED,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100155 sock_sndtimeo(sk, flags & O_NONBLOCK));
Andrei Emeltchenkob3fb6112012-02-22 17:11:57 +0200156
157 release_sock(sk);
158
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200159 return err;
160}
161
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200162static int l2cap_sock_listen(struct socket *sock, int backlog)
163{
164 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300165 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200166 int err = 0;
167
168 BT_DBG("sk %p backlog %d", sk, backlog);
169
170 lock_sock(sk);
171
Marcel Holtmann6b3af732012-04-19 13:43:51 +0200172 if (sk->sk_state != BT_BOUND) {
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200173 err = -EBADFD;
174 goto done;
175 }
176
Marcel Holtmann6b3af732012-04-19 13:43:51 +0200177 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) {
178 err = -EINVAL;
179 goto done;
180 }
181
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300182 switch (chan->mode) {
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200183 case L2CAP_MODE_BASIC:
184 break;
185 case L2CAP_MODE_ERTM:
186 case L2CAP_MODE_STREAMING:
187 if (!disable_ertm)
188 break;
189 /* fall through */
190 default:
191 err = -ENOTSUPP;
192 goto done;
193 }
194
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200195 sk->sk_max_ack_backlog = backlog;
196 sk->sk_ack_backlog = 0;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300197
198 chan->state = BT_LISTEN;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200199 sk->sk_state = BT_LISTEN;
200
201done:
202 release_sock(sk);
203 return err;
204}
205
Gustavo Padovan2d792812012-10-06 10:07:01 +0100206static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
207 int flags)
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200208{
209 DECLARE_WAITQUEUE(wait, current);
210 struct sock *sk = sock->sk, *nsk;
211 long timeo;
212 int err = 0;
213
214 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
215
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200216 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
217
218 BT_DBG("sk %p timeo %ld", sk, timeo);
219
220 /* Wait for an incoming connection. (wake-one). */
221 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400222 while (1) {
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200223 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200224
225 if (sk->sk_state != BT_LISTEN) {
226 err = -EBADFD;
227 break;
228 }
229
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400230 nsk = bt_accept_dequeue(sk, newsock);
231 if (nsk)
232 break;
233
234 if (!timeo) {
235 err = -EAGAIN;
236 break;
237 }
238
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200239 if (signal_pending(current)) {
240 err = sock_intr_errno(timeo);
241 break;
242 }
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400243
244 release_sock(sk);
245 timeo = schedule_timeout(timeo);
246 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200247 }
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400248 __set_current_state(TASK_RUNNING);
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200249 remove_wait_queue(sk_sleep(sk), &wait);
250
251 if (err)
252 goto done;
253
254 newsock->state = SS_CONNECTED;
255
256 BT_DBG("new socket %p", nsk);
257
258done:
259 release_sock(sk);
260 return err;
261}
262
Gustavo Padovan2d792812012-10-06 10:07:01 +0100263static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
264 int *len, int peer)
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200265{
266 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
267 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300268 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200269
270 BT_DBG("sock %p, sk %p", sock, sk);
271
Mathias Krause792039c2012-08-15 11:31:51 +0000272 memset(la, 0, sizeof(struct sockaddr_l2));
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200273 addr->sa_family = AF_BLUETOOTH;
274 *len = sizeof(struct sockaddr_l2);
275
276 if (peer) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300277 la->l2_psm = chan->psm;
Marcel Holtmann7eafc592013-10-13 08:12:47 -0700278 bacpy(&la->l2_bdaddr, &chan->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300279 la->l2_cid = cpu_to_le16(chan->dcid);
Marcel Holtmann4f1654e2013-10-13 08:50:41 -0700280 la->l2_bdaddr_type = chan->dst_type;
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200281 } else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300282 la->l2_psm = chan->sport;
Marcel Holtmann7eafc592013-10-13 08:12:47 -0700283 bacpy(&la->l2_bdaddr, &chan->src);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300284 la->l2_cid = cpu_to_le16(chan->scid);
Marcel Holtmann4f1654e2013-10-13 08:50:41 -0700285 la->l2_bdaddr_type = chan->src_type;
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200286 }
287
288 return 0;
289}
290
Gustavo Padovan2d792812012-10-06 10:07:01 +0100291static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
292 char __user *optval, int __user *optlen)
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200293{
294 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300295 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200296 struct l2cap_options opts;
297 struct l2cap_conninfo cinfo;
298 int len, err = 0;
299 u32 opt;
300
301 BT_DBG("sk %p", sk);
302
303 if (get_user(len, optlen))
304 return -EFAULT;
305
306 lock_sock(sk);
307
308 switch (optname) {
309 case L2CAP_OPTIONS:
Vasiliy Kulikove3fb5922011-02-10 20:59:42 +0300310 memset(&opts, 0, sizeof(opts));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300311 opts.imtu = chan->imtu;
312 opts.omtu = chan->omtu;
313 opts.flush_to = chan->flush_to;
314 opts.mode = chan->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300315 opts.fcs = chan->fcs;
316 opts.max_tx = chan->max_tx;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300317 opts.txwin_size = chan->tx_win;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200318
319 len = min_t(unsigned int, len, sizeof(opts));
320 if (copy_to_user(optval, (char *) &opts, len))
321 err = -EFAULT;
322
323 break;
324
325 case L2CAP_LM:
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300326 switch (chan->sec_level) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200327 case BT_SECURITY_LOW:
328 opt = L2CAP_LM_AUTH;
329 break;
330 case BT_SECURITY_MEDIUM:
331 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
332 break;
333 case BT_SECURITY_HIGH:
334 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
Gustavo Padovan2d792812012-10-06 10:07:01 +0100335 L2CAP_LM_SECURE;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200336 break;
337 default:
338 opt = 0;
339 break;
340 }
341
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +0300342 if (test_bit(FLAG_ROLE_SWITCH, &chan->flags))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200343 opt |= L2CAP_LM_MASTER;
344
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300345 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200346 opt |= L2CAP_LM_RELIABLE;
347
348 if (put_user(opt, (u32 __user *) optval))
349 err = -EFAULT;
350 break;
351
352 case L2CAP_CONNINFO:
353 if (sk->sk_state != BT_CONNECTED &&
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300354 !(sk->sk_state == BT_CONNECT2 &&
355 test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200356 err = -ENOTCONN;
357 break;
358 }
359
Filip Palian8d03e972011-05-12 19:32:46 +0200360 memset(&cinfo, 0, sizeof(cinfo));
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300361 cinfo.hci_handle = chan->conn->hcon->handle;
362 memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200363
364 len = min_t(unsigned int, len, sizeof(cinfo));
365 if (copy_to_user(optval, (char *) &cinfo, len))
366 err = -EFAULT;
367
368 break;
369
370 default:
371 err = -ENOPROTOOPT;
372 break;
373 }
374
375 release_sock(sk);
376 return err;
377}
378
Gustavo Padovan2d792812012-10-06 10:07:01 +0100379static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
380 char __user *optval, int __user *optlen)
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200381{
382 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300383 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200384 struct bt_security sec;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700385 struct bt_power pwr;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200386 int len, err = 0;
387
388 BT_DBG("sk %p", sk);
389
390 if (level == SOL_L2CAP)
391 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
392
393 if (level != SOL_BLUETOOTH)
394 return -ENOPROTOOPT;
395
396 if (get_user(len, optlen))
397 return -EFAULT;
398
399 lock_sock(sk);
400
401 switch (optname) {
402 case BT_SECURITY:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300403 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100404 chan->chan_type != L2CAP_CHAN_RAW) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200405 err = -EINVAL;
406 break;
407 }
408
Vinicius Costa Gomes8f360112011-07-08 18:31:46 -0300409 memset(&sec, 0, sizeof(sec));
Andrei Emeltchenko85e34362012-10-05 16:56:54 +0300410 if (chan->conn) {
Gustavo Padovanc6585a42012-05-07 03:07:26 -0300411 sec.level = chan->conn->hcon->sec_level;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200412
Andrei Emeltchenko85e34362012-10-05 16:56:54 +0300413 if (sk->sk_state == BT_CONNECTED)
414 sec.key_size = chan->conn->hcon->enc_key_size;
415 } else {
416 sec.level = chan->sec_level;
417 }
Vinicius Costa Gomes8f360112011-07-08 18:31:46 -0300418
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200419 len = min_t(unsigned int, len, sizeof(sec));
420 if (copy_to_user(optval, (char *) &sec, len))
421 err = -EFAULT;
422
423 break;
424
425 case BT_DEFER_SETUP:
426 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
427 err = -EINVAL;
428 break;
429 }
430
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300431 if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
432 (u32 __user *) optval))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200433 err = -EFAULT;
434
435 break;
436
437 case BT_FLUSHABLE:
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +0300438 if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
Gustavo Padovan2d792812012-10-06 10:07:01 +0100439 (u32 __user *) optval))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200440 err = -EFAULT;
441
442 break;
443
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700444 case BT_POWER:
445 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
Gustavo Padovan2d792812012-10-06 10:07:01 +0100446 && sk->sk_type != SOCK_RAW) {
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700447 err = -EINVAL;
448 break;
449 }
450
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300451 pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700452
453 len = min_t(unsigned int, len, sizeof(pwr));
454 if (copy_to_user(optval, (char *) &pwr, len))
455 err = -EFAULT;
456
457 break;
458
Mat Martineau2ea66482011-11-02 16:18:30 -0700459 case BT_CHANNEL_POLICY:
Mat Martineau2ea66482011-11-02 16:18:30 -0700460 if (put_user(chan->chan_policy, (u32 __user *) optval))
461 err = -EFAULT;
462 break;
463
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200464 default:
465 err = -ENOPROTOOPT;
466 break;
467 }
468
469 release_sock(sk);
470 return err;
471}
472
Andre Guedes682877c2012-05-31 17:01:34 -0300473static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)
474{
475 switch (chan->scid) {
Johan Hedberg073d1cf2013-04-29 19:35:35 +0300476 case L2CAP_CID_ATT:
Andre Guedes8c3a4f02012-05-31 17:01:35 -0300477 if (mtu < L2CAP_LE_MIN_MTU)
Andre Guedes682877c2012-05-31 17:01:34 -0300478 return false;
479 break;
480
481 default:
482 if (mtu < L2CAP_DEFAULT_MIN_MTU)
483 return false;
484 }
485
486 return true;
487}
488
Gustavo Padovan2d792812012-10-06 10:07:01 +0100489static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
490 char __user *optval, unsigned int optlen)
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200491{
492 struct sock *sk = sock->sk;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300493 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200494 struct l2cap_options opts;
495 int len, err = 0;
496 u32 opt;
497
498 BT_DBG("sk %p", sk);
499
500 lock_sock(sk);
501
502 switch (optname) {
503 case L2CAP_OPTIONS:
504 if (sk->sk_state == BT_CONNECTED) {
505 err = -EINVAL;
506 break;
507 }
508
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300509 opts.imtu = chan->imtu;
510 opts.omtu = chan->omtu;
511 opts.flush_to = chan->flush_to;
512 opts.mode = chan->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300513 opts.fcs = chan->fcs;
514 opts.max_tx = chan->max_tx;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300515 opts.txwin_size = chan->tx_win;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200516
517 len = min_t(unsigned int, sizeof(opts), optlen);
518 if (copy_from_user((char *) &opts, optval, len)) {
519 err = -EFAULT;
520 break;
521 }
522
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300523 if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200524 err = -EINVAL;
525 break;
526 }
527
Andre Guedes682877c2012-05-31 17:01:34 -0300528 if (!l2cap_valid_mtu(chan, opts.imtu)) {
529 err = -EINVAL;
530 break;
531 }
532
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300533 chan->mode = opts.mode;
534 switch (chan->mode) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200535 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300536 clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200537 break;
538 case L2CAP_MODE_ERTM:
539 case L2CAP_MODE_STREAMING:
540 if (!disable_ertm)
541 break;
542 /* fall through */
543 default:
544 err = -EINVAL;
545 break;
546 }
547
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300548 chan->imtu = opts.imtu;
549 chan->omtu = opts.omtu;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300550 chan->fcs = opts.fcs;
551 chan->max_tx = opts.max_tx;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300552 chan->tx_win = opts.txwin_size;
Andrei Emeltchenko12d59782012-10-10 17:38:26 +0300553 chan->flush_to = opts.flush_to;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200554 break;
555
556 case L2CAP_LM:
557 if (get_user(opt, (u32 __user *) optval)) {
558 err = -EFAULT;
559 break;
560 }
561
562 if (opt & L2CAP_LM_AUTH)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300563 chan->sec_level = BT_SECURITY_LOW;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200564 if (opt & L2CAP_LM_ENCRYPT)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300565 chan->sec_level = BT_SECURITY_MEDIUM;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200566 if (opt & L2CAP_LM_SECURE)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300567 chan->sec_level = BT_SECURITY_HIGH;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200568
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +0300569 if (opt & L2CAP_LM_MASTER)
570 set_bit(FLAG_ROLE_SWITCH, &chan->flags);
571 else
572 clear_bit(FLAG_ROLE_SWITCH, &chan->flags);
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300573
574 if (opt & L2CAP_LM_RELIABLE)
575 set_bit(FLAG_FORCE_RELIABLE, &chan->flags);
576 else
577 clear_bit(FLAG_FORCE_RELIABLE, &chan->flags);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200578 break;
579
580 default:
581 err = -ENOPROTOOPT;
582 break;
583 }
584
585 release_sock(sk);
586 return err;
587}
588
Gustavo Padovan2d792812012-10-06 10:07:01 +0100589static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
590 char __user *optval, unsigned int optlen)
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200591{
592 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300593 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200594 struct bt_security sec;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700595 struct bt_power pwr;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300596 struct l2cap_conn *conn;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200597 int len, err = 0;
598 u32 opt;
599
600 BT_DBG("sk %p", sk);
601
602 if (level == SOL_L2CAP)
603 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
604
605 if (level != SOL_BLUETOOTH)
606 return -ENOPROTOOPT;
607
608 lock_sock(sk);
609
610 switch (optname) {
611 case BT_SECURITY:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300612 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100613 chan->chan_type != L2CAP_CHAN_RAW) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200614 err = -EINVAL;
615 break;
616 }
617
618 sec.level = BT_SECURITY_LOW;
619
620 len = min_t(unsigned int, sizeof(sec), optlen);
621 if (copy_from_user((char *) &sec, optval, len)) {
622 err = -EFAULT;
623 break;
624 }
625
626 if (sec.level < BT_SECURITY_LOW ||
Gustavo Padovan2d792812012-10-06 10:07:01 +0100627 sec.level > BT_SECURITY_HIGH) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200628 err = -EINVAL;
629 break;
630 }
631
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300632 chan->sec_level = sec.level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300633
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200634 if (!chan->conn)
635 break;
636
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300637 conn = chan->conn;
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200638
639 /*change security for LE channels */
Johan Hedberg073d1cf2013-04-29 19:35:35 +0300640 if (chan->scid == L2CAP_CID_ATT) {
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300641 if (!conn->hcon->out) {
642 err = -EINVAL;
643 break;
644 }
645
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300646 if (smp_conn_security(conn->hcon, sec.level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300647 break;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300648 sk->sk_state = BT_CONFIG;
Gustavo F. Padovan3542b8542011-12-28 13:54:17 -0200649 chan->state = BT_CONFIG;
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200650
Gustavo Padovana7d77232012-05-13 03:20:07 -0300651 /* or for ACL link */
652 } else if ((sk->sk_state == BT_CONNECT2 &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100653 test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
Gustavo Padovana7d77232012-05-13 03:20:07 -0300654 sk->sk_state == BT_CONNECTED) {
655 if (!l2cap_chan_check_security(chan))
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300656 set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
Gustavo Padovana7d77232012-05-13 03:20:07 -0300657 else
658 sk->sk_state_change(sk);
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200659 } else {
660 err = -EINVAL;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300661 }
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200662 break;
663
664 case BT_DEFER_SETUP:
665 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
666 err = -EINVAL;
667 break;
668 }
669
670 if (get_user(opt, (u32 __user *) optval)) {
671 err = -EFAULT;
672 break;
673 }
674
Marcel Holtmannbdc25782013-10-14 02:45:34 -0700675 if (opt) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300676 set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
Marcel Holtmannbdc25782013-10-14 02:45:34 -0700677 set_bit(FLAG_DEFER_SETUP, &chan->flags);
678 } else {
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300679 clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
Marcel Holtmannbdc25782013-10-14 02:45:34 -0700680 clear_bit(FLAG_DEFER_SETUP, &chan->flags);
681 }
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200682 break;
683
684 case BT_FLUSHABLE:
685 if (get_user(opt, (u32 __user *) optval)) {
686 err = -EFAULT;
687 break;
688 }
689
690 if (opt > BT_FLUSHABLE_ON) {
691 err = -EINVAL;
692 break;
693 }
694
695 if (opt == BT_FLUSHABLE_OFF) {
Johannes Bergc1f23a22013-10-07 18:19:16 +0200696 conn = chan->conn;
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300697 /* proceed further only when we have l2cap_conn and
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200698 No Flush support in the LM */
699 if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
700 err = -EINVAL;
701 break;
702 }
703 }
704
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +0300705 if (opt)
706 set_bit(FLAG_FLUSHABLE, &chan->flags);
707 else
708 clear_bit(FLAG_FLUSHABLE, &chan->flags);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200709 break;
710
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700711 case BT_POWER:
712 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100713 chan->chan_type != L2CAP_CHAN_RAW) {
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700714 err = -EINVAL;
715 break;
716 }
717
718 pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
719
720 len = min_t(unsigned int, sizeof(pwr), optlen);
721 if (copy_from_user((char *) &pwr, optval, len)) {
722 err = -EFAULT;
723 break;
724 }
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300725
726 if (pwr.force_active)
727 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
728 else
729 clear_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700730 break;
731
Mat Martineau2ea66482011-11-02 16:18:30 -0700732 case BT_CHANNEL_POLICY:
Mat Martineau2ea66482011-11-02 16:18:30 -0700733 if (get_user(opt, (u32 __user *) optval)) {
734 err = -EFAULT;
735 break;
736 }
737
738 if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
739 err = -EINVAL;
740 break;
741 }
742
743 if (chan->mode != L2CAP_MODE_ERTM &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100744 chan->mode != L2CAP_MODE_STREAMING) {
Mat Martineau2ea66482011-11-02 16:18:30 -0700745 err = -EOPNOTSUPP;
746 break;
747 }
748
749 chan->chan_policy = (u8) opt;
Mat Martineau3f7a56c2012-10-23 15:24:23 -0700750
751 if (sk->sk_state == BT_CONNECTED &&
752 chan->move_role == L2CAP_MOVE_ROLE_NONE)
753 l2cap_move_start(chan);
754
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200755 break;
756
757 default:
758 err = -ENOPROTOOPT;
759 break;
760 }
761
762 release_sock(sk);
763 return err;
764}
765
Gustavo Padovan2d792812012-10-06 10:07:01 +0100766static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
767 struct msghdr *msg, size_t len)
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200768{
769 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300770 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200771 int err;
772
773 BT_DBG("sock %p, sk %p", sock, sk);
774
775 err = sock_error(sk);
776 if (err)
777 return err;
778
779 if (msg->msg_flags & MSG_OOB)
780 return -EOPNOTSUPP;
781
Mat Martineaua6a55682012-05-04 14:20:31 -0700782 if (sk->sk_state != BT_CONNECTED)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -0300783 return -ENOTCONN;
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200784
Johan Hedberge793dcf2013-09-16 13:05:19 +0300785 lock_sock(sk);
786 err = bt_sock_wait_ready(sk, msg->msg_flags);
787 release_sock(sk);
788 if (err)
789 return err;
790
Mat Martineaua6a55682012-05-04 14:20:31 -0700791 l2cap_chan_lock(chan);
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200792 err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
Mat Martineaua6a55682012-05-04 14:20:31 -0700793 l2cap_chan_unlock(chan);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200794
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200795 return err;
796}
797
Gustavo Padovan2d792812012-10-06 10:07:01 +0100798static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
799 struct msghdr *msg, size_t len, int flags)
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200800{
801 struct sock *sk = sock->sk;
Mat Martineaue3281402011-07-07 09:39:02 -0700802 struct l2cap_pinfo *pi = l2cap_pi(sk);
803 int err;
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200804
805 lock_sock(sk);
806
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300807 if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,
808 &bt_sk(sk)->flags)) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300809 sk->sk_state = BT_CONFIG;
Gustavo F. Padovan3542b8542011-12-28 13:54:17 -0200810 pi->chan->state = BT_CONFIG;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300811
Mat Martineaue3281402011-07-07 09:39:02 -0700812 __l2cap_connect_rsp_defer(pi->chan);
Johan Hedberg970871b2013-09-25 13:26:05 +0300813 err = 0;
814 goto done;
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200815 }
816
817 release_sock(sk);
818
819 if (sock->type == SOCK_STREAM)
Mat Martineaue3281402011-07-07 09:39:02 -0700820 err = bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
821 else
822 err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200823
Mat Martineaue3281402011-07-07 09:39:02 -0700824 if (pi->chan->mode != L2CAP_MODE_ERTM)
825 return err;
826
827 /* Attempt to put pending rx data in the socket buffer */
828
829 lock_sock(sk);
830
831 if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
832 goto done;
833
834 if (pi->rx_busy_skb) {
835 if (!sock_queue_rcv_skb(sk, pi->rx_busy_skb))
836 pi->rx_busy_skb = NULL;
837 else
838 goto done;
839 }
840
841 /* Restore data flow when half of the receive buffer is
842 * available. This avoids resending large numbers of
843 * frames.
844 */
845 if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
846 l2cap_chan_busy(pi->chan, 0);
847
848done:
849 release_sock(sk);
850 return err;
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200851}
852
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200853/* Kill socket (only if zapped and orphan)
854 * Must be called on unlocked socket.
855 */
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300856static void l2cap_sock_kill(struct sock *sk)
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200857{
858 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
859 return;
860
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200861 BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state));
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200862
863 /* Kill poor orphan */
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300864
Jaganath Kanakkassery4af66c62012-07-13 18:17:55 +0530865 l2cap_chan_put(l2cap_pi(sk)->chan);
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200866 sock_set_flag(sk, SOCK_DEAD);
867 sock_put(sk);
868}
869
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200870static int l2cap_sock_shutdown(struct socket *sock, int how)
871{
872 struct sock *sk = sock->sk;
Andrei Emeltchenko7ddb6e02012-02-14 15:12:57 +0200873 struct l2cap_chan *chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200874 struct l2cap_conn *conn;
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200875 int err = 0;
876
877 BT_DBG("sock %p, sk %p", sock, sk);
878
879 if (!sk)
880 return 0;
881
Andrei Emeltchenko7ddb6e02012-02-14 15:12:57 +0200882 chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200883 conn = chan->conn;
884
885 if (conn)
886 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko7ddb6e02012-02-14 15:12:57 +0200887
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200888 l2cap_chan_lock(chan);
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200889 lock_sock(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200890
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200891 if (!sk->sk_shutdown) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300892 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200893 err = __l2cap_wait_ack(sk);
894
895 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200896
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200897 release_sock(sk);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300898 l2cap_chan_close(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200899 lock_sock(sk);
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200900
901 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
902 err = bt_sock_wait_state(sk, BT_CLOSED,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100903 sk->sk_lingertime);
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200904 }
905
906 if (!err && sk->sk_err)
907 err = -sk->sk_err;
908
909 release_sock(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200910 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200911
912 if (conn)
913 mutex_unlock(&conn->chan_lock);
914
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200915 return err;
916}
917
Gustavo F. Padovan554f05b2011-02-04 02:36:42 -0200918static int l2cap_sock_release(struct socket *sock)
919{
920 struct sock *sk = sock->sk;
921 int err;
922
923 BT_DBG("sock %p, sk %p", sock, sk);
924
925 if (!sk)
926 return 0;
927
Masatake YAMATO5b28d952012-07-26 01:29:25 +0900928 bt_sock_unlink(&l2cap_sk_list, sk);
929
Gustavo F. Padovan554f05b2011-02-04 02:36:42 -0200930 err = l2cap_sock_shutdown(sock, 2);
931
932 sock_orphan(sk);
933 l2cap_sock_kill(sk);
934 return err;
935}
936
Andrei Emeltchenkoc0df7f62012-05-27 22:27:52 -0300937static void l2cap_sock_cleanup_listen(struct sock *parent)
938{
939 struct sock *sk;
940
941 BT_DBG("parent %p", parent);
942
943 /* Close not yet accepted channels */
944 while ((sk = bt_accept_dequeue(parent, NULL))) {
945 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
946
947 l2cap_chan_lock(chan);
948 __clear_chan_timer(chan);
949 l2cap_chan_close(chan, ECONNRESET);
950 l2cap_chan_unlock(chan);
951
952 l2cap_sock_kill(sk);
953 }
954}
955
Gustavo Padovan80b98022012-05-27 22:27:51 -0300956static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300957{
Gustavo Padovan80b98022012-05-27 22:27:51 -0300958 struct sock *sk, *parent = chan->data;
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300959
Gustavo Padovan53826692012-05-27 22:27:55 -0300960 /* Check for backlog size */
961 if (sk_acceptq_is_full(parent)) {
962 BT_DBG("backlog full %d", parent->sk_ack_backlog);
963 return NULL;
964 }
965
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300966 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100967 GFP_ATOMIC);
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300968 if (!sk)
969 return NULL;
970
Octavian Purdilad22015a2012-01-22 00:28:34 +0200971 bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
972
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300973 l2cap_sock_init(sk, parent);
974
Gustavo Padovan644912e2012-10-12 19:35:23 +0800975 bt_accept_enqueue(parent, sk);
976
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300977 return l2cap_pi(sk)->chan;
978}
979
Gustavo Padovan80b98022012-05-27 22:27:51 -0300980static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan23070492011-05-16 17:57:22 -0300981{
Gustavo Padovan80b98022012-05-27 22:27:51 -0300982 struct sock *sk = chan->data;
Marcel Holtmann84b34d92013-10-13 11:36:07 -0700983 int err;
Gustavo F. Padovan23070492011-05-16 17:57:22 -0300984
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200985 lock_sock(sk);
986
Marcel Holtmann84b34d92013-10-13 11:36:07 -0700987 if (l2cap_pi(sk)->rx_busy_skb) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200988 err = -ENOMEM;
989 goto done;
990 }
Mat Martineaue3281402011-07-07 09:39:02 -0700991
992 err = sock_queue_rcv_skb(sk, skb);
993
994 /* For ERTM, handle one skb that doesn't fit into the recv
995 * buffer. This is important to do because the data frames
996 * have already been acked, so the skb cannot be discarded.
997 *
998 * Notify the l2cap core that the buffer is full, so the
999 * LOCAL_BUSY state is entered and no more frames are
1000 * acked and reassembled until there is buffer space
1001 * available.
1002 */
Marcel Holtmann84b34d92013-10-13 11:36:07 -07001003 if (err < 0 && chan->mode == L2CAP_MODE_ERTM) {
1004 l2cap_pi(sk)->rx_busy_skb = skb;
1005 l2cap_chan_busy(chan, 1);
Mat Martineaue3281402011-07-07 09:39:02 -07001006 err = 0;
1007 }
1008
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001009done:
1010 release_sock(sk);
1011
Mat Martineaue3281402011-07-07 09:39:02 -07001012 return err;
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001013}
1014
Gustavo Padovan80b98022012-05-27 22:27:51 -03001015static void l2cap_sock_close_cb(struct l2cap_chan *chan)
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03001016{
Gustavo Padovan80b98022012-05-27 22:27:51 -03001017 struct sock *sk = chan->data;
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03001018
1019 l2cap_sock_kill(sk);
1020}
1021
Andrei Emeltchenkoc0df7f62012-05-27 22:27:52 -03001022static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err)
1023{
1024 struct sock *sk = chan->data;
1025 struct sock *parent;
1026
1027 lock_sock(sk);
1028
1029 parent = bt_sk(sk)->parent;
1030
1031 sock_set_flag(sk, SOCK_ZAPPED);
1032
1033 switch (chan->state) {
1034 case BT_OPEN:
1035 case BT_BOUND:
1036 case BT_CLOSED:
1037 break;
1038 case BT_LISTEN:
1039 l2cap_sock_cleanup_listen(sk);
1040 sk->sk_state = BT_CLOSED;
1041 chan->state = BT_CLOSED;
1042
1043 break;
1044 default:
1045 sk->sk_state = BT_CLOSED;
1046 chan->state = BT_CLOSED;
1047
1048 sk->sk_err = err;
1049
1050 if (parent) {
1051 bt_accept_unlink(sk);
1052 parent->sk_data_ready(parent, 0);
1053 } else {
1054 sk->sk_state_change(sk);
1055 }
1056
1057 break;
1058 }
1059
1060 release_sock(sk);
1061}
1062
Gustavo Padovan80b98022012-05-27 22:27:51 -03001063static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001064{
Gustavo Padovan80b98022012-05-27 22:27:51 -03001065 struct sock *sk = chan->data;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001066
1067 sk->sk_state = state;
1068}
1069
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001070static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
Gustavo Padovan90338942012-04-06 20:15:47 -03001071 unsigned long len, int nb)
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001072{
Gustavo Padovan90338942012-04-06 20:15:47 -03001073 struct sk_buff *skb;
1074 int err;
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001075
Mat Martineaua6a55682012-05-04 14:20:31 -07001076 l2cap_chan_unlock(chan);
Gustavo Padovan90338942012-04-06 20:15:47 -03001077 skb = bt_skb_send_alloc(chan->sk, len, nb, &err);
Mat Martineaua6a55682012-05-04 14:20:31 -07001078 l2cap_chan_lock(chan);
1079
Gustavo Padovan90338942012-04-06 20:15:47 -03001080 if (!skb)
1081 return ERR_PTR(err);
1082
1083 return skb;
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001084}
1085
Andrei Emeltchenko54a59aa2012-05-27 22:27:53 -03001086static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
1087{
1088 struct sock *sk = chan->data;
1089 struct sock *parent;
1090
1091 lock_sock(sk);
1092
1093 parent = bt_sk(sk)->parent;
1094
1095 BT_DBG("sk %p, parent %p", sk, parent);
1096
1097 sk->sk_state = BT_CONNECTED;
1098 sk->sk_state_change(sk);
1099
1100 if (parent)
1101 parent->sk_data_ready(parent, 0);
1102
1103 release_sock(sk);
1104}
1105
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08001106static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
1107{
1108 struct sock *sk = chan->data;
1109 struct sock *parent = bt_sk(sk)->parent;
1110
1111 if (parent)
1112 parent->sk_data_ready(parent, 0);
1113}
1114
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001115static struct l2cap_ops l2cap_chan_ops = {
1116 .name = "L2CAP Socket Interface",
1117 .new_connection = l2cap_sock_new_connection_cb,
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001118 .recv = l2cap_sock_recv_cb,
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03001119 .close = l2cap_sock_close_cb,
Andrei Emeltchenkoc0df7f62012-05-27 22:27:52 -03001120 .teardown = l2cap_sock_teardown_cb,
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001121 .state_change = l2cap_sock_state_change_cb,
Andrei Emeltchenko54a59aa2012-05-27 22:27:53 -03001122 .ready = l2cap_sock_ready_cb,
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08001123 .defer = l2cap_sock_defer_cb,
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001124 .alloc_skb = l2cap_sock_alloc_skb_cb,
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001125};
1126
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001127static void l2cap_sock_destruct(struct sock *sk)
1128{
1129 BT_DBG("sk %p", sk);
1130
Sasha Levin23d3a862012-10-08 16:48:32 -04001131 if (l2cap_pi(sk)->chan)
1132 l2cap_chan_put(l2cap_pi(sk)->chan);
Marcel Holtmann84b34d92013-10-13 11:36:07 -07001133
Mat Martineaue3281402011-07-07 09:39:02 -07001134 if (l2cap_pi(sk)->rx_busy_skb) {
1135 kfree_skb(l2cap_pi(sk)->rx_busy_skb);
1136 l2cap_pi(sk)->rx_busy_skb = NULL;
1137 }
1138
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001139 skb_queue_purge(&sk->sk_receive_queue);
1140 skb_queue_purge(&sk->sk_write_queue);
1141}
1142
Marcel Holtmann2edf8702013-10-13 12:55:29 -07001143static void l2cap_skb_msg_name(struct sk_buff *skb, void *msg_name,
1144 int *msg_namelen)
1145{
1146 struct sockaddr_l2 *la = (struct sockaddr_l2 *) msg_name;
1147
1148 memset(la, 0, sizeof(struct sockaddr_l2));
1149 la->l2_family = AF_BLUETOOTH;
1150 la->l2_psm = bt_cb(skb)->psm;
1151 bacpy(&la->l2_bdaddr, &bt_cb(skb)->bdaddr);
1152
1153 *msg_namelen = sizeof(struct sockaddr_l2);
1154}
1155
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001156static void l2cap_sock_init(struct sock *sk, struct sock *parent)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001157{
Marcel Holtmann84b34d92013-10-13 11:36:07 -07001158 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001159
1160 BT_DBG("sk %p", sk);
1161
1162 if (parent) {
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001163 struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
1164
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001165 sk->sk_type = parent->sk_type;
Gustavo Padovanc5daa682012-05-16 12:17:10 -03001166 bt_sk(sk)->flags = bt_sk(parent)->flags;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001167
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001168 chan->chan_type = pchan->chan_type;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001169 chan->imtu = pchan->imtu;
1170 chan->omtu = pchan->omtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001171 chan->conf_state = pchan->conf_state;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001172 chan->mode = pchan->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001173 chan->fcs = pchan->fcs;
1174 chan->max_tx = pchan->max_tx;
1175 chan->tx_win = pchan->tx_win;
Andrei Emeltchenko6b3c7102011-11-02 09:57:10 +02001176 chan->tx_win_max = pchan->tx_win_max;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001177 chan->sec_level = pchan->sec_level;
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001178 chan->flags = pchan->flags;
Paul Moore6230c9b2011-10-07 09:40:59 +00001179
1180 security_sk_clone(parent, sk);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001181 } else {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001182 switch (sk->sk_type) {
1183 case SOCK_RAW:
1184 chan->chan_type = L2CAP_CHAN_RAW;
1185 break;
1186 case SOCK_DGRAM:
1187 chan->chan_type = L2CAP_CHAN_CONN_LESS;
Marcel Holtmann2edf8702013-10-13 12:55:29 -07001188 bt_sk(sk)->skb_msg_name = l2cap_skb_msg_name;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001189 break;
1190 case SOCK_SEQPACKET:
1191 case SOCK_STREAM:
1192 chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
1193 break;
1194 }
1195
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001196 chan->imtu = L2CAP_DEFAULT_MTU;
1197 chan->omtu = 0;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001198 if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001199 chan->mode = L2CAP_MODE_ERTM;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001200 set_bit(CONF_STATE2_DEVICE, &chan->conf_state);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001201 } else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001202 chan->mode = L2CAP_MODE_BASIC;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001203 }
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +03001204
1205 l2cap_chan_set_defaults(chan);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001206 }
1207
1208 /* Default config options */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001209 chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001210
1211 chan->data = sk;
1212 chan->ops = &l2cap_chan_ops;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001213}
1214
1215static struct proto l2cap_proto = {
1216 .name = "L2CAP",
1217 .owner = THIS_MODULE,
1218 .obj_size = sizeof(struct l2cap_pinfo)
1219};
1220
Gustavo Padovan2d792812012-10-06 10:07:01 +01001221static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
1222 int proto, gfp_t prio)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001223{
1224 struct sock *sk;
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001225 struct l2cap_chan *chan;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001226
1227 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
1228 if (!sk)
1229 return NULL;
1230
1231 sock_init_data(sock, sk);
1232 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
1233
1234 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08001235 sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001236
1237 sock_reset_flag(sk, SOCK_ZAPPED);
1238
1239 sk->sk_protocol = proto;
1240 sk->sk_state = BT_OPEN;
1241
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -03001242 chan = l2cap_chan_create();
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001243 if (!chan) {
Jaganath Kanakkassery49dfbb92012-07-19 12:54:04 +05301244 sk_free(sk);
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001245 return NULL;
1246 }
1247
Mat Martineau61d6ef32012-04-27 16:50:50 -07001248 l2cap_chan_hold(chan);
1249
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -03001250 chan->sk = sk;
1251
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001252 l2cap_pi(sk)->chan = chan;
1253
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001254 return sk;
1255}
1256
1257static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
1258 int kern)
1259{
1260 struct sock *sk;
1261
1262 BT_DBG("sock %p", sock);
1263
1264 sock->state = SS_UNCONNECTED;
1265
1266 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01001267 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001268 return -ESOCKTNOSUPPORT;
1269
1270 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
1271 return -EPERM;
1272
1273 sock->ops = &l2cap_sock_ops;
1274
1275 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
1276 if (!sk)
1277 return -ENOMEM;
1278
1279 l2cap_sock_init(sk, NULL);
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001280 bt_sock_link(&l2cap_sk_list, sk);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001281 return 0;
1282}
1283
Gustavo F. Padovancf2f90f2011-04-27 18:40:39 -03001284static const struct proto_ops l2cap_sock_ops = {
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001285 .family = PF_BLUETOOTH,
1286 .owner = THIS_MODULE,
1287 .release = l2cap_sock_release,
1288 .bind = l2cap_sock_bind,
1289 .connect = l2cap_sock_connect,
1290 .listen = l2cap_sock_listen,
1291 .accept = l2cap_sock_accept,
1292 .getname = l2cap_sock_getname,
1293 .sendmsg = l2cap_sock_sendmsg,
1294 .recvmsg = l2cap_sock_recvmsg,
1295 .poll = bt_sock_poll,
1296 .ioctl = bt_sock_ioctl,
1297 .mmap = sock_no_mmap,
1298 .socketpair = sock_no_socketpair,
1299 .shutdown = l2cap_sock_shutdown,
1300 .setsockopt = l2cap_sock_setsockopt,
1301 .getsockopt = l2cap_sock_getsockopt
1302};
1303
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001304static const struct net_proto_family l2cap_sock_family_ops = {
1305 .family = PF_BLUETOOTH,
1306 .owner = THIS_MODULE,
1307 .create = l2cap_sock_create,
1308};
1309
1310int __init l2cap_init_sockets(void)
1311{
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001312 int err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001313
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001314 err = proto_register(&l2cap_proto, 0);
1315 if (err < 0)
1316 return err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001317
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001318 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001319 if (err < 0) {
1320 BT_ERR("L2CAP socket registration failed");
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001321 goto error;
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001322 }
1323
Al Virob0316612013-04-04 19:14:33 -04001324 err = bt_procfs_init(&init_net, "l2cap", &l2cap_sk_list,
Gustavo Padovan2d792812012-10-06 10:07:01 +01001325 NULL);
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001326 if (err < 0) {
1327 BT_ERR("Failed to create L2CAP proc file");
1328 bt_sock_unregister(BTPROTO_L2CAP);
1329 goto error;
1330 }
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001331
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001332 BT_INFO("L2CAP socket layer initialized");
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001333
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001334 return 0;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001335
1336error:
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001337 proto_unregister(&l2cap_proto);
1338 return err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001339}
1340
1341void l2cap_cleanup_sockets(void)
1342{
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001343 bt_procfs_cleanup(&init_net, "l2cap");
David Herrmann5e9d7f82013-02-24 19:36:51 +01001344 bt_sock_unregister(BTPROTO_L2CAP);
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001345 proto_unregister(&l2cap_proto);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001346}