blob: 4ba15b3b2e6a08f6fe27f2110efd31c4df44dd8a [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.
6
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
17 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
22 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
24 SOFTWARE IS DISCLAIMED.
25*/
26
27/* Bluetooth L2CAP sockets. */
28
29#include <net/bluetooth/bluetooth.h>
Gustavo F. Padovan33575df2011-02-04 02:48:48 -020030#include <net/bluetooth/hci_core.h>
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020031#include <net/bluetooth/l2cap.h>
32
Gustavo F. Padovan6ddc0482011-02-04 03:23:31 -020033/* ---- L2CAP timers ---- */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020034static void l2cap_sock_timeout(unsigned long arg)
35{
36 struct sock *sk = (struct sock *) arg;
37 int reason;
38
39 BT_DBG("sock %p state %d", sk, sk->sk_state);
40
41 bh_lock_sock(sk);
42
43 if (sock_owned_by_user(sk)) {
44 /* sk is owned by user. Try again later */
45 l2cap_sock_set_timer(sk, HZ / 5);
46 bh_unlock_sock(sk);
47 sock_put(sk);
48 return;
49 }
50
51 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
52 reason = ECONNREFUSED;
53 else if (sk->sk_state == BT_CONNECT &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -030054 l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020055 reason = ECONNREFUSED;
56 else
57 reason = ETIMEDOUT;
58
59 __l2cap_sock_close(sk, reason);
60
61 bh_unlock_sock(sk);
62
63 l2cap_sock_kill(sk);
64 sock_put(sk);
65}
66
Gustavo F. Padovan6ddc0482011-02-04 03:23:31 -020067void l2cap_sock_set_timer(struct sock *sk, long timeout)
68{
69 BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
70 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
71}
72
73void l2cap_sock_clear_timer(struct sock *sk)
74{
75 BT_DBG("sock %p state %d", sk, sk->sk_state);
76 sk_stop_timer(sk, &sk->sk_timer);
77}
78
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -020079static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
80{
81 struct sock *sk;
82 struct hlist_node *node;
83 sk_for_each(sk, node, &l2cap_sk_list.head)
84 if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
85 goto found;
86 sk = NULL;
87found:
88 return sk;
89}
90
91static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
92{
93 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -030094 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -020095 struct sockaddr_l2 la;
96 int len, err = 0;
97
98 BT_DBG("sk %p", sk);
99
100 if (!addr || addr->sa_family != AF_BLUETOOTH)
101 return -EINVAL;
102
103 memset(&la, 0, sizeof(la));
104 len = min_t(unsigned int, sizeof(la), alen);
105 memcpy(&la, addr, len);
106
Ville Tervob62f3282011-02-10 22:38:50 -0300107 if (la.l2_cid && la.l2_psm)
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200108 return -EINVAL;
109
110 lock_sock(sk);
111
112 if (sk->sk_state != BT_OPEN) {
113 err = -EBADFD;
114 goto done;
115 }
116
117 if (la.l2_psm) {
118 __u16 psm = __le16_to_cpu(la.l2_psm);
119
120 /* PSM must be odd and lsb of upper byte must be 0 */
121 if ((psm & 0x0101) != 0x0001) {
122 err = -EINVAL;
123 goto done;
124 }
125
126 /* Restrict usage of well-known PSMs */
127 if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
128 err = -EACCES;
129 goto done;
130 }
131 }
132
133 write_lock_bh(&l2cap_sk_list.lock);
134
135 if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
136 err = -EADDRINUSE;
137 } else {
138 /* Save source address */
139 bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
140 l2cap_pi(sk)->psm = la.l2_psm;
141 l2cap_pi(sk)->sport = la.l2_psm;
142 sk->sk_state = BT_BOUND;
143
144 if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
145 __le16_to_cpu(la.l2_psm) == 0x0003)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300146 chan->sec_level = BT_SECURITY_SDP;
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200147 }
148
Ville Tervob62f3282011-02-10 22:38:50 -0300149 if (la.l2_cid)
150 l2cap_pi(sk)->scid = la.l2_cid;
151
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200152 write_unlock_bh(&l2cap_sk_list.lock);
153
154done:
155 release_sock(sk);
156 return err;
157}
158
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200159static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
160{
161 struct sock *sk = sock->sk;
162 struct sockaddr_l2 la;
163 int len, err = 0;
164
165 BT_DBG("sk %p", sk);
166
167 if (!addr || alen < sizeof(addr->sa_family) ||
168 addr->sa_family != AF_BLUETOOTH)
169 return -EINVAL;
170
171 memset(&la, 0, sizeof(la));
172 len = min_t(unsigned int, sizeof(la), alen);
173 memcpy(&la, addr, len);
174
Ville Tervoacd7d372011-02-10 22:38:49 -0300175 if (la.l2_cid && la.l2_psm)
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200176 return -EINVAL;
177
178 lock_sock(sk);
179
180 if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
Ville Tervoacd7d372011-02-10 22:38:49 -0300181 && !(la.l2_psm || la.l2_cid)) {
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200182 err = -EINVAL;
183 goto done;
184 }
185
186 switch (l2cap_pi(sk)->mode) {
187 case L2CAP_MODE_BASIC:
188 break;
189 case L2CAP_MODE_ERTM:
190 case L2CAP_MODE_STREAMING:
191 if (!disable_ertm)
192 break;
193 /* fall through */
194 default:
195 err = -ENOTSUPP;
196 goto done;
197 }
198
199 switch (sk->sk_state) {
200 case BT_CONNECT:
201 case BT_CONNECT2:
202 case BT_CONFIG:
203 /* Already connecting */
204 goto wait;
205
206 case BT_CONNECTED:
207 /* Already connected */
208 err = -EISCONN;
209 goto done;
210
211 case BT_OPEN:
212 case BT_BOUND:
213 /* Can connect */
214 break;
215
216 default:
217 err = -EBADFD;
218 goto done;
219 }
220
221 /* PSM must be odd and lsb of upper byte must be 0 */
222 if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
Ville Tervoacd7d372011-02-10 22:38:49 -0300223 sk->sk_type != SOCK_RAW && !la.l2_cid) {
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200224 err = -EINVAL;
225 goto done;
226 }
227
228 /* Set destination address and psm */
229 bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
230 l2cap_pi(sk)->psm = la.l2_psm;
Ville Tervoacd7d372011-02-10 22:38:49 -0300231 l2cap_pi(sk)->dcid = la.l2_cid;
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200232
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300233 err = l2cap_chan_connect(l2cap_pi(sk)->chan);
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200234 if (err)
235 goto done;
236
237wait:
238 err = bt_sock_wait_state(sk, BT_CONNECTED,
239 sock_sndtimeo(sk, flags & O_NONBLOCK));
240done:
241 release_sock(sk);
242 return err;
243}
244
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200245static int l2cap_sock_listen(struct socket *sock, int backlog)
246{
247 struct sock *sk = sock->sk;
248 int err = 0;
249
250 BT_DBG("sk %p backlog %d", sk, backlog);
251
252 lock_sock(sk);
253
254 if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
255 || sk->sk_state != BT_BOUND) {
256 err = -EBADFD;
257 goto done;
258 }
259
260 switch (l2cap_pi(sk)->mode) {
261 case L2CAP_MODE_BASIC:
262 break;
263 case L2CAP_MODE_ERTM:
264 case L2CAP_MODE_STREAMING:
265 if (!disable_ertm)
266 break;
267 /* fall through */
268 default:
269 err = -ENOTSUPP;
270 goto done;
271 }
272
Gustavo F. Padovancd69a032011-04-05 15:24:40 -0300273 if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) {
Gustavo F. Padovanaf6bcd82011-02-04 02:40:28 -0200274 bdaddr_t *src = &bt_sk(sk)->src;
275 u16 psm;
276
277 err = -EINVAL;
278
279 write_lock_bh(&l2cap_sk_list.lock);
280
281 for (psm = 0x1001; psm < 0x1100; psm += 2)
282 if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
283 l2cap_pi(sk)->psm = cpu_to_le16(psm);
284 l2cap_pi(sk)->sport = cpu_to_le16(psm);
285 err = 0;
286 break;
287 }
288
289 write_unlock_bh(&l2cap_sk_list.lock);
290
291 if (err < 0)
292 goto done;
293 }
294
295 sk->sk_max_ack_backlog = backlog;
296 sk->sk_ack_backlog = 0;
297 sk->sk_state = BT_LISTEN;
298
299done:
300 release_sock(sk);
301 return err;
302}
303
Gustavo F. Padovanc47b7c72011-02-04 02:42:23 -0200304static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
305{
306 DECLARE_WAITQUEUE(wait, current);
307 struct sock *sk = sock->sk, *nsk;
308 long timeo;
309 int err = 0;
310
311 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
312
313 if (sk->sk_state != BT_LISTEN) {
314 err = -EBADFD;
315 goto done;
316 }
317
318 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
319
320 BT_DBG("sk %p timeo %ld", sk, timeo);
321
322 /* Wait for an incoming connection. (wake-one). */
323 add_wait_queue_exclusive(sk_sleep(sk), &wait);
324 while (!(nsk = bt_accept_dequeue(sk, newsock))) {
325 set_current_state(TASK_INTERRUPTIBLE);
326 if (!timeo) {
327 err = -EAGAIN;
328 break;
329 }
330
331 release_sock(sk);
332 timeo = schedule_timeout(timeo);
333 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
334
335 if (sk->sk_state != BT_LISTEN) {
336 err = -EBADFD;
337 break;
338 }
339
340 if (signal_pending(current)) {
341 err = sock_intr_errno(timeo);
342 break;
343 }
344 }
345 set_current_state(TASK_RUNNING);
346 remove_wait_queue(sk_sleep(sk), &wait);
347
348 if (err)
349 goto done;
350
351 newsock->state = SS_CONNECTED;
352
353 BT_DBG("new socket %p", nsk);
354
355done:
356 release_sock(sk);
357 return err;
358}
359
Gustavo F. Padovand7175d52011-02-04 02:43:46 -0200360static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
361{
362 struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
363 struct sock *sk = sock->sk;
364
365 BT_DBG("sock %p, sk %p", sock, sk);
366
367 addr->sa_family = AF_BLUETOOTH;
368 *len = sizeof(struct sockaddr_l2);
369
370 if (peer) {
371 la->l2_psm = l2cap_pi(sk)->psm;
372 bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
373 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
374 } else {
375 la->l2_psm = l2cap_pi(sk)->sport;
376 bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
377 la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
378 }
379
380 return 0;
381}
382
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200383static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
384{
385 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300386 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200387 struct l2cap_options opts;
388 struct l2cap_conninfo cinfo;
389 int len, err = 0;
390 u32 opt;
391
392 BT_DBG("sk %p", sk);
393
394 if (get_user(len, optlen))
395 return -EFAULT;
396
397 lock_sock(sk);
398
399 switch (optname) {
400 case L2CAP_OPTIONS:
Vasiliy Kulikove3fb5922011-02-10 20:59:42 +0300401 memset(&opts, 0, sizeof(opts));
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200402 opts.imtu = l2cap_pi(sk)->imtu;
403 opts.omtu = l2cap_pi(sk)->omtu;
404 opts.flush_to = l2cap_pi(sk)->flush_to;
405 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300406 opts.fcs = chan->fcs;
407 opts.max_tx = chan->max_tx;
408 opts.txwin_size = (__u16)chan->tx_win;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200409
410 len = min_t(unsigned int, len, sizeof(opts));
411 if (copy_to_user(optval, (char *) &opts, len))
412 err = -EFAULT;
413
414 break;
415
416 case L2CAP_LM:
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300417 switch (chan->sec_level) {
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200418 case BT_SECURITY_LOW:
419 opt = L2CAP_LM_AUTH;
420 break;
421 case BT_SECURITY_MEDIUM:
422 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
423 break;
424 case BT_SECURITY_HIGH:
425 opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
426 L2CAP_LM_SECURE;
427 break;
428 default:
429 opt = 0;
430 break;
431 }
432
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300433 if (chan->role_switch)
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200434 opt |= L2CAP_LM_MASTER;
435
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300436 if (chan->force_reliable)
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200437 opt |= L2CAP_LM_RELIABLE;
438
439 if (put_user(opt, (u32 __user *) optval))
440 err = -EFAULT;
441 break;
442
443 case L2CAP_CONNINFO:
444 if (sk->sk_state != BT_CONNECTED &&
445 !(sk->sk_state == BT_CONNECT2 &&
446 bt_sk(sk)->defer_setup)) {
447 err = -ENOTCONN;
448 break;
449 }
450
451 cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
452 memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
453
454 len = min_t(unsigned int, len, sizeof(cinfo));
455 if (copy_to_user(optval, (char *) &cinfo, len))
456 err = -EFAULT;
457
458 break;
459
460 default:
461 err = -ENOPROTOOPT;
462 break;
463 }
464
465 release_sock(sk);
466 return err;
467}
468
469static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
470{
471 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300472 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200473 struct bt_security sec;
474 int len, err = 0;
475
476 BT_DBG("sk %p", sk);
477
478 if (level == SOL_L2CAP)
479 return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
480
481 if (level != SOL_BLUETOOTH)
482 return -ENOPROTOOPT;
483
484 if (get_user(len, optlen))
485 return -EFAULT;
486
487 lock_sock(sk);
488
489 switch (optname) {
490 case BT_SECURITY:
491 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
492 && sk->sk_type != SOCK_RAW) {
493 err = -EINVAL;
494 break;
495 }
496
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300497 sec.level = chan->sec_level;
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200498
499 len = min_t(unsigned int, len, sizeof(sec));
500 if (copy_to_user(optval, (char *) &sec, len))
501 err = -EFAULT;
502
503 break;
504
505 case BT_DEFER_SETUP:
506 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
507 err = -EINVAL;
508 break;
509 }
510
511 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
512 err = -EFAULT;
513
514 break;
515
516 case BT_FLUSHABLE:
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300517 if (put_user(chan->flushable, (u32 __user *) optval))
Gustavo F. Padovan99f48082011-02-04 02:52:55 -0200518 err = -EFAULT;
519
520 break;
521
522 default:
523 err = -ENOPROTOOPT;
524 break;
525 }
526
527 release_sock(sk);
528 return err;
529}
530
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200531static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
532{
533 struct sock *sk = sock->sk;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300534 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200535 struct l2cap_options opts;
536 int len, err = 0;
537 u32 opt;
538
539 BT_DBG("sk %p", sk);
540
541 lock_sock(sk);
542
543 switch (optname) {
544 case L2CAP_OPTIONS:
545 if (sk->sk_state == BT_CONNECTED) {
546 err = -EINVAL;
547 break;
548 }
549
550 opts.imtu = l2cap_pi(sk)->imtu;
551 opts.omtu = l2cap_pi(sk)->omtu;
552 opts.flush_to = l2cap_pi(sk)->flush_to;
553 opts.mode = l2cap_pi(sk)->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300554 opts.fcs = chan->fcs;
555 opts.max_tx = chan->max_tx;
556 opts.txwin_size = (__u16)chan->tx_win;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200557
558 len = min_t(unsigned int, sizeof(opts), optlen);
559 if (copy_from_user((char *) &opts, optval, len)) {
560 err = -EFAULT;
561 break;
562 }
563
564 if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
565 err = -EINVAL;
566 break;
567 }
568
569 l2cap_pi(sk)->mode = opts.mode;
570 switch (l2cap_pi(sk)->mode) {
571 case L2CAP_MODE_BASIC:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300572 chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200573 break;
574 case L2CAP_MODE_ERTM:
575 case L2CAP_MODE_STREAMING:
576 if (!disable_ertm)
577 break;
578 /* fall through */
579 default:
580 err = -EINVAL;
581 break;
582 }
583
584 l2cap_pi(sk)->imtu = opts.imtu;
585 l2cap_pi(sk)->omtu = opts.omtu;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300586 chan->fcs = opts.fcs;
587 chan->max_tx = opts.max_tx;
588 chan->tx_win = (__u8)opts.txwin_size;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200589 break;
590
591 case L2CAP_LM:
592 if (get_user(opt, (u32 __user *) optval)) {
593 err = -EFAULT;
594 break;
595 }
596
597 if (opt & L2CAP_LM_AUTH)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300598 chan->sec_level = BT_SECURITY_LOW;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200599 if (opt & L2CAP_LM_ENCRYPT)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300600 chan->sec_level = BT_SECURITY_MEDIUM;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200601 if (opt & L2CAP_LM_SECURE)
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300602 chan->sec_level = BT_SECURITY_HIGH;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200603
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300604 chan->role_switch = (opt & L2CAP_LM_MASTER);
605 chan->force_reliable = (opt & L2CAP_LM_RELIABLE);
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200606 break;
607
608 default:
609 err = -ENOPROTOOPT;
610 break;
611 }
612
613 release_sock(sk);
614 return err;
615}
616
617static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
618{
619 struct sock *sk = sock->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300620 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200621 struct bt_security sec;
622 int len, err = 0;
623 u32 opt;
624
625 BT_DBG("sk %p", sk);
626
627 if (level == SOL_L2CAP)
628 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
629
630 if (level != SOL_BLUETOOTH)
631 return -ENOPROTOOPT;
632
633 lock_sock(sk);
634
635 switch (optname) {
636 case BT_SECURITY:
637 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
638 && sk->sk_type != SOCK_RAW) {
639 err = -EINVAL;
640 break;
641 }
642
643 sec.level = BT_SECURITY_LOW;
644
645 len = min_t(unsigned int, sizeof(sec), optlen);
646 if (copy_from_user((char *) &sec, optval, len)) {
647 err = -EFAULT;
648 break;
649 }
650
651 if (sec.level < BT_SECURITY_LOW ||
652 sec.level > BT_SECURITY_HIGH) {
653 err = -EINVAL;
654 break;
655 }
656
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300657 chan->sec_level = sec.level;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200658 break;
659
660 case BT_DEFER_SETUP:
661 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
662 err = -EINVAL;
663 break;
664 }
665
666 if (get_user(opt, (u32 __user *) optval)) {
667 err = -EFAULT;
668 break;
669 }
670
671 bt_sk(sk)->defer_setup = opt;
672 break;
673
674 case BT_FLUSHABLE:
675 if (get_user(opt, (u32 __user *) optval)) {
676 err = -EFAULT;
677 break;
678 }
679
680 if (opt > BT_FLUSHABLE_ON) {
681 err = -EINVAL;
682 break;
683 }
684
685 if (opt == BT_FLUSHABLE_OFF) {
686 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
687 /* proceed futher only when we have l2cap_conn and
688 No Flush support in the LM */
689 if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
690 err = -EINVAL;
691 break;
692 }
693 }
694
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300695 chan->flushable = opt;
Gustavo F. Padovan33575df2011-02-04 02:48:48 -0200696 break;
697
698 default:
699 err = -ENOPROTOOPT;
700 break;
701 }
702
703 release_sock(sk);
704 return err;
705}
706
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200707static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
708{
709 struct sock *sk = sock->sk;
710 struct l2cap_pinfo *pi = l2cap_pi(sk);
711 struct sk_buff *skb;
712 u16 control;
713 int err;
714
715 BT_DBG("sock %p, sk %p", sock, sk);
716
717 err = sock_error(sk);
718 if (err)
719 return err;
720
721 if (msg->msg_flags & MSG_OOB)
722 return -EOPNOTSUPP;
723
724 lock_sock(sk);
725
726 if (sk->sk_state != BT_CONNECTED) {
727 err = -ENOTCONN;
728 goto done;
729 }
730
731 /* Connectionless channel */
732 if (sk->sk_type == SOCK_DGRAM) {
733 skb = l2cap_create_connless_pdu(sk, msg, len);
734 if (IS_ERR(skb)) {
735 err = PTR_ERR(skb);
736 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300737 l2cap_do_send(pi->chan, skb);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200738 err = len;
739 }
740 goto done;
741 }
742
743 switch (pi->mode) {
744 case L2CAP_MODE_BASIC:
745 /* Check outgoing MTU */
746 if (len > pi->omtu) {
747 err = -EMSGSIZE;
748 goto done;
749 }
750
751 /* Create a basic PDU */
752 skb = l2cap_create_basic_pdu(sk, msg, len);
753 if (IS_ERR(skb)) {
754 err = PTR_ERR(skb);
755 goto done;
756 }
757
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300758 l2cap_do_send(pi->chan, skb);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200759 err = len;
760 break;
761
762 case L2CAP_MODE_ERTM:
763 case L2CAP_MODE_STREAMING:
764 /* Entire SDU fits into one PDU */
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300765 if (len <= pi->chan->remote_mps) {
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200766 control = L2CAP_SDU_UNSEGMENTED;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300767 skb = l2cap_create_iframe_pdu(pi->chan, msg, len,
768 control, 0);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200769 if (IS_ERR(skb)) {
770 err = PTR_ERR(skb);
771 goto done;
772 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300773 __skb_queue_tail(&pi->chan->tx_q, skb);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200774
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300775 if (pi->chan->tx_send_head == NULL)
776 pi->chan->tx_send_head = skb;
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200777
778 } else {
779 /* Segment SDU into multiples PDUs */
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300780 err = l2cap_sar_segment_sdu(pi->chan, msg, len);
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200781 if (err < 0)
782 goto done;
783 }
784
785 if (pi->mode == L2CAP_MODE_STREAMING) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300786 l2cap_streaming_send(pi->chan);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300787 err = len;
788 break;
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200789 }
790
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300791 if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
792 (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) {
793 err = len;
794 break;
795 }
796 err = l2cap_ertm_send(pi->chan);
797
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200798 if (err >= 0)
799 err = len;
800 break;
801
802 default:
803 BT_DBG("bad state %1.1x", pi->mode);
804 err = -EBADFD;
805 }
806
807done:
808 release_sock(sk);
809 return err;
810}
811
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200812static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
813{
814 struct sock *sk = sock->sk;
815
816 lock_sock(sk);
817
818 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -0300819 __l2cap_connect_rsp_defer(sk);
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200820 release_sock(sk);
821 return 0;
822 }
823
824 release_sock(sk);
825
826 if (sock->type == SOCK_STREAM)
827 return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
828
829 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
830}
831
Gustavo F. Padovan05fc1572011-02-04 03:26:01 -0200832/* Kill socket (only if zapped and orphan)
833 * Must be called on unlocked socket.
834 */
835void l2cap_sock_kill(struct sock *sk)
836{
837 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
838 return;
839
840 BT_DBG("sk %p state %d", sk, sk->sk_state);
841
842 /* Kill poor orphan */
843 bt_sock_unlink(&l2cap_sk_list, sk);
844 sock_set_flag(sk, SOCK_DEAD);
845 sock_put(sk);
846}
847
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200848/* Must be called on unlocked socket. */
849static void l2cap_sock_close(struct sock *sk)
850{
851 l2cap_sock_clear_timer(sk);
852 lock_sock(sk);
853 __l2cap_sock_close(sk, ECONNRESET);
854 release_sock(sk);
855 l2cap_sock_kill(sk);
856}
857
858static void l2cap_sock_cleanup_listen(struct sock *parent)
859{
860 struct sock *sk;
861
862 BT_DBG("parent %p", parent);
863
864 /* Close not yet accepted channels */
865 while ((sk = bt_accept_dequeue(parent, NULL)))
866 l2cap_sock_close(sk);
867
868 parent->sk_state = BT_CLOSED;
869 sock_set_flag(parent, SOCK_ZAPPED);
870}
871
872void __l2cap_sock_close(struct sock *sk, int reason)
873{
Ville Tervo5589fa92011-02-10 22:38:51 -0300874 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300875 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Ville Tervo5589fa92011-02-10 22:38:51 -0300876
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200877 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
878
879 switch (sk->sk_state) {
880 case BT_LISTEN:
881 l2cap_sock_cleanup_listen(sk);
882 break;
883
884 case BT_CONNECTED:
885 case BT_CONFIG:
Ville Tervo5589fa92011-02-10 22:38:51 -0300886 if ((sk->sk_type == SOCK_SEQPACKET ||
887 sk->sk_type == SOCK_STREAM) &&
888 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200889 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300890 l2cap_send_disconn_req(conn, chan, reason);
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200891 } else
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300892 l2cap_chan_del(chan, reason);
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200893 break;
894
895 case BT_CONNECT2:
Ville Tervo5589fa92011-02-10 22:38:51 -0300896 if ((sk->sk_type == SOCK_SEQPACKET ||
897 sk->sk_type == SOCK_STREAM) &&
898 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200899 struct l2cap_conn_rsp rsp;
900 __u16 result;
901
902 if (bt_sk(sk)->defer_setup)
903 result = L2CAP_CR_SEC_BLOCK;
904 else
905 result = L2CAP_CR_BAD_PSM;
906
907 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
908 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
909 rsp.result = cpu_to_le16(result);
910 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300911 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
912 sizeof(rsp), &rsp);
Andrei Emeltchenko34bd0272011-03-24 17:16:08 +0200913 }
914
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300915 l2cap_chan_del(chan, reason);
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200916 break;
917
918 case BT_CONNECT:
919 case BT_DISCONN:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300920 l2cap_chan_del(chan, reason);
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200921 break;
922
923 default:
924 sock_set_flag(sk, SOCK_ZAPPED);
925 break;
926 }
927}
928
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200929static int l2cap_sock_shutdown(struct socket *sock, int how)
930{
931 struct sock *sk = sock->sk;
932 int err = 0;
933
934 BT_DBG("sock %p, sk %p", sock, sk);
935
936 if (!sk)
937 return 0;
938
939 lock_sock(sk);
940 if (!sk->sk_shutdown) {
941 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
942 err = __l2cap_wait_ack(sk);
943
944 sk->sk_shutdown = SHUTDOWN_MASK;
945 l2cap_sock_clear_timer(sk);
946 __l2cap_sock_close(sk, 0);
947
948 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
949 err = bt_sock_wait_state(sk, BT_CLOSED,
950 sk->sk_lingertime);
951 }
952
953 if (!err && sk->sk_err)
954 err = -sk->sk_err;
955
956 release_sock(sk);
957 return err;
958}
959
Gustavo F. Padovan554f05b2011-02-04 02:36:42 -0200960static int l2cap_sock_release(struct socket *sock)
961{
962 struct sock *sk = sock->sk;
963 int err;
964
965 BT_DBG("sock %p, sk %p", sock, sk);
966
967 if (!sk)
968 return 0;
969
970 err = l2cap_sock_shutdown(sock, 2);
971
972 sock_orphan(sk);
973 l2cap_sock_kill(sk);
974 return err;
975}
976
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200977static void l2cap_sock_destruct(struct sock *sk)
978{
979 BT_DBG("sk %p", sk);
980
981 skb_queue_purge(&sk->sk_receive_queue);
982 skb_queue_purge(&sk->sk_write_queue);
983}
984
985void l2cap_sock_init(struct sock *sk, struct sock *parent)
986{
987 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300988 struct l2cap_chan *chan = pi->chan;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200989
990 BT_DBG("sk %p", sk);
991
992 if (parent) {
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300993 struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
994
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -0200995 sk->sk_type = parent->sk_type;
996 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
997
998 pi->imtu = l2cap_pi(parent)->imtu;
999 pi->omtu = l2cap_pi(parent)->omtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001000 chan->conf_state = pchan->conf_state;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001001 pi->mode = l2cap_pi(parent)->mode;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001002 chan->fcs = pchan->fcs;
1003 chan->max_tx = pchan->max_tx;
1004 chan->tx_win = pchan->tx_win;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001005 chan->sec_level = pchan->sec_level;
1006 chan->role_switch = pchan->role_switch;
1007 chan->force_reliable = pchan->force_reliable;
1008 chan->flushable = pchan->flushable;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001009 } else {
1010 pi->imtu = L2CAP_DEFAULT_MTU;
1011 pi->omtu = 0;
1012 if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
1013 pi->mode = L2CAP_MODE_ERTM;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001014 chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001015 } else {
1016 pi->mode = L2CAP_MODE_BASIC;
1017 }
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001018 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
1019 chan->fcs = L2CAP_FCS_CRC16;
1020 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001021 chan->sec_level = BT_SECURITY_LOW;
1022 chan->role_switch = 0;
1023 chan->force_reliable = 0;
1024 chan->flushable = BT_FLUSHABLE_OFF;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001025 }
1026
1027 /* Default config options */
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001028 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001029}
1030
1031static struct proto l2cap_proto = {
1032 .name = "L2CAP",
1033 .owner = THIS_MODULE,
1034 .obj_size = sizeof(struct l2cap_pinfo)
1035};
1036
1037struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
1038{
1039 struct sock *sk;
1040
1041 sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
1042 if (!sk)
1043 return NULL;
1044
1045 sock_init_data(sock, sk);
1046 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
1047
1048 sk->sk_destruct = l2cap_sock_destruct;
1049 sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
1050
1051 sock_reset_flag(sk, SOCK_ZAPPED);
1052
1053 sk->sk_protocol = proto;
1054 sk->sk_state = BT_OPEN;
1055
1056 setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
1057
1058 bt_sock_link(&l2cap_sk_list, sk);
1059 return sk;
1060}
1061
1062static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
1063 int kern)
1064{
1065 struct sock *sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001066 struct l2cap_chan *chan;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001067
1068 BT_DBG("sock %p", sock);
1069
1070 sock->state = SS_UNCONNECTED;
1071
1072 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
1073 sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
1074 return -ESOCKTNOSUPPORT;
1075
1076 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
1077 return -EPERM;
1078
1079 sock->ops = &l2cap_sock_ops;
1080
1081 sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
1082 if (!sk)
1083 return -ENOMEM;
1084
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001085 chan = l2cap_chan_alloc(sk);
1086 if (!chan) {
1087 l2cap_sock_kill(sk);
1088 return -ENOMEM;
1089 }
1090
1091 l2cap_pi(sk)->chan = chan;
1092
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001093 l2cap_sock_init(sk, NULL);
1094 return 0;
1095}
1096
Gustavo F. Padovan65390582011-02-04 02:33:56 -02001097const struct proto_ops l2cap_sock_ops = {
1098 .family = PF_BLUETOOTH,
1099 .owner = THIS_MODULE,
1100 .release = l2cap_sock_release,
1101 .bind = l2cap_sock_bind,
1102 .connect = l2cap_sock_connect,
1103 .listen = l2cap_sock_listen,
1104 .accept = l2cap_sock_accept,
1105 .getname = l2cap_sock_getname,
1106 .sendmsg = l2cap_sock_sendmsg,
1107 .recvmsg = l2cap_sock_recvmsg,
1108 .poll = bt_sock_poll,
1109 .ioctl = bt_sock_ioctl,
1110 .mmap = sock_no_mmap,
1111 .socketpair = sock_no_socketpair,
1112 .shutdown = l2cap_sock_shutdown,
1113 .setsockopt = l2cap_sock_setsockopt,
1114 .getsockopt = l2cap_sock_getsockopt
1115};
1116
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001117static const struct net_proto_family l2cap_sock_family_ops = {
1118 .family = PF_BLUETOOTH,
1119 .owner = THIS_MODULE,
1120 .create = l2cap_sock_create,
1121};
1122
1123int __init l2cap_init_sockets(void)
1124{
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001125 int err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001126
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001127 err = proto_register(&l2cap_proto, 0);
1128 if (err < 0)
1129 return err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001130
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001131 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
1132 if (err < 0)
1133 goto error;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001134
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001135 BT_INFO("L2CAP socket layer initialized");
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001136
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001137 return 0;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001138
1139error:
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001140 BT_ERR("L2CAP socket registration failed");
1141 proto_unregister(&l2cap_proto);
1142 return err;
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001143}
1144
1145void l2cap_cleanup_sockets(void)
1146{
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001147 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
1148 BT_ERR("L2CAP socket unregistration failed");
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001149
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03001150 proto_unregister(&l2cap_proto);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02001151}