blob: 8412b637407b999fb3b13b06d8602a6c3b9080bd [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
4
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth address family and sockets. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
Marcel Holtmann3241ad82008-07-14 20:13:50 +020028#include <asm/ioctls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
30#include <net/bluetooth/bluetooth.h>
Masatake YAMATO256a06c2012-07-26 01:26:32 +090031#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
Gustavo F. Padovan64274512011-02-07 20:08:52 -020033#define VERSION "2.16"
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35/* Bluetooth sockets */
36#define BT_MAX_PROTO 8
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000037static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010038static DEFINE_RWLOCK(bt_proto_lock);
Dave Young68845cb2008-04-01 23:58:35 -070039
Dave Young68845cb2008-04-01 23:58:35 -070040static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070041static const char *const bt_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070042 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
43 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
44 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
45 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
46 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
47 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
48 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
49 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
50};
51
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010052static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070053static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070054 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
55 "slock-AF_BLUETOOTH-BTPROTO_HCI",
56 "slock-AF_BLUETOOTH-BTPROTO_SCO",
57 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
58 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
59 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
60 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
61 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
62};
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010063
Octavian Purdilab5a30dd2012-01-22 00:28:34 +020064void bt_sock_reclassify_lock(struct sock *sk, int proto)
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010065{
Octavian Purdilab5a30dd2012-01-22 00:28:34 +020066 BUG_ON(!sk);
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010067 BUG_ON(sock_owned_by_user(sk));
68
69 sock_lock_init_class_and_name(sk,
70 bt_slock_key_strings[proto], &bt_slock_key[proto],
71 bt_key_strings[proto], &bt_lock_key[proto]);
72}
Octavian Purdilab5a30dd2012-01-22 00:28:34 +020073EXPORT_SYMBOL(bt_sock_reclassify_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000075int bt_sock_register(int proto, const struct net_proto_family *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -070076{
Marcel Holtmann74da6262006-10-15 17:31:14 +020077 int err = 0;
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 if (proto < 0 || proto >= BT_MAX_PROTO)
80 return -EINVAL;
81
Marcel Holtmann74da6262006-10-15 17:31:14 +020082 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Marcel Holtmann74da6262006-10-15 17:31:14 +020084 if (bt_proto[proto])
85 err = -EEXIST;
86 else
87 bt_proto[proto] = ops;
88
89 write_unlock(&bt_proto_lock);
90
91 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092}
93EXPORT_SYMBOL(bt_sock_register);
94
95int bt_sock_unregister(int proto)
96{
Marcel Holtmann74da6262006-10-15 17:31:14 +020097 int err = 0;
98
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 if (proto < 0 || proto >= BT_MAX_PROTO)
100 return -EINVAL;
101
Marcel Holtmann74da6262006-10-15 17:31:14 +0200102 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Marcel Holtmann74da6262006-10-15 17:31:14 +0200104 if (!bt_proto[proto])
105 err = -ENOENT;
106 else
107 bt_proto[proto] = NULL;
108
109 write_unlock(&bt_proto_lock);
110
111 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112}
113EXPORT_SYMBOL(bt_sock_unregister);
114
Eric Paris3f378b62009-11-05 22:18:14 -0800115static int bt_sock_create(struct net *net, struct socket *sock, int proto,
116 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200118 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700120 if (net != &init_net)
121 return -EAFNOSUPPORT;
122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 if (proto < 0 || proto >= BT_MAX_PROTO)
124 return -EINVAL;
125
Johannes Berg95a5afc2008-10-16 15:24:51 -0700126 if (!bt_proto[proto])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 request_module("bt-proto-%d", proto);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200128
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 err = -EPROTONOSUPPORT;
Marcel Holtmann74da6262006-10-15 17:31:14 +0200130
131 read_lock(&bt_proto_lock);
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
Eric Paris3f378b62009-11-05 22:18:14 -0800134 err = bt_proto[proto]->create(net, sock, proto, kern);
Octavian Purdilab5a30dd2012-01-22 00:28:34 +0200135 if (!err)
136 bt_sock_reclassify_lock(sock->sk, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 module_put(bt_proto[proto]->owner);
138 }
Marcel Holtmann74da6262006-10-15 17:31:14 +0200139
140 read_unlock(&bt_proto_lock);
141
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900142 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143}
144
145void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
146{
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200147 write_lock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 sk_add_node(sk, &l->head);
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200149 write_unlock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150}
151EXPORT_SYMBOL(bt_sock_link);
152
153void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
154{
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200155 write_lock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 sk_del_node_init(sk);
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200157 write_unlock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158}
159EXPORT_SYMBOL(bt_sock_unlink);
160
161void bt_accept_enqueue(struct sock *parent, struct sock *sk)
162{
163 BT_DBG("parent %p, sk %p", parent, sk);
164
165 sock_hold(sk);
166 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
167 bt_sk(sk)->parent = parent;
168 parent->sk_ack_backlog++;
169}
170EXPORT_SYMBOL(bt_accept_enqueue);
171
172void bt_accept_unlink(struct sock *sk)
173{
174 BT_DBG("sk %p state %d", sk, sk->sk_state);
175
176 list_del_init(&bt_sk(sk)->accept_q);
177 bt_sk(sk)->parent->sk_ack_backlog--;
178 bt_sk(sk)->parent = NULL;
179 sock_put(sk);
180}
181EXPORT_SYMBOL(bt_accept_unlink);
182
183struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
184{
185 struct list_head *p, *n;
186 struct sock *sk;
187
188 BT_DBG("parent %p", parent);
189
190 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
191 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
192
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200193 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
195 /* FIXME: Is this check still needed */
196 if (sk->sk_state == BT_CLOSED) {
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200197 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 bt_accept_unlink(sk);
199 continue;
200 }
201
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100202 if (sk->sk_state == BT_CONNECTED || !newsock ||
Vinicius Costa Gomesd0609912012-05-31 22:53:39 -0300203 test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 bt_accept_unlink(sk);
205 if (newsock)
206 sock_graft(sk, newsock);
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200207
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200208 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 return sk;
210 }
211
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200212 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 }
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 return NULL;
216}
217EXPORT_SYMBOL(bt_accept_dequeue);
218
219int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100220 struct msghdr *msg, size_t len, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221{
222 int noblock = flags & MSG_DONTWAIT;
223 struct sock *sk = sock->sk;
224 struct sk_buff *skb;
225 size_t copied;
226 int err;
227
Marcel Holtmanna418b892008-11-30 12:17:28 +0100228 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 if (flags & (MSG_OOB))
231 return -EOPNOTSUPP;
232
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200233 skb = skb_recv_datagram(sk, flags, noblock, &err);
234 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 if (sk->sk_shutdown & RCV_SHUTDOWN)
236 return 0;
237 return err;
238 }
239
240 msg->msg_namelen = 0;
241
242 copied = skb->len;
243 if (len < copied) {
244 msg->msg_flags |= MSG_TRUNC;
245 copied = len;
246 }
247
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300248 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200250 if (err == 0)
Neil Horman3b885782009-10-12 13:26:31 -0700251 sock_recv_ts_and_drops(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253 skb_free_datagram(sk, skb);
254
255 return err ? : copied;
256}
257EXPORT_SYMBOL(bt_sock_recvmsg);
258
Mat Martineau796c86e2010-09-08 10:05:27 -0700259static long bt_sock_data_wait(struct sock *sk, long timeo)
260{
261 DECLARE_WAITQUEUE(wait, current);
262
263 add_wait_queue(sk_sleep(sk), &wait);
264 for (;;) {
265 set_current_state(TASK_INTERRUPTIBLE);
266
267 if (!skb_queue_empty(&sk->sk_receive_queue))
268 break;
269
270 if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
271 break;
272
273 if (signal_pending(current) || !timeo)
274 break;
275
276 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
277 release_sock(sk);
278 timeo = schedule_timeout(timeo);
279 lock_sock(sk);
280 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
281 }
282
283 __set_current_state(TASK_RUNNING);
284 remove_wait_queue(sk_sleep(sk), &wait);
285 return timeo;
286}
287
288int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
289 struct msghdr *msg, size_t size, int flags)
290{
291 struct sock *sk = sock->sk;
292 int err = 0;
293 size_t target, copied = 0;
294 long timeo;
295
296 if (flags & MSG_OOB)
297 return -EOPNOTSUPP;
298
299 msg->msg_namelen = 0;
300
301 BT_DBG("sk %p size %zu", sk, size);
302
303 lock_sock(sk);
304
305 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
306 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
307
308 do {
309 struct sk_buff *skb;
310 int chunk;
311
312 skb = skb_dequeue(&sk->sk_receive_queue);
313 if (!skb) {
314 if (copied >= target)
315 break;
316
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200317 err = sock_error(sk);
318 if (err)
Mat Martineau796c86e2010-09-08 10:05:27 -0700319 break;
320 if (sk->sk_shutdown & RCV_SHUTDOWN)
321 break;
322
323 err = -EAGAIN;
324 if (!timeo)
325 break;
326
327 timeo = bt_sock_data_wait(sk, timeo);
328
329 if (signal_pending(current)) {
330 err = sock_intr_errno(timeo);
331 goto out;
332 }
333 continue;
334 }
335
336 chunk = min_t(unsigned int, skb->len, size);
Mat Martineau5b668eb2011-07-22 14:53:59 -0700337 if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
Mat Martineau796c86e2010-09-08 10:05:27 -0700338 skb_queue_head(&sk->sk_receive_queue, skb);
339 if (!copied)
340 copied = -EFAULT;
341 break;
342 }
343 copied += chunk;
344 size -= chunk;
345
346 sock_recv_ts_and_drops(msg, sk, skb);
347
348 if (!(flags & MSG_PEEK)) {
Mat Martineau5b668eb2011-07-22 14:53:59 -0700349 int skb_len = skb_headlen(skb);
350
351 if (chunk <= skb_len) {
352 __skb_pull(skb, chunk);
353 } else {
354 struct sk_buff *frag;
355
356 __skb_pull(skb, skb_len);
357 chunk -= skb_len;
358
359 skb_walk_frags(skb, frag) {
360 if (chunk <= frag->len) {
361 /* Pulling partial data */
362 skb->len -= chunk;
363 skb->data_len -= chunk;
364 __skb_pull(frag, chunk);
365 break;
366 } else if (frag->len) {
367 /* Pulling all frag data */
368 chunk -= frag->len;
369 skb->len -= frag->len;
370 skb->data_len -= frag->len;
371 __skb_pull(frag, frag->len);
372 }
373 }
374 }
375
Mat Martineau796c86e2010-09-08 10:05:27 -0700376 if (skb->len) {
377 skb_queue_head(&sk->sk_receive_queue, skb);
378 break;
379 }
380 kfree_skb(skb);
381
382 } else {
383 /* put message back and return */
384 skb_queue_head(&sk->sk_receive_queue, skb);
385 break;
386 }
387 } while (size);
388
389out:
390 release_sock(sk);
391 return copied ? : err;
392}
393EXPORT_SYMBOL(bt_sock_stream_recvmsg);
394
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395static inline unsigned int bt_accept_poll(struct sock *parent)
396{
397 struct list_head *p, *n;
398 struct sock *sk;
399
400 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
401 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
Marcel Holtmannd5f2d2b2009-02-16 02:57:30 +0100402 if (sk->sk_state == BT_CONNECTED ||
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300403 (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
404 sk->sk_state == BT_CONNECT2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 return POLLIN | POLLRDNORM;
406 }
407
408 return 0;
409}
410
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300411unsigned int bt_sock_poll(struct file *file, struct socket *sock,
412 poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
414 struct sock *sk = sock->sk;
415 unsigned int mask = 0;
416
417 BT_DBG("sock %p, sk %p", sock, sk);
418
Eric Dumazetaa395142010-04-20 13:03:51 +0000419 poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421 if (sk->sk_state == BT_LISTEN)
422 return bt_accept_poll(sk);
423
424 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
425 mask |= POLLERR;
426
Davide Libenzif348d702006-03-25 03:07:39 -0800427 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +0000428 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Davide Libenzif348d702006-03-25 03:07:39 -0800429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (sk->sk_shutdown == SHUTDOWN_MASK)
431 mask |= POLLHUP;
432
Eric Dumazetdb409802010-09-06 11:13:50 +0000433 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 mask |= POLLIN | POLLRDNORM;
435
436 if (sk->sk_state == BT_CLOSED)
437 mask |= POLLHUP;
438
439 if (sk->sk_state == BT_CONNECT ||
440 sk->sk_state == BT_CONNECT2 ||
441 sk->sk_state == BT_CONFIG)
442 return mask;
443
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300444 if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
446 else
447 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
448
449 return mask;
450}
451EXPORT_SYMBOL(bt_sock_poll);
452
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200453int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
454{
455 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200456 struct sk_buff *skb;
457 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200458 int err;
459
460 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
461
462 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200463 case TIOCOUTQ:
464 if (sk->sk_state == BT_LISTEN)
465 return -EINVAL;
466
Eric Dumazet31e6d362009-06-17 19:05:41 -0700467 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200468 if (amount < 0)
469 amount = 0;
470 err = put_user(amount, (int __user *) arg);
471 break;
472
473 case TIOCINQ:
474 if (sk->sk_state == BT_LISTEN)
475 return -EINVAL;
476
477 lock_sock(sk);
478 skb = skb_peek(&sk->sk_receive_queue);
479 amount = skb ? skb->len : 0;
480 release_sock(sk);
481 err = put_user(amount, (int __user *) arg);
482 break;
483
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200484 case SIOCGSTAMP:
485 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
486 break;
487
488 case SIOCGSTAMPNS:
489 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
490 break;
491
492 default:
493 err = -ENOIOCTLCMD;
494 break;
495 }
496
497 return err;
498}
499EXPORT_SYMBOL(bt_sock_ioctl);
500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
502{
503 DECLARE_WAITQUEUE(wait, current);
504 int err = 0;
505
506 BT_DBG("sk %p", sk);
507
Eric Dumazetaa395142010-04-20 13:03:51 +0000508 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400509 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 while (sk->sk_state != state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200512 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 break;
514 }
515
516 if (signal_pending(current)) {
517 err = sock_intr_errno(timeo);
518 break;
519 }
520
521 release_sock(sk);
522 timeo = schedule_timeout(timeo);
523 lock_sock(sk);
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400524 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800526 err = sock_error(sk);
527 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 }
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400530 __set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000531 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 return err;
533}
534EXPORT_SYMBOL(bt_sock_wait_state);
535
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900536#ifdef CONFIG_PROC_FS
537struct bt_seq_state {
538 struct bt_sock_list *l;
539};
540
541static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
542 __acquires(seq->private->l->lock)
543{
544 struct bt_seq_state *s = seq->private;
545 struct bt_sock_list *l = s->l;
546
547 read_lock(&l->lock);
548 return seq_hlist_start_head(&l->head, *pos);
549}
550
551static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
552{
553 struct bt_seq_state *s = seq->private;
554 struct bt_sock_list *l = s->l;
555
556 return seq_hlist_next(v, &l->head, pos);
557}
558
559static void bt_seq_stop(struct seq_file *seq, void *v)
560 __releases(seq->private->l->lock)
561{
562 struct bt_seq_state *s = seq->private;
563 struct bt_sock_list *l = s->l;
564
565 read_unlock(&l->lock);
566}
567
568static int bt_seq_show(struct seq_file *seq, void *v)
569{
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900570 struct bt_seq_state *s = seq->private;
571 struct bt_sock_list *l = s->l;
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900572
573 if (v == SEQ_START_TOKEN) {
574 seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
575
576 if (l->custom_seq_show) {
577 seq_putc(seq, ' ');
578 l->custom_seq_show(seq, v);
579 }
580
581 seq_putc(seq, '\n');
582 } else {
Andrei Emeltchenko09d5d4a2012-08-07 18:05:04 +0300583 struct sock *sk = sk_entry(v);
584 struct bt_sock *bt = bt_sk(sk);
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900585
Andrei Emeltchenko7028a882012-09-25 12:49:45 +0300586 seq_printf(seq,
587 "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu",
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900588 sk,
589 atomic_read(&sk->sk_refcnt),
590 sk_rmem_alloc_get(sk),
591 sk_wmem_alloc_get(sk),
Eric W. Biederman1bbb3092012-10-03 20:32:17 -0700592 from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900593 sock_i_ino(sk),
Andrei Emeltchenko7028a882012-09-25 12:49:45 +0300594 &bt->src,
595 &bt->dst,
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900596 bt->parent? sock_i_ino(bt->parent): 0LU);
597
598 if (l->custom_seq_show) {
599 seq_putc(seq, ' ');
600 l->custom_seq_show(seq, v);
601 }
602
603 seq_putc(seq, '\n');
604 }
605 return 0;
606}
607
608static struct seq_operations bt_seq_ops = {
609 .start = bt_seq_start,
610 .next = bt_seq_next,
611 .stop = bt_seq_stop,
612 .show = bt_seq_show,
613};
614
615static int bt_seq_open(struct inode *inode, struct file *file)
616{
617 struct bt_sock_list *sk_list;
618 struct bt_seq_state *s;
619
620 sk_list = PDE(inode)->data;
621 s = __seq_open_private(file, &bt_seq_ops,
622 sizeof(struct bt_seq_state));
Andrei Emeltchenko31f47072012-08-07 18:05:06 +0300623 if (!s)
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900624 return -ENOMEM;
625
626 s->l = sk_list;
627 return 0;
628}
629
630int bt_procfs_init(struct module* module, struct net *net, const char *name,
631 struct bt_sock_list* sk_list,
632 int (* seq_show)(struct seq_file *, void *))
633{
634 struct proc_dir_entry * pde;
635
636 sk_list->custom_seq_show = seq_show;
637
638 sk_list->fops.owner = module;
639 sk_list->fops.open = bt_seq_open;
640 sk_list->fops.read = seq_read;
641 sk_list->fops.llseek = seq_lseek;
642 sk_list->fops.release = seq_release_private;
643
Gao fengd4beaa62013-02-18 01:34:54 +0000644 pde = proc_create(name, 0, net->proc_net, &sk_list->fops);
Andrei Emeltchenko31f47072012-08-07 18:05:06 +0300645 if (!pde)
Masatake YAMATO256a06c2012-07-26 01:26:32 +0900646 return -ENOMEM;
647
648 pde->data = sk_list;
649
650 return 0;
651}
652
653void bt_procfs_cleanup(struct net *net, const char *name)
654{
655 proc_net_remove(net, name);
656}
657#else
658int bt_procfs_init(struct module* module, struct net *net, const char *name,
659 struct bt_sock_list* sk_list,
660 int (* seq_show)(struct seq_file *, void *))
661{
662 return 0;
663}
664
665void bt_procfs_cleanup(struct net *net, const char *name)
666{
667}
668#endif
669EXPORT_SYMBOL(bt_procfs_init);
670EXPORT_SYMBOL(bt_procfs_cleanup);
671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672static struct net_proto_family bt_sock_family_ops = {
673 .owner = THIS_MODULE,
674 .family = PF_BLUETOOTH,
675 .create = bt_sock_create,
676};
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678static int __init bt_init(void)
679{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200680 int err;
681
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 BT_INFO("Core ver %s", VERSION);
683
Marcel Holtmann27d35282006-07-03 10:02:37 +0200684 err = bt_sysfs_init();
685 if (err < 0)
686 return err;
687
688 err = sock_register(&bt_sock_family_ops);
689 if (err < 0) {
690 bt_sysfs_cleanup();
691 return err;
692 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694 BT_INFO("HCI device and connection manager initialized");
695
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200696 err = hci_sock_init();
697 if (err < 0)
698 goto error;
699
700 err = l2cap_init();
Anand Gadiyar0ed54da2011-02-22 12:43:26 +0530701 if (err < 0)
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200702 goto sock_err;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200703
704 err = sco_init();
705 if (err < 0) {
706 l2cap_exit();
707 goto sock_err;
708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 return 0;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200711
712sock_err:
713 hci_sock_cleanup();
714
715error:
716 sock_unregister(PF_BLUETOOTH);
717 bt_sysfs_cleanup();
718
719 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
722static void __exit bt_exit(void)
723{
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200724
725 sco_exit();
726
727 l2cap_exit();
728
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 hci_sock_cleanup();
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200732
733 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734}
735
736subsys_initcall(bt_init);
737module_exit(bt_exit);
738
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200739MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
741MODULE_VERSION(VERSION);
742MODULE_LICENSE("GPL");
743MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);