blob: 3f21207d59e509bdf473f6f5cbdd2cb5d0e560b5 [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
Johan Hedberg80c1a2e2013-10-14 21:17:52 +030072 if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
73 return -EINVAL;
74
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -020075 lock_sock(sk);
76
77 if (sk->sk_state != BT_OPEN) {
78 err = -EBADFD;
79 goto done;
80 }
81
82 if (la.l2_psm) {
83 __u16 psm = __le16_to_cpu(la.l2_psm);
84
85 /* PSM must be odd and lsb of upper byte must be 0 */
86 if ((psm & 0x0101) != 0x0001) {
87 err = -EINVAL;
88 goto done;
89 }
90
91 /* Restrict usage of well-known PSMs */
92 if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
93 err = -EACCES;
94 goto done;
95 }
96 }
97
Ville Tervob62f3282011-02-10 22:38:50 -030098 if (la.l2_cid)
Santosh Nayak6e4aff12012-03-01 22:46:36 +053099 err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid));
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300100 else
101 err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
Ville Tervob62f3282011-02-10 22:38:50 -0300102
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300103 if (err < 0)
104 goto done;
105
Marcel Holtmann6a974b52013-10-12 07:19:31 -0700106 switch (chan->chan_type) {
Marcel Holtmann3124b842013-10-12 07:19:32 -0700107 case L2CAP_CHAN_CONN_LESS:
108 if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_3DSP)
109 chan->sec_level = BT_SECURITY_SDP;
110 break;
Marcel Holtmann6a974b52013-10-12 07:19:31 -0700111 case L2CAP_CHAN_CONN_ORIENTED:
112 if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP ||
113 __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
114 chan->sec_level = BT_SECURITY_SDP;
115 break;
116 }
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300117
Marcel Holtmann7eafc592013-10-13 08:12:47 -0700118 bacpy(&chan->src, &la.l2_bdaddr);
Marcel Holtmann4f1654e2013-10-13 08:50:41 -0700119 chan->src_type = la.l2_bdaddr_type;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300120
121 chan->state = BT_BOUND;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300122 sk->sk_state = BT_BOUND;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200123
124done:
125 release_sock(sk);
126 return err;
127}
128
Gustavo Padovan2d792812012-10-06 10:07:01 +0100129static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
130 int alen, int flags)
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200131{
132 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300133 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200134 struct sockaddr_l2 la;
135 int len, err = 0;
136
137 BT_DBG("sk %p", sk);
138
139 if (!addr || alen < sizeof(addr->sa_family) ||
140 addr->sa_family != AF_BLUETOOTH)
141 return -EINVAL;
142
143 memset(&la, 0, sizeof(la));
144 len = min_t(unsigned int, sizeof(la), alen);
145 memcpy(&la, addr, len);
146
Ville Tervoacd7d372011-02-10 22:38:49 -0300147 if (la.l2_cid && la.l2_psm)
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200148 return -EINVAL;
149
Johan Hedberg80c1a2e2013-10-14 21:17:52 +0300150 if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
151 return -EINVAL;
152
Santosh Nayak6e4aff12012-03-01 22:46:36 +0530153 err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
Andre Guedes8e9f9892012-04-24 21:02:55 -0300154 &la.l2_bdaddr, la.l2_bdaddr_type);
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200155 if (err)
Andrei Emeltchenkob3fb6112012-02-22 17:11:57 +0200156 return err;
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200157
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200158 lock_sock(sk);
159
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200160 err = bt_sock_wait_state(sk, BT_CONNECTED,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100161 sock_sndtimeo(sk, flags & O_NONBLOCK));
Andrei Emeltchenkob3fb6112012-02-22 17:11:57 +0200162
163 release_sock(sk);
164
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200165 return err;
166}
167
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200168static int l2cap_sock_listen(struct socket *sock, int backlog)
169{
170 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300171 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200172 int err = 0;
173
174 BT_DBG("sk %p backlog %d", sk, backlog);
175
176 lock_sock(sk);
177
Marcel Holtmann6b3af732012-04-19 13:43:51 +0200178 if (sk->sk_state != BT_BOUND) {
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200179 err = -EBADFD;
180 goto done;
181 }
182
Marcel Holtmann6b3af732012-04-19 13:43:51 +0200183 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) {
184 err = -EINVAL;
185 goto done;
186 }
187
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300188 switch (chan->mode) {
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200189 case L2CAP_MODE_BASIC:
190 break;
191 case L2CAP_MODE_ERTM:
192 case L2CAP_MODE_STREAMING:
193 if (!disable_ertm)
194 break;
195 /* fall through */
196 default:
197 err = -ENOTSUPP;
198 goto done;
199 }
200
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200201 sk->sk_max_ack_backlog = backlog;
202 sk->sk_ack_backlog = 0;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300203
204 chan->state = BT_LISTEN;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200205 sk->sk_state = BT_LISTEN;
206
207done:
208 release_sock(sk);
209 return err;
210}
211
Gustavo Padovan2d792812012-10-06 10:07:01 +0100212static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
213 int flags)
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200214{
215 DECLARE_WAITQUEUE(wait, current);
216 struct sock *sk = sock->sk, *nsk;
217 long timeo;
218 int err = 0;
219
220 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
221
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200222 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
223
224 BT_DBG("sk %p timeo %ld", sk, timeo);
225
226 /* Wait for an incoming connection. (wake-one). */
227 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400228 while (1) {
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200229 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200230
231 if (sk->sk_state != BT_LISTEN) {
232 err = -EBADFD;
233 break;
234 }
235
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400236 nsk = bt_accept_dequeue(sk, newsock);
237 if (nsk)
238 break;
239
240 if (!timeo) {
241 err = -EAGAIN;
242 break;
243 }
244
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200245 if (signal_pending(current)) {
246 err = sock_intr_errno(timeo);
247 break;
248 }
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400249
250 release_sock(sk);
251 timeo = schedule_timeout(timeo);
252 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200253 }
Peter Hurleyf9a3c202011-07-24 00:10:52 -0400254 __set_current_state(TASK_RUNNING);
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200255 remove_wait_queue(sk_sleep(sk), &wait);
256
257 if (err)
258 goto done;
259
260 newsock->state = SS_CONNECTED;
261
262 BT_DBG("new socket %p", nsk);
263
264done:
265 release_sock(sk);
266 return err;
267}
268
Gustavo Padovan2d792812012-10-06 10:07:01 +0100269static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
270 int *len, int peer)
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200271{
272 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
273 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300274 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200275
276 BT_DBG("sock %p, sk %p", sock, sk);
277
Mathias Krause792039c2012-08-15 11:31:51 +0000278 memset(la, 0, sizeof(struct sockaddr_l2));
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200279 addr->sa_family = AF_BLUETOOTH;
280 *len = sizeof(struct sockaddr_l2);
281
282 if (peer) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300283 la->l2_psm = chan->psm;
Marcel Holtmann7eafc592013-10-13 08:12:47 -0700284 bacpy(&la->l2_bdaddr, &chan->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300285 la->l2_cid = cpu_to_le16(chan->dcid);
Marcel Holtmann4f1654e2013-10-13 08:50:41 -0700286 la->l2_bdaddr_type = chan->dst_type;
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200287 } else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300288 la->l2_psm = chan->sport;
Marcel Holtmann7eafc592013-10-13 08:12:47 -0700289 bacpy(&la->l2_bdaddr, &chan->src);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300290 la->l2_cid = cpu_to_le16(chan->scid);
Marcel Holtmann4f1654e2013-10-13 08:50:41 -0700291 la->l2_bdaddr_type = chan->src_type;
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200292 }
293
294 return 0;
295}
296
Gustavo Padovan2d792812012-10-06 10:07:01 +0100297static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
298 char __user *optval, int __user *optlen)
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200299{
300 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300301 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200302 struct l2cap_options opts;
303 struct l2cap_conninfo cinfo;
304 int len, err = 0;
305 u32 opt;
306
307 BT_DBG("sk %p", sk);
308
309 if (get_user(len, optlen))
310 return -EFAULT;
311
312 lock_sock(sk);
313
314 switch (optname) {
315 case L2CAP_OPTIONS:
Vasiliy Kulikove3fb5922011-02-10 20:59:42 +0300316 memset(&opts, 0, sizeof(opts));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300317 opts.imtu = chan->imtu;
318 opts.omtu = chan->omtu;
319 opts.flush_to = chan->flush_to;
320 opts.mode = chan->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300321 opts.fcs = chan->fcs;
322 opts.max_tx = chan->max_tx;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300323 opts.txwin_size = chan->tx_win;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200324
325 len = min_t(unsigned int, len, sizeof(opts));
326 if (copy_to_user(optval, (char *) &opts, len))
327 err = -EFAULT;
328
329 break;
330
331 case L2CAP_LM:
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300332 switch (chan->sec_level) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200333 case BT_SECURITY_LOW:
334 opt = L2CAP_LM_AUTH;
335 break;
336 case BT_SECURITY_MEDIUM:
337 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
338 break;
339 case BT_SECURITY_HIGH:
340 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
Gustavo Padovan2d792812012-10-06 10:07:01 +0100341 L2CAP_LM_SECURE;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200342 break;
343 default:
344 opt = 0;
345 break;
346 }
347
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +0300348 if (test_bit(FLAG_ROLE_SWITCH, &chan->flags))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200349 opt |= L2CAP_LM_MASTER;
350
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300351 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200352 opt |= L2CAP_LM_RELIABLE;
353
354 if (put_user(opt, (u32 __user *) optval))
355 err = -EFAULT;
356 break;
357
358 case L2CAP_CONNINFO:
359 if (sk->sk_state != BT_CONNECTED &&
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300360 !(sk->sk_state == BT_CONNECT2 &&
361 test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200362 err = -ENOTCONN;
363 break;
364 }
365
Filip Palian8d03e972011-05-12 19:32:46 +0200366 memset(&cinfo, 0, sizeof(cinfo));
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300367 cinfo.hci_handle = chan->conn->hcon->handle;
368 memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200369
370 len = min_t(unsigned int, len, sizeof(cinfo));
371 if (copy_to_user(optval, (char *) &cinfo, len))
372 err = -EFAULT;
373
374 break;
375
376 default:
377 err = -ENOPROTOOPT;
378 break;
379 }
380
381 release_sock(sk);
382 return err;
383}
384
Gustavo Padovan2d792812012-10-06 10:07:01 +0100385static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
386 char __user *optval, int __user *optlen)
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200387{
388 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300389 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200390 struct bt_security sec;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700391 struct bt_power pwr;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200392 int len, err = 0;
393
394 BT_DBG("sk %p", sk);
395
396 if (level == SOL_L2CAP)
397 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
398
399 if (level != SOL_BLUETOOTH)
400 return -ENOPROTOOPT;
401
402 if (get_user(len, optlen))
403 return -EFAULT;
404
405 lock_sock(sk);
406
407 switch (optname) {
408 case BT_SECURITY:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300409 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100410 chan->chan_type != L2CAP_CHAN_RAW) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200411 err = -EINVAL;
412 break;
413 }
414
Vinicius Costa Gomes8f360112011-07-08 18:31:46 -0300415 memset(&sec, 0, sizeof(sec));
Andrei Emeltchenko85e34362012-10-05 16:56:54 +0300416 if (chan->conn) {
Gustavo Padovanc6585a42012-05-07 03:07:26 -0300417 sec.level = chan->conn->hcon->sec_level;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200418
Andrei Emeltchenko85e34362012-10-05 16:56:54 +0300419 if (sk->sk_state == BT_CONNECTED)
420 sec.key_size = chan->conn->hcon->enc_key_size;
421 } else {
422 sec.level = chan->sec_level;
423 }
Vinicius Costa Gomes8f360112011-07-08 18:31:46 -0300424
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200425 len = min_t(unsigned int, len, sizeof(sec));
426 if (copy_to_user(optval, (char *) &sec, len))
427 err = -EFAULT;
428
429 break;
430
431 case BT_DEFER_SETUP:
432 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
433 err = -EINVAL;
434 break;
435 }
436
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300437 if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
438 (u32 __user *) optval))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200439 err = -EFAULT;
440
441 break;
442
443 case BT_FLUSHABLE:
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +0300444 if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
Gustavo Padovan2d792812012-10-06 10:07:01 +0100445 (u32 __user *) optval))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200446 err = -EFAULT;
447
448 break;
449
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700450 case BT_POWER:
451 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
Gustavo Padovan2d792812012-10-06 10:07:01 +0100452 && sk->sk_type != SOCK_RAW) {
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700453 err = -EINVAL;
454 break;
455 }
456
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300457 pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700458
459 len = min_t(unsigned int, len, sizeof(pwr));
460 if (copy_to_user(optval, (char *) &pwr, len))
461 err = -EFAULT;
462
463 break;
464
Mat Martineau2ea66482011-11-02 16:18:30 -0700465 case BT_CHANNEL_POLICY:
Mat Martineau2ea66482011-11-02 16:18:30 -0700466 if (put_user(chan->chan_policy, (u32 __user *) optval))
467 err = -EFAULT;
468 break;
469
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200470 default:
471 err = -ENOPROTOOPT;
472 break;
473 }
474
475 release_sock(sk);
476 return err;
477}
478
Andre Guedes682877c2012-05-31 17:01:34 -0300479static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)
480{
481 switch (chan->scid) {
Johan Hedberg073d1cf2013-04-29 19:35:35 +0300482 case L2CAP_CID_ATT:
Andre Guedes8c3a4f02012-05-31 17:01:35 -0300483 if (mtu < L2CAP_LE_MIN_MTU)
Andre Guedes682877c2012-05-31 17:01:34 -0300484 return false;
485 break;
486
487 default:
488 if (mtu < L2CAP_DEFAULT_MIN_MTU)
489 return false;
490 }
491
492 return true;
493}
494
Gustavo Padovan2d792812012-10-06 10:07:01 +0100495static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
496 char __user *optval, unsigned int optlen)
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200497{
498 struct sock *sk = sock->sk;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300499 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200500 struct l2cap_options opts;
501 int len, err = 0;
502 u32 opt;
503
504 BT_DBG("sk %p", sk);
505
506 lock_sock(sk);
507
508 switch (optname) {
509 case L2CAP_OPTIONS:
510 if (sk->sk_state == BT_CONNECTED) {
511 err = -EINVAL;
512 break;
513 }
514
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300515 opts.imtu = chan->imtu;
516 opts.omtu = chan->omtu;
517 opts.flush_to = chan->flush_to;
518 opts.mode = chan->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300519 opts.fcs = chan->fcs;
520 opts.max_tx = chan->max_tx;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300521 opts.txwin_size = chan->tx_win;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200522
523 len = min_t(unsigned int, sizeof(opts), optlen);
524 if (copy_from_user((char *) &opts, optval, len)) {
525 err = -EFAULT;
526 break;
527 }
528
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300529 if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200530 err = -EINVAL;
531 break;
532 }
533
Andre Guedes682877c2012-05-31 17:01:34 -0300534 if (!l2cap_valid_mtu(chan, opts.imtu)) {
535 err = -EINVAL;
536 break;
537 }
538
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300539 chan->mode = opts.mode;
540 switch (chan->mode) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200541 case L2CAP_MODE_BASIC:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300542 clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200543 break;
544 case L2CAP_MODE_ERTM:
545 case L2CAP_MODE_STREAMING:
546 if (!disable_ertm)
547 break;
548 /* fall through */
549 default:
550 err = -EINVAL;
551 break;
552 }
553
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300554 chan->imtu = opts.imtu;
555 chan->omtu = opts.omtu;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300556 chan->fcs = opts.fcs;
557 chan->max_tx = opts.max_tx;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +0300558 chan->tx_win = opts.txwin_size;
Andrei Emeltchenko12d59782012-10-10 17:38:26 +0300559 chan->flush_to = opts.flush_to;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200560 break;
561
562 case L2CAP_LM:
563 if (get_user(opt, (u32 __user *) optval)) {
564 err = -EFAULT;
565 break;
566 }
567
568 if (opt & L2CAP_LM_AUTH)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300569 chan->sec_level = BT_SECURITY_LOW;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200570 if (opt & L2CAP_LM_ENCRYPT)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300571 chan->sec_level = BT_SECURITY_MEDIUM;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200572 if (opt & L2CAP_LM_SECURE)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300573 chan->sec_level = BT_SECURITY_HIGH;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200574
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +0300575 if (opt & L2CAP_LM_MASTER)
576 set_bit(FLAG_ROLE_SWITCH, &chan->flags);
577 else
578 clear_bit(FLAG_ROLE_SWITCH, &chan->flags);
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300579
580 if (opt & L2CAP_LM_RELIABLE)
581 set_bit(FLAG_FORCE_RELIABLE, &chan->flags);
582 else
583 clear_bit(FLAG_FORCE_RELIABLE, &chan->flags);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200584 break;
585
586 default:
587 err = -ENOPROTOOPT;
588 break;
589 }
590
591 release_sock(sk);
592 return err;
593}
594
Gustavo Padovan2d792812012-10-06 10:07:01 +0100595static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
596 char __user *optval, unsigned int optlen)
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200597{
598 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300599 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200600 struct bt_security sec;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700601 struct bt_power pwr;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300602 struct l2cap_conn *conn;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200603 int len, err = 0;
604 u32 opt;
605
606 BT_DBG("sk %p", sk);
607
608 if (level == SOL_L2CAP)
609 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
610
611 if (level != SOL_BLUETOOTH)
612 return -ENOPROTOOPT;
613
614 lock_sock(sk);
615
616 switch (optname) {
617 case BT_SECURITY:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300618 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100619 chan->chan_type != L2CAP_CHAN_RAW) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200620 err = -EINVAL;
621 break;
622 }
623
624 sec.level = BT_SECURITY_LOW;
625
626 len = min_t(unsigned int, sizeof(sec), optlen);
627 if (copy_from_user((char *) &sec, optval, len)) {
628 err = -EFAULT;
629 break;
630 }
631
632 if (sec.level < BT_SECURITY_LOW ||
Gustavo Padovan2d792812012-10-06 10:07:01 +0100633 sec.level > BT_SECURITY_HIGH) {
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200634 err = -EINVAL;
635 break;
636 }
637
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300638 chan->sec_level = sec.level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300639
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200640 if (!chan->conn)
641 break;
642
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300643 conn = chan->conn;
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200644
645 /*change security for LE channels */
Johan Hedberg073d1cf2013-04-29 19:35:35 +0300646 if (chan->scid == L2CAP_CID_ATT) {
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300647 if (!conn->hcon->out) {
648 err = -EINVAL;
649 break;
650 }
651
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300652 if (smp_conn_security(conn->hcon, sec.level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300653 break;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300654 sk->sk_state = BT_CONFIG;
Gustavo F. Padovan3542b8542011-12-28 13:54:17 -0200655 chan->state = BT_CONFIG;
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200656
Gustavo Padovana7d77232012-05-13 03:20:07 -0300657 /* or for ACL link */
658 } else if ((sk->sk_state == BT_CONNECT2 &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100659 test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
Gustavo Padovana7d77232012-05-13 03:20:07 -0300660 sk->sk_state == BT_CONNECTED) {
661 if (!l2cap_chan_check_security(chan))
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300662 set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
Gustavo Padovana7d77232012-05-13 03:20:07 -0300663 else
664 sk->sk_state_change(sk);
Gustavo F. Padovan0bee1d62011-11-05 19:58:31 -0200665 } else {
666 err = -EINVAL;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300667 }
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200668 break;
669
670 case BT_DEFER_SETUP:
671 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
672 err = -EINVAL;
673 break;
674 }
675
676 if (get_user(opt, (u32 __user *) optval)) {
677 err = -EFAULT;
678 break;
679 }
680
Marcel Holtmannbdc25782013-10-14 02:45:34 -0700681 if (opt) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300682 set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
Marcel Holtmannbdc25782013-10-14 02:45:34 -0700683 set_bit(FLAG_DEFER_SETUP, &chan->flags);
684 } else {
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300685 clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
Marcel Holtmannbdc25782013-10-14 02:45:34 -0700686 clear_bit(FLAG_DEFER_SETUP, &chan->flags);
687 }
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200688 break;
689
690 case BT_FLUSHABLE:
691 if (get_user(opt, (u32 __user *) optval)) {
692 err = -EFAULT;
693 break;
694 }
695
696 if (opt > BT_FLUSHABLE_ON) {
697 err = -EINVAL;
698 break;
699 }
700
701 if (opt == BT_FLUSHABLE_OFF) {
Johannes Bergc1f23a22013-10-07 18:19:16 +0200702 conn = chan->conn;
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300703 /* proceed further only when we have l2cap_conn and
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200704 No Flush support in the LM */
705 if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
706 err = -EINVAL;
707 break;
708 }
709 }
710
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +0300711 if (opt)
712 set_bit(FLAG_FLUSHABLE, &chan->flags);
713 else
714 clear_bit(FLAG_FLUSHABLE, &chan->flags);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200715 break;
716
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700717 case BT_POWER:
718 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100719 chan->chan_type != L2CAP_CHAN_RAW) {
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700720 err = -EINVAL;
721 break;
722 }
723
724 pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
725
726 len = min_t(unsigned int, sizeof(pwr), optlen);
727 if (copy_from_user((char *) &pwr, optval, len)) {
728 err = -EFAULT;
729 break;
730 }
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300731
732 if (pwr.force_active)
733 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
734 else
735 clear_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700736 break;
737
Mat Martineau2ea66482011-11-02 16:18:30 -0700738 case BT_CHANNEL_POLICY:
Mat Martineau2ea66482011-11-02 16:18:30 -0700739 if (get_user(opt, (u32 __user *) optval)) {
740 err = -EFAULT;
741 break;
742 }
743
744 if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
745 err = -EINVAL;
746 break;
747 }
748
749 if (chan->mode != L2CAP_MODE_ERTM &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100750 chan->mode != L2CAP_MODE_STREAMING) {
Mat Martineau2ea66482011-11-02 16:18:30 -0700751 err = -EOPNOTSUPP;
752 break;
753 }
754
755 chan->chan_policy = (u8) opt;
Mat Martineau3f7a56c2012-10-23 15:24:23 -0700756
757 if (sk->sk_state == BT_CONNECTED &&
758 chan->move_role == L2CAP_MOVE_ROLE_NONE)
759 l2cap_move_start(chan);
760
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200761 break;
762
763 default:
764 err = -ENOPROTOOPT;
765 break;
766 }
767
768 release_sock(sk);
769 return err;
770}
771
Gustavo Padovan2d792812012-10-06 10:07:01 +0100772static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
773 struct msghdr *msg, size_t len)
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200774{
775 struct sock *sk = sock->sk;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300776 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200777 int err;
778
779 BT_DBG("sock %p, sk %p", sock, sk);
780
781 err = sock_error(sk);
782 if (err)
783 return err;
784
785 if (msg->msg_flags & MSG_OOB)
786 return -EOPNOTSUPP;
787
Mat Martineaua6a55682012-05-04 14:20:31 -0700788 if (sk->sk_state != BT_CONNECTED)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -0300789 return -ENOTCONN;
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200790
Johan Hedberge793dcf2013-09-16 13:05:19 +0300791 lock_sock(sk);
792 err = bt_sock_wait_ready(sk, msg->msg_flags);
793 release_sock(sk);
794 if (err)
795 return err;
796
Mat Martineaua6a55682012-05-04 14:20:31 -0700797 l2cap_chan_lock(chan);
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200798 err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
Mat Martineaua6a55682012-05-04 14:20:31 -0700799 l2cap_chan_unlock(chan);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200800
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200801 return err;
802}
803
Gustavo Padovan2d792812012-10-06 10:07:01 +0100804static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
805 struct msghdr *msg, size_t len, int flags)
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200806{
807 struct sock *sk = sock->sk;
Mat Martineaue3281402011-07-07 09:39:02 -0700808 struct l2cap_pinfo *pi = l2cap_pi(sk);
809 int err;
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200810
811 lock_sock(sk);
812
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300813 if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,
814 &bt_sk(sk)->flags)) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300815 sk->sk_state = BT_CONFIG;
Gustavo F. Padovan3542b8542011-12-28 13:54:17 -0200816 pi->chan->state = BT_CONFIG;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300817
Mat Martineaue3281402011-07-07 09:39:02 -0700818 __l2cap_connect_rsp_defer(pi->chan);
Johan Hedberg970871b2013-09-25 13:26:05 +0300819 err = 0;
820 goto done;
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200821 }
822
823 release_sock(sk);
824
825 if (sock->type == SOCK_STREAM)
Mat Martineaue3281402011-07-07 09:39:02 -0700826 err = bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
827 else
828 err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200829
Mat Martineaue3281402011-07-07 09:39:02 -0700830 if (pi->chan->mode != L2CAP_MODE_ERTM)
831 return err;
832
833 /* Attempt to put pending rx data in the socket buffer */
834
835 lock_sock(sk);
836
837 if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
838 goto done;
839
840 if (pi->rx_busy_skb) {
841 if (!sock_queue_rcv_skb(sk, pi->rx_busy_skb))
842 pi->rx_busy_skb = NULL;
843 else
844 goto done;
845 }
846
847 /* Restore data flow when half of the receive buffer is
848 * available. This avoids resending large numbers of
849 * frames.
850 */
851 if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
852 l2cap_chan_busy(pi->chan, 0);
853
854done:
855 release_sock(sk);
856 return err;
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200857}
858
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200859/* Kill socket (only if zapped and orphan)
860 * Must be called on unlocked socket.
861 */
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300862static void l2cap_sock_kill(struct sock *sk)
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200863{
864 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
865 return;
866
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200867 BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state));
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200868
869 /* Kill poor orphan */
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300870
Jaganath Kanakkassery4af66c62012-07-13 18:17:55 +0530871 l2cap_chan_put(l2cap_pi(sk)->chan);
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200872 sock_set_flag(sk, SOCK_DEAD);
873 sock_put(sk);
874}
875
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200876static int l2cap_sock_shutdown(struct socket *sock, int how)
877{
878 struct sock *sk = sock->sk;
Andrei Emeltchenko7ddb6e02012-02-14 15:12:57 +0200879 struct l2cap_chan *chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200880 struct l2cap_conn *conn;
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200881 int err = 0;
882
883 BT_DBG("sock %p, sk %p", sock, sk);
884
885 if (!sk)
886 return 0;
887
Andrei Emeltchenko7ddb6e02012-02-14 15:12:57 +0200888 chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200889 conn = chan->conn;
890
891 if (conn)
892 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko7ddb6e02012-02-14 15:12:57 +0200893
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200894 l2cap_chan_lock(chan);
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200895 lock_sock(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200896
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200897 if (!sk->sk_shutdown) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300898 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200899 err = __l2cap_wait_ack(sk);
900
901 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200902
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200903 release_sock(sk);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300904 l2cap_chan_close(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200905 lock_sock(sk);
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200906
907 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
908 err = bt_sock_wait_state(sk, BT_CLOSED,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100909 sk->sk_lingertime);
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200910 }
911
912 if (!err && sk->sk_err)
913 err = -sk->sk_err;
914
915 release_sock(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200916 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200917
918 if (conn)
919 mutex_unlock(&conn->chan_lock);
920
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200921 return err;
922}
923
Gustavo F. Padovan554f05b2011-02-04 02:36:42 -0200924static int l2cap_sock_release(struct socket *sock)
925{
926 struct sock *sk = sock->sk;
927 int err;
928
929 BT_DBG("sock %p, sk %p", sock, sk);
930
931 if (!sk)
932 return 0;
933
Masatake YAMATO5b28d952012-07-26 01:29:25 +0900934 bt_sock_unlink(&l2cap_sk_list, sk);
935
Gustavo F. Padovan554f05b2011-02-04 02:36:42 -0200936 err = l2cap_sock_shutdown(sock, 2);
937
938 sock_orphan(sk);
939 l2cap_sock_kill(sk);
940 return err;
941}
942
Andrei Emeltchenkoc0df7f62012-05-27 22:27:52 -0300943static void l2cap_sock_cleanup_listen(struct sock *parent)
944{
945 struct sock *sk;
946
947 BT_DBG("parent %p", parent);
948
949 /* Close not yet accepted channels */
950 while ((sk = bt_accept_dequeue(parent, NULL))) {
951 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
952
953 l2cap_chan_lock(chan);
954 __clear_chan_timer(chan);
955 l2cap_chan_close(chan, ECONNRESET);
956 l2cap_chan_unlock(chan);
957
958 l2cap_sock_kill(sk);
959 }
960}
961
Gustavo Padovan80b98022012-05-27 22:27:51 -0300962static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300963{
Gustavo Padovan80b98022012-05-27 22:27:51 -0300964 struct sock *sk, *parent = chan->data;
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300965
Gustavo Padovan53826692012-05-27 22:27:55 -0300966 /* Check for backlog size */
967 if (sk_acceptq_is_full(parent)) {
968 BT_DBG("backlog full %d", parent->sk_ack_backlog);
969 return NULL;
970 }
971
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300972 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100973 GFP_ATOMIC);
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300974 if (!sk)
975 return NULL;
976
Octavian Purdilad22015a2012-01-22 00:28:34 +0200977 bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
978
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300979 l2cap_sock_init(sk, parent);
980
Gustavo Padovan644912e2012-10-12 19:35:23 +0800981 bt_accept_enqueue(parent, sk);
982
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300983 return l2cap_pi(sk)->chan;
984}
985
Gustavo Padovan80b98022012-05-27 22:27:51 -0300986static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan23070492011-05-16 17:57:22 -0300987{
Gustavo Padovan80b98022012-05-27 22:27:51 -0300988 struct sock *sk = chan->data;
Marcel Holtmann84b34d92013-10-13 11:36:07 -0700989 int err;
Gustavo F. Padovan23070492011-05-16 17:57:22 -0300990
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200991 lock_sock(sk);
992
Marcel Holtmann84b34d92013-10-13 11:36:07 -0700993 if (l2cap_pi(sk)->rx_busy_skb) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200994 err = -ENOMEM;
995 goto done;
996 }
Mat Martineaue3281402011-07-07 09:39:02 -0700997
998 err = sock_queue_rcv_skb(sk, skb);
999
1000 /* For ERTM, handle one skb that doesn't fit into the recv
1001 * buffer. This is important to do because the data frames
1002 * have already been acked, so the skb cannot be discarded.
1003 *
1004 * Notify the l2cap core that the buffer is full, so the
1005 * LOCAL_BUSY state is entered and no more frames are
1006 * acked and reassembled until there is buffer space
1007 * available.
1008 */
Marcel Holtmann84b34d92013-10-13 11:36:07 -07001009 if (err < 0 && chan->mode == L2CAP_MODE_ERTM) {
1010 l2cap_pi(sk)->rx_busy_skb = skb;
1011 l2cap_chan_busy(chan, 1);
Mat Martineaue3281402011-07-07 09:39:02 -07001012 err = 0;
1013 }
1014
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001015done:
1016 release_sock(sk);
1017
Mat Martineaue3281402011-07-07 09:39:02 -07001018 return err;
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001019}
1020
Gustavo Padovan80b98022012-05-27 22:27:51 -03001021static void l2cap_sock_close_cb(struct l2cap_chan *chan)
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03001022{
Gustavo Padovan80b98022012-05-27 22:27:51 -03001023 struct sock *sk = chan->data;
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03001024
1025 l2cap_sock_kill(sk);
1026}
1027
Andrei Emeltchenkoc0df7f62012-05-27 22:27:52 -03001028static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err)
1029{
1030 struct sock *sk = chan->data;
1031 struct sock *parent;
1032
1033 lock_sock(sk);
1034
1035 parent = bt_sk(sk)->parent;
1036
1037 sock_set_flag(sk, SOCK_ZAPPED);
1038
1039 switch (chan->state) {
1040 case BT_OPEN:
1041 case BT_BOUND:
1042 case BT_CLOSED:
1043 break;
1044 case BT_LISTEN:
1045 l2cap_sock_cleanup_listen(sk);
1046 sk->sk_state = BT_CLOSED;
1047 chan->state = BT_CLOSED;
1048
1049 break;
1050 default:
1051 sk->sk_state = BT_CLOSED;
1052 chan->state = BT_CLOSED;
1053
1054 sk->sk_err = err;
1055
1056 if (parent) {
1057 bt_accept_unlink(sk);
1058 parent->sk_data_ready(parent, 0);
1059 } else {
1060 sk->sk_state_change(sk);
1061 }
1062
1063 break;
1064 }
1065
1066 release_sock(sk);
1067}
1068
Gustavo Padovan80b98022012-05-27 22:27:51 -03001069static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001070{
Gustavo Padovan80b98022012-05-27 22:27:51 -03001071 struct sock *sk = chan->data;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001072
1073 sk->sk_state = state;
1074}
1075
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001076static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
Gustavo Padovan90338942012-04-06 20:15:47 -03001077 unsigned long len, int nb)
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001078{
Gustavo Padovan90338942012-04-06 20:15:47 -03001079 struct sk_buff *skb;
1080 int err;
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001081
Mat Martineaua6a55682012-05-04 14:20:31 -07001082 l2cap_chan_unlock(chan);
Gustavo Padovan90338942012-04-06 20:15:47 -03001083 skb = bt_skb_send_alloc(chan->sk, len, nb, &err);
Mat Martineaua6a55682012-05-04 14:20:31 -07001084 l2cap_chan_lock(chan);
1085
Gustavo Padovan90338942012-04-06 20:15:47 -03001086 if (!skb)
1087 return ERR_PTR(err);
1088
1089 return skb;
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001090}
1091
Andrei Emeltchenko54a59aa2012-05-27 22:27:53 -03001092static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
1093{
1094 struct sock *sk = chan->data;
1095 struct sock *parent;
1096
1097 lock_sock(sk);
1098
1099 parent = bt_sk(sk)->parent;
1100
1101 BT_DBG("sk %p, parent %p", sk, parent);
1102
1103 sk->sk_state = BT_CONNECTED;
1104 sk->sk_state_change(sk);
1105
1106 if (parent)
1107 parent->sk_data_ready(parent, 0);
1108
1109 release_sock(sk);
1110}
1111
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08001112static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
1113{
1114 struct sock *sk = chan->data;
1115 struct sock *parent = bt_sk(sk)->parent;
1116
1117 if (parent)
1118 parent->sk_data_ready(parent, 0);
1119}
1120
Marcel Holtmannd97c8992013-10-14 02:53:54 -07001121static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
1122{
1123 struct sock *sk = chan->data;
1124
1125 clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
1126 sk->sk_state_change(sk);
1127}
1128
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001129static struct l2cap_ops l2cap_chan_ops = {
1130 .name = "L2CAP Socket Interface",
1131 .new_connection = l2cap_sock_new_connection_cb,
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001132 .recv = l2cap_sock_recv_cb,
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03001133 .close = l2cap_sock_close_cb,
Andrei Emeltchenkoc0df7f62012-05-27 22:27:52 -03001134 .teardown = l2cap_sock_teardown_cb,
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001135 .state_change = l2cap_sock_state_change_cb,
Andrei Emeltchenko54a59aa2012-05-27 22:27:53 -03001136 .ready = l2cap_sock_ready_cb,
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08001137 .defer = l2cap_sock_defer_cb,
Marcel Holtmannd97c8992013-10-14 02:53:54 -07001138 .resume = l2cap_sock_resume_cb,
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001139 .alloc_skb = l2cap_sock_alloc_skb_cb,
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001140};
1141
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001142static void l2cap_sock_destruct(struct sock *sk)
1143{
1144 BT_DBG("sk %p", sk);
1145
Sasha Levin23d3a862012-10-08 16:48:32 -04001146 if (l2cap_pi(sk)->chan)
1147 l2cap_chan_put(l2cap_pi(sk)->chan);
Marcel Holtmann84b34d92013-10-13 11:36:07 -07001148
Mat Martineaue3281402011-07-07 09:39:02 -07001149 if (l2cap_pi(sk)->rx_busy_skb) {
1150 kfree_skb(l2cap_pi(sk)->rx_busy_skb);
1151 l2cap_pi(sk)->rx_busy_skb = NULL;
1152 }
1153
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001154 skb_queue_purge(&sk->sk_receive_queue);
1155 skb_queue_purge(&sk->sk_write_queue);
1156}
1157
Marcel Holtmann2edf8702013-10-13 12:55:29 -07001158static void l2cap_skb_msg_name(struct sk_buff *skb, void *msg_name,
1159 int *msg_namelen)
1160{
1161 struct sockaddr_l2 *la = (struct sockaddr_l2 *) msg_name;
1162
1163 memset(la, 0, sizeof(struct sockaddr_l2));
1164 la->l2_family = AF_BLUETOOTH;
1165 la->l2_psm = bt_cb(skb)->psm;
1166 bacpy(&la->l2_bdaddr, &bt_cb(skb)->bdaddr);
1167
1168 *msg_namelen = sizeof(struct sockaddr_l2);
1169}
1170
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001171static void l2cap_sock_init(struct sock *sk, struct sock *parent)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001172{
Marcel Holtmann84b34d92013-10-13 11:36:07 -07001173 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001174
1175 BT_DBG("sk %p", sk);
1176
1177 if (parent) {
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001178 struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
1179
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001180 sk->sk_type = parent->sk_type;
Gustavo Padovanc5daa682012-05-16 12:17:10 -03001181 bt_sk(sk)->flags = bt_sk(parent)->flags;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001182
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001183 chan->chan_type = pchan->chan_type;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001184 chan->imtu = pchan->imtu;
1185 chan->omtu = pchan->omtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001186 chan->conf_state = pchan->conf_state;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001187 chan->mode = pchan->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001188 chan->fcs = pchan->fcs;
1189 chan->max_tx = pchan->max_tx;
1190 chan->tx_win = pchan->tx_win;
Andrei Emeltchenko6b3c7102011-11-02 09:57:10 +02001191 chan->tx_win_max = pchan->tx_win_max;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001192 chan->sec_level = pchan->sec_level;
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001193 chan->flags = pchan->flags;
Paul Moore6230c9b2011-10-07 09:40:59 +00001194
1195 security_sk_clone(parent, sk);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001196 } else {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001197 switch (sk->sk_type) {
1198 case SOCK_RAW:
1199 chan->chan_type = L2CAP_CHAN_RAW;
1200 break;
1201 case SOCK_DGRAM:
1202 chan->chan_type = L2CAP_CHAN_CONN_LESS;
Marcel Holtmann2edf8702013-10-13 12:55:29 -07001203 bt_sk(sk)->skb_msg_name = l2cap_skb_msg_name;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001204 break;
1205 case SOCK_SEQPACKET:
1206 case SOCK_STREAM:
1207 chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
1208 break;
1209 }
1210
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001211 chan->imtu = L2CAP_DEFAULT_MTU;
1212 chan->omtu = 0;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001213 if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001214 chan->mode = L2CAP_MODE_ERTM;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001215 set_bit(CONF_STATE2_DEVICE, &chan->conf_state);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001216 } else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001217 chan->mode = L2CAP_MODE_BASIC;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001218 }
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +03001219
1220 l2cap_chan_set_defaults(chan);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001221 }
1222
1223 /* Default config options */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001224 chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001225
1226 chan->data = sk;
1227 chan->ops = &l2cap_chan_ops;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001228}
1229
1230static struct proto l2cap_proto = {
1231 .name = "L2CAP",
1232 .owner = THIS_MODULE,
1233 .obj_size = sizeof(struct l2cap_pinfo)
1234};
1235
Gustavo Padovan2d792812012-10-06 10:07:01 +01001236static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
1237 int proto, gfp_t prio)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001238{
1239 struct sock *sk;
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001240 struct l2cap_chan *chan;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001241
1242 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
1243 if (!sk)
1244 return NULL;
1245
1246 sock_init_data(sock, sk);
1247 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
1248
1249 sk->sk_destruct = l2cap_sock_destruct;
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08001250 sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001251
1252 sock_reset_flag(sk, SOCK_ZAPPED);
1253
1254 sk->sk_protocol = proto;
1255 sk->sk_state = BT_OPEN;
1256
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -03001257 chan = l2cap_chan_create();
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001258 if (!chan) {
Jaganath Kanakkassery49dfbb92012-07-19 12:54:04 +05301259 sk_free(sk);
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001260 return NULL;
1261 }
1262
Mat Martineau61d6ef32012-04-27 16:50:50 -07001263 l2cap_chan_hold(chan);
1264
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -03001265 chan->sk = sk;
1266
Gustavo F. Padovandc50a062011-05-16 16:42:01 -03001267 l2cap_pi(sk)->chan = chan;
1268
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001269 return sk;
1270}
1271
1272static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
1273 int kern)
1274{
1275 struct sock *sk;
1276
1277 BT_DBG("sock %p", sock);
1278
1279 sock->state = SS_UNCONNECTED;
1280
1281 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01001282 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001283 return -ESOCKTNOSUPPORT;
1284
1285 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
1286 return -EPERM;
1287
1288 sock->ops = &l2cap_sock_ops;
1289
1290 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
1291 if (!sk)
1292 return -ENOMEM;
1293
1294 l2cap_sock_init(sk, NULL);
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001295 bt_sock_link(&l2cap_sk_list, sk);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001296 return 0;
1297}
1298
Gustavo F. Padovancf2f90f2011-04-27 18:40:39 -03001299static const struct proto_ops l2cap_sock_ops = {
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001300 .family = PF_BLUETOOTH,
1301 .owner = THIS_MODULE,
1302 .release = l2cap_sock_release,
1303 .bind = l2cap_sock_bind,
1304 .connect = l2cap_sock_connect,
1305 .listen = l2cap_sock_listen,
1306 .accept = l2cap_sock_accept,
1307 .getname = l2cap_sock_getname,
1308 .sendmsg = l2cap_sock_sendmsg,
1309 .recvmsg = l2cap_sock_recvmsg,
1310 .poll = bt_sock_poll,
1311 .ioctl = bt_sock_ioctl,
1312 .mmap = sock_no_mmap,
1313 .socketpair = sock_no_socketpair,
1314 .shutdown = l2cap_sock_shutdown,
1315 .setsockopt = l2cap_sock_setsockopt,
1316 .getsockopt = l2cap_sock_getsockopt
1317};
1318
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001319static const struct net_proto_family l2cap_sock_family_ops = {
1320 .family = PF_BLUETOOTH,
1321 .owner = THIS_MODULE,
1322 .create = l2cap_sock_create,
1323};
1324
1325int __init l2cap_init_sockets(void)
1326{
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001327 int err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001328
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001329 err = proto_register(&l2cap_proto, 0);
1330 if (err < 0)
1331 return err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001332
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001333 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001334 if (err < 0) {
1335 BT_ERR("L2CAP socket registration failed");
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001336 goto error;
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001337 }
1338
Al Virob0316612013-04-04 19:14:33 -04001339 err = bt_procfs_init(&init_net, "l2cap", &l2cap_sk_list,
Gustavo Padovan2d792812012-10-06 10:07:01 +01001340 NULL);
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001341 if (err < 0) {
1342 BT_ERR("Failed to create L2CAP proc file");
1343 bt_sock_unregister(BTPROTO_L2CAP);
1344 goto error;
1345 }
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001346
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001347 BT_INFO("L2CAP socket layer initialized");
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001348
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001349 return 0;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001350
1351error:
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001352 proto_unregister(&l2cap_proto);
1353 return err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001354}
1355
1356void l2cap_cleanup_sockets(void)
1357{
Masatake YAMATO5b28d952012-07-26 01:29:25 +09001358 bt_procfs_cleanup(&init_net, "l2cap");
David Herrmann5e9d7f82013-02-24 19:36:51 +01001359 bt_sock_unregister(BTPROTO_L2CAP);
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001360 proto_unregister(&l2cap_proto);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001361}