af_bluetooth.c 17.2 KB
Newer Older
1
/*
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14
   BlueZ - Bluetooth protocol stack for Linux
   Copyright (C) 2000-2001 Qualcomm Incorporated

   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as
   published by the Free Software Foundation;

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 16 17
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
L
Linus Torvalds 已提交
18 19
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

20 21
   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
L
Linus Torvalds 已提交
22 23 24 25 26 27
   SOFTWARE IS DISCLAIMED.
*/

/* Bluetooth address family and sockets. */

#include <linux/module.h>
28
#include <linux/debugfs.h>
29
#include <linux/stringify.h>
30 31
#include <linux/sched/signal.h>

32
#include <asm/ioctls.h>
L
Linus Torvalds 已提交
33 34

#include <net/bluetooth/bluetooth.h>
35
#include <linux/proc_fs.h>
L
Linus Torvalds 已提交
36

37
#include "leds.h"
38 39
#include "selftest.h"

L
Linus Torvalds 已提交
40 41
/* Bluetooth sockets */
#define BT_MAX_PROTO	8
42
static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
43
static DEFINE_RWLOCK(bt_proto_lock);
44 45

static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
46
static const char *const bt_key_strings[BT_MAX_PROTO] = {
47 48 49 50 51 52 53 54 55 56
	"sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
	"sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
	"sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
	"sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
	"sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
	"sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
	"sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
	"sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
};

57
static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
58
static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
59 60 61 62 63 64 65 66 67
	"slock-AF_BLUETOOTH-BTPROTO_L2CAP",
	"slock-AF_BLUETOOTH-BTPROTO_HCI",
	"slock-AF_BLUETOOTH-BTPROTO_SCO",
	"slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
	"slock-AF_BLUETOOTH-BTPROTO_BNEP",
	"slock-AF_BLUETOOTH-BTPROTO_CMTP",
	"slock-AF_BLUETOOTH-BTPROTO_HIDP",
	"slock-AF_BLUETOOTH-BTPROTO_AVDTP",
};
68

69
void bt_sock_reclassify_lock(struct sock *sk, int proto)
70
{
71
	BUG_ON(!sk);
72
	BUG_ON(!sock_allow_reclassification(sk));
73 74 75 76 77

	sock_lock_init_class_and_name(sk,
			bt_slock_key_strings[proto], &bt_slock_key[proto],
				bt_key_strings[proto], &bt_lock_key[proto]);
}
78
EXPORT_SYMBOL(bt_sock_reclassify_lock);
L
Linus Torvalds 已提交
79

80
int bt_sock_register(int proto, const struct net_proto_family *ops)
L
Linus Torvalds 已提交
81
{
82 83
	int err = 0;

L
Linus Torvalds 已提交
84 85 86
	if (proto < 0 || proto >= BT_MAX_PROTO)
		return -EINVAL;

87 88
	write_lock(&bt_proto_lock);

L
Linus Torvalds 已提交
89
	if (bt_proto[proto])
90 91 92 93 94
		err = -EEXIST;
	else
		bt_proto[proto] = ops;

	write_unlock(&bt_proto_lock);
L
Linus Torvalds 已提交
95

96
	return err;
L
Linus Torvalds 已提交
97 98 99
}
EXPORT_SYMBOL(bt_sock_register);

100
void bt_sock_unregister(int proto)
L
Linus Torvalds 已提交
101 102
{
	if (proto < 0 || proto >= BT_MAX_PROTO)
103
		return;
L
Linus Torvalds 已提交
104

105
	write_lock(&bt_proto_lock);
106
	bt_proto[proto] = NULL;
107
	write_unlock(&bt_proto_lock);
L
Linus Torvalds 已提交
108 109 110
}
EXPORT_SYMBOL(bt_sock_unregister);

111 112
static int bt_sock_create(struct net *net, struct socket *sock, int proto,
			  int kern)
L
Linus Torvalds 已提交
113
{
114
	int err;
L
Linus Torvalds 已提交
115

116 117 118
	if (net != &init_net)
		return -EAFNOSUPPORT;

L
Linus Torvalds 已提交
119 120 121
	if (proto < 0 || proto >= BT_MAX_PROTO)
		return -EINVAL;

122
	if (!bt_proto[proto])
L
Linus Torvalds 已提交
123
		request_module("bt-proto-%d", proto);
124

L
Linus Torvalds 已提交
125
	err = -EPROTONOSUPPORT;
126 127 128

	read_lock(&bt_proto_lock);

L
Linus Torvalds 已提交
129
	if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
130
		err = bt_proto[proto]->create(net, sock, proto, kern);
131 132
		if (!err)
			bt_sock_reclassify_lock(sock->sk, proto);
L
Linus Torvalds 已提交
133 134
		module_put(bt_proto[proto]->owner);
	}
135 136 137

	read_unlock(&bt_proto_lock);

138
	return err;
L
Linus Torvalds 已提交
139 140 141 142
}

void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
{
143
	write_lock(&l->lock);
L
Linus Torvalds 已提交
144
	sk_add_node(sk, &l->head);
145
	write_unlock(&l->lock);
L
Linus Torvalds 已提交
146 147 148 149 150
}
EXPORT_SYMBOL(bt_sock_link);

void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
{
151
	write_lock(&l->lock);
L
Linus Torvalds 已提交
152
	sk_del_node_init(sk);
153
	write_unlock(&l->lock);
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161
}
EXPORT_SYMBOL(bt_sock_unlink);

void bt_accept_enqueue(struct sock *parent, struct sock *sk)
{
	BT_DBG("parent %p, sk %p", parent, sk);

	sock_hold(sk);
162
	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
L
Linus Torvalds 已提交
163 164
	list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
	bt_sk(sk)->parent = parent;
165
	release_sock(sk);
L
Linus Torvalds 已提交
166 167 168 169
	parent->sk_ack_backlog++;
}
EXPORT_SYMBOL(bt_accept_enqueue);

170 171 172
/* Calling function must hold the sk lock.
 * bt_sk(sk)->parent must be non-NULL meaning sk is in the parent list.
 */
L
Linus Torvalds 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185
void bt_accept_unlink(struct sock *sk)
{
	BT_DBG("sk %p state %d", sk, sk->sk_state);

	list_del_init(&bt_sk(sk)->accept_q);
	bt_sk(sk)->parent->sk_ack_backlog--;
	bt_sk(sk)->parent = NULL;
	sock_put(sk);
}
EXPORT_SYMBOL(bt_accept_unlink);

struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
{
G
Geliang Tang 已提交
186
	struct bt_sock *s, *n;
L
Linus Torvalds 已提交
187 188 189 190
	struct sock *sk;

	BT_DBG("parent %p", parent);

191
restart:
G
Geliang Tang 已提交
192 193
	list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) {
		sk = (struct sock *)s;
L
Linus Torvalds 已提交
194

195 196
		/* Prevent early freeing of sk due to unlink and sock_kill */
		sock_hold(sk);
197
		lock_sock(sk);
L
Linus Torvalds 已提交
198

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
		/* Check sk has not already been unlinked via
		 * bt_accept_unlink() due to serialisation caused by sk locking
		 */
		if (!bt_sk(sk)->parent) {
			BT_DBG("sk %p, already unlinked", sk);
			release_sock(sk);
			sock_put(sk);

			/* Restart the loop as sk is no longer in the list
			 * and also avoid a potential infinite loop because
			 * list_for_each_entry_safe() is not thread safe.
			 */
			goto restart;
		}

		/* sk is safely in the parent list so reduce reference count */
		sock_put(sk);

L
Linus Torvalds 已提交
217 218 219
		/* FIXME: Is this check still needed */
		if (sk->sk_state == BT_CLOSED) {
			bt_accept_unlink(sk);
220
			release_sock(sk);
L
Linus Torvalds 已提交
221 222 223
			continue;
		}

224
		if (sk->sk_state == BT_CONNECTED || !newsock ||
225
		    test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
L
Linus Torvalds 已提交
226 227 228
			bt_accept_unlink(sk);
			if (newsock)
				sock_graft(sk, newsock);
229

230
			release_sock(sk);
L
Linus Torvalds 已提交
231 232 233
			return sk;
		}

234
		release_sock(sk);
L
Linus Torvalds 已提交
235
	}
236

L
Linus Torvalds 已提交
237 238 239 240
	return NULL;
}
EXPORT_SYMBOL(bt_accept_dequeue);

241 242
int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
		    int flags)
L
Linus Torvalds 已提交
243 244 245 246 247
{
	int noblock = flags & MSG_DONTWAIT;
	struct sock *sk = sock->sk;
	struct sk_buff *skb;
	size_t copied;
248
	size_t skblen;
L
Linus Torvalds 已提交
249 250
	int err;

251
	BT_DBG("sock %p sk %p len %zu", sock, sk, len);
L
Linus Torvalds 已提交
252

253
	if (flags & MSG_OOB)
L
Linus Torvalds 已提交
254 255
		return -EOPNOTSUPP;

256 257
	skb = skb_recv_datagram(sk, flags, noblock, &err);
	if (!skb) {
258
		if (sk->sk_shutdown & RCV_SHUTDOWN)
L
Linus Torvalds 已提交
259
			return 0;
260

L
Linus Torvalds 已提交
261 262 263
		return err;
	}

264
	skblen = skb->len;
L
Linus Torvalds 已提交
265 266 267 268 269 270
	copied = skb->len;
	if (len < copied) {
		msg->msg_flags |= MSG_TRUNC;
		copied = len;
	}

271
	skb_reset_transport_header(skb);
272
	err = skb_copy_datagram_msg(skb, 0, msg, copied);
273
	if (err == 0) {
274
		sock_recv_ts_and_drops(msg, sk, skb);
L
Linus Torvalds 已提交
275

276
		if (msg->msg_name && bt_sk(sk)->skb_msg_name)
277 278 279 280
			bt_sk(sk)->skb_msg_name(skb, msg->msg_name,
						&msg->msg_namelen);
	}

L
Linus Torvalds 已提交
281 282
	skb_free_datagram(sk, skb);

283
	if (flags & MSG_TRUNC)
284 285
		copied = skblen;

L
Linus Torvalds 已提交
286 287 288 289
	return err ? : copied;
}
EXPORT_SYMBOL(bt_sock_recvmsg);

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
static long bt_sock_data_wait(struct sock *sk, long timeo)
{
	DECLARE_WAITQUEUE(wait, current);

	add_wait_queue(sk_sleep(sk), &wait);
	for (;;) {
		set_current_state(TASK_INTERRUPTIBLE);

		if (!skb_queue_empty(&sk->sk_receive_queue))
			break;

		if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
			break;

		if (signal_pending(current) || !timeo)
			break;

307
		sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
308 309 310
		release_sock(sk);
		timeo = schedule_timeout(timeo);
		lock_sock(sk);
311
		sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
312 313 314 315 316 317 318
	}

	__set_current_state(TASK_RUNNING);
	remove_wait_queue(sk_sleep(sk), &wait);
	return timeo;
}

319 320
int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg,
			   size_t size, int flags)
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
{
	struct sock *sk = sock->sk;
	int err = 0;
	size_t target, copied = 0;
	long timeo;

	if (flags & MSG_OOB)
		return -EOPNOTSUPP;

	BT_DBG("sk %p size %zu", sk, size);

	lock_sock(sk);

	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);

	do {
		struct sk_buff *skb;
		int chunk;

		skb = skb_dequeue(&sk->sk_receive_queue);
		if (!skb) {
			if (copied >= target)
				break;

346 347
			err = sock_error(sk);
			if (err)
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
				break;
			if (sk->sk_shutdown & RCV_SHUTDOWN)
				break;

			err = -EAGAIN;
			if (!timeo)
				break;

			timeo = bt_sock_data_wait(sk, timeo);

			if (signal_pending(current)) {
				err = sock_intr_errno(timeo);
				goto out;
			}
			continue;
		}

		chunk = min_t(unsigned int, skb->len, size);
366
		if (skb_copy_datagram_msg(skb, 0, msg, chunk)) {
367 368 369 370 371 372 373 374 375 376 377
			skb_queue_head(&sk->sk_receive_queue, skb);
			if (!copied)
				copied = -EFAULT;
			break;
		}
		copied += chunk;
		size   -= chunk;

		sock_recv_ts_and_drops(msg, sk, skb);

		if (!(flags & MSG_PEEK)) {
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
			int skb_len = skb_headlen(skb);

			if (chunk <= skb_len) {
				__skb_pull(skb, chunk);
			} else {
				struct sk_buff *frag;

				__skb_pull(skb, skb_len);
				chunk -= skb_len;

				skb_walk_frags(skb, frag) {
					if (chunk <= frag->len) {
						/* Pulling partial data */
						skb->len -= chunk;
						skb->data_len -= chunk;
						__skb_pull(frag, chunk);
						break;
					} else if (frag->len) {
						/* Pulling all frag data */
						chunk -= frag->len;
						skb->len -= frag->len;
						skb->data_len -= frag->len;
						__skb_pull(frag, frag->len);
					}
				}
			}

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
			if (skb->len) {
				skb_queue_head(&sk->sk_receive_queue, skb);
				break;
			}
			kfree_skb(skb);

		} else {
			/* put message back and return */
			skb_queue_head(&sk->sk_receive_queue, skb);
			break;
		}
	} while (size);

out:
	release_sock(sk);
	return copied ? : err;
}
EXPORT_SYMBOL(bt_sock_stream_recvmsg);

A
Al Viro 已提交
424
static inline __poll_t bt_accept_poll(struct sock *parent)
L
Linus Torvalds 已提交
425
{
G
Geliang Tang 已提交
426
	struct bt_sock *s, *n;
L
Linus Torvalds 已提交
427 428
	struct sock *sk;

G
Geliang Tang 已提交
429 430
	list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) {
		sk = (struct sock *)s;
431
		if (sk->sk_state == BT_CONNECTED ||
432 433
		    (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
		     sk->sk_state == BT_CONNECT2))
434
			return EPOLLIN | EPOLLRDNORM;
L
Linus Torvalds 已提交
435 436 437 438 439
	}

	return 0;
}

440 441
__poll_t bt_sock_poll(struct file *file, struct socket *sock,
			  poll_table *wait)
L
Linus Torvalds 已提交
442 443
{
	struct sock *sk = sock->sk;
A
Al Viro 已提交
444
	__poll_t mask = 0;
L
Linus Torvalds 已提交
445 446 447

	BT_DBG("sock %p, sk %p", sock, sk);

448 449
	poll_wait(file, sk_sleep(sk), wait);

L
Linus Torvalds 已提交
450 451 452 453
	if (sk->sk_state == BT_LISTEN)
		return bt_accept_poll(sk);

	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
454 455
		mask |= EPOLLERR |
			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
L
Linus Torvalds 已提交
456

457
	if (sk->sk_shutdown & RCV_SHUTDOWN)
458
		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
459

L
Linus Torvalds 已提交
460
	if (sk->sk_shutdown == SHUTDOWN_MASK)
461
		mask |= EPOLLHUP;
L
Linus Torvalds 已提交
462

E
Eric Dumazet 已提交
463
	if (!skb_queue_empty(&sk->sk_receive_queue))
464
		mask |= EPOLLIN | EPOLLRDNORM;
L
Linus Torvalds 已提交
465 466

	if (sk->sk_state == BT_CLOSED)
467
		mask |= EPOLLHUP;
L
Linus Torvalds 已提交
468 469 470 471 472 473

	if (sk->sk_state == BT_CONNECT ||
			sk->sk_state == BT_CONNECT2 ||
			sk->sk_state == BT_CONFIG)
		return mask;

474
	if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
475
		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
L
Linus Torvalds 已提交
476
	else
477
		sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
L
Linus Torvalds 已提交
478 479 480

	return mask;
}
481
EXPORT_SYMBOL(bt_sock_poll);
L
Linus Torvalds 已提交
482

483 484 485
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct sock *sk = sock->sk;
486 487
	struct sk_buff *skb;
	long amount;
488 489 490 491 492
	int err;

	BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);

	switch (cmd) {
493 494 495 496
	case TIOCOUTQ:
		if (sk->sk_state == BT_LISTEN)
			return -EINVAL;

497
		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
		if (amount < 0)
			amount = 0;
		err = put_user(amount, (int __user *) arg);
		break;

	case TIOCINQ:
		if (sk->sk_state == BT_LISTEN)
			return -EINVAL;

		lock_sock(sk);
		skb = skb_peek(&sk->sk_receive_queue);
		amount = skb ? skb->len : 0;
		release_sock(sk);
		err = put_user(amount, (int __user *) arg);
		break;

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
	case SIOCGSTAMP:
		err = sock_get_timestamp(sk, (struct timeval __user *) arg);
		break;

	case SIOCGSTAMPNS:
		err = sock_get_timestampns(sk, (struct timespec __user *) arg);
		break;

	default:
		err = -ENOIOCTLCMD;
		break;
	}

	return err;
}
EXPORT_SYMBOL(bt_sock_ioctl);

531
/* This function expects the sk lock to be held when called */
L
Linus Torvalds 已提交
532 533 534 535 536 537 538
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
{
	DECLARE_WAITQUEUE(wait, current);
	int err = 0;

	BT_DBG("sk %p", sk);

E
Eric Dumazet 已提交
539
	add_wait_queue(sk_sleep(sk), &wait);
540
	set_current_state(TASK_INTERRUPTIBLE);
L
Linus Torvalds 已提交
541 542
	while (sk->sk_state != state) {
		if (!timeo) {
543
			err = -EINPROGRESS;
L
Linus Torvalds 已提交
544 545 546 547 548 549 550 551 552 553 554
			break;
		}

		if (signal_pending(current)) {
			err = sock_intr_errno(timeo);
			break;
		}

		release_sock(sk);
		timeo = schedule_timeout(timeo);
		lock_sock(sk);
555
		set_current_state(TASK_INTERRUPTIBLE);
L
Linus Torvalds 已提交
556

557 558
		err = sock_error(sk);
		if (err)
L
Linus Torvalds 已提交
559 560
			break;
	}
561
	__set_current_state(TASK_RUNNING);
E
Eric Dumazet 已提交
562
	remove_wait_queue(sk_sleep(sk), &wait);
L
Linus Torvalds 已提交
563 564 565 566
	return err;
}
EXPORT_SYMBOL(bt_sock_wait_state);

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
/* This function expects the sk lock to be held when called */
int bt_sock_wait_ready(struct sock *sk, unsigned long flags)
{
	DECLARE_WAITQUEUE(wait, current);
	unsigned long timeo;
	int err = 0;

	BT_DBG("sk %p", sk);

	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);

	add_wait_queue(sk_sleep(sk), &wait);
	set_current_state(TASK_INTERRUPTIBLE);
	while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) {
		if (!timeo) {
			err = -EAGAIN;
			break;
		}

		if (signal_pending(current)) {
			err = sock_intr_errno(timeo);
			break;
		}

		release_sock(sk);
		timeo = schedule_timeout(timeo);
		lock_sock(sk);
		set_current_state(TASK_INTERRUPTIBLE);

		err = sock_error(sk);
		if (err)
			break;
	}
	__set_current_state(TASK_RUNNING);
	remove_wait_queue(sk_sleep(sk), &wait);

	return err;
}
EXPORT_SYMBOL(bt_sock_wait_ready);

607 608 609 610
#ifdef CONFIG_PROC_FS
static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
	__acquires(seq->private->l->lock)
{
611
	struct bt_sock_list *l = PDE_DATA(file_inode(seq->file));
612 613 614 615 616 617 618

	read_lock(&l->lock);
	return seq_hlist_start_head(&l->head, *pos);
}

static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
619
	struct bt_sock_list *l = PDE_DATA(file_inode(seq->file));
620 621 622 623 624 625 626

	return seq_hlist_next(v, &l->head, pos);
}

static void bt_seq_stop(struct seq_file *seq, void *v)
	__releases(seq->private->l->lock)
{
627
	struct bt_sock_list *l = PDE_DATA(file_inode(seq->file));
628 629 630 631 632 633

	read_unlock(&l->lock);
}

static int bt_seq_show(struct seq_file *seq, void *v)
{
634
	struct bt_sock_list *l = PDE_DATA(file_inode(seq->file));
635 636

	if (v == SEQ_START_TOKEN) {
637
		seq_puts(seq ,"sk               RefCnt Rmem   Wmem   User   Inode  Parent");
638 639 640 641 642 643 644 645

		if (l->custom_seq_show) {
			seq_putc(seq, ' ');
			l->custom_seq_show(seq, v);
		}

		seq_putc(seq, '\n');
	} else {
646 647
		struct sock *sk = sk_entry(v);
		struct bt_sock *bt = bt_sk(sk);
648

649
		seq_printf(seq,
650
			   "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu",
651
			   sk,
652
			   refcount_read(&sk->sk_refcnt),
653 654
			   sk_rmem_alloc_get(sk),
			   sk_wmem_alloc_get(sk),
655
			   from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
656 657 658 659 660 661 662 663 664 665 666 667 668
			   sock_i_ino(sk),
			   bt->parent? sock_i_ino(bt->parent): 0LU);

		if (l->custom_seq_show) {
			seq_putc(seq, ' ');
			l->custom_seq_show(seq, v);
		}

		seq_putc(seq, '\n');
	}
	return 0;
}

669
static const struct seq_operations bt_seq_ops = {
670 671 672 673 674 675
	.start = bt_seq_start,
	.next  = bt_seq_next,
	.stop  = bt_seq_stop,
	.show  = bt_seq_show,
};

676
int bt_procfs_init(struct net *net, const char *name,
677
		   struct bt_sock_list *sk_list,
678 679 680 681
		   int (* seq_show)(struct seq_file *, void *))
{
	sk_list->custom_seq_show = seq_show;

682
	if (!proc_create_seq_data(name, 0, net->proc_net, &bt_seq_ops, sk_list))
683 684 685 686 687 688
		return -ENOMEM;
	return 0;
}

void bt_procfs_cleanup(struct net *net, const char *name)
{
689
	remove_proc_entry(name, net->proc_net);
690 691
}
#else
692
int bt_procfs_init(struct net *net, const char *name,
693
		   struct bt_sock_list *sk_list,
694 695 696 697 698 699 700 701 702 703 704 705
		   int (* seq_show)(struct seq_file *, void *))
{
	return 0;
}

void bt_procfs_cleanup(struct net *net, const char *name)
{
}
#endif
EXPORT_SYMBOL(bt_procfs_init);
EXPORT_SYMBOL(bt_procfs_cleanup);

706
static const struct net_proto_family bt_sock_family_ops = {
L
Linus Torvalds 已提交
707 708 709 710 711
	.owner	= THIS_MODULE,
	.family	= PF_BLUETOOTH,
	.create	= bt_sock_create,
};

712 713 714
struct dentry *bt_debugfs;
EXPORT_SYMBOL_GPL(bt_debugfs);

715 716 717
#define VERSION __stringify(BT_SUBSYS_VERSION) "." \
		__stringify(BT_SUBSYS_REVISION)

L
Linus Torvalds 已提交
718 719
static int __init bt_init(void)
{
720 721
	int err;

722
	sock_skb_cb_check_size(sizeof(struct bt_skb_cb));
723

724
	BT_INFO("Core ver %s", VERSION);
L
Linus Torvalds 已提交
725

726 727 728 729
	err = bt_selftest();
	if (err < 0)
		return err;

730 731
	bt_debugfs = debugfs_create_dir("bluetooth", NULL);

732 733
	bt_leds_init();

734 735 736
	err = bt_sysfs_init();
	if (err < 0)
		return err;
L
Linus Torvalds 已提交
737

738
	err = sock_register(&bt_sock_family_ops);
739 740
	if (err)
		goto cleanup_sysfs;
L
Linus Torvalds 已提交
741

742
	BT_INFO("HCI device and connection manager initialized");
L
Linus Torvalds 已提交
743

744
	err = hci_sock_init();
745 746
	if (err)
		goto unregister_socket;
747 748

	err = l2cap_init();
749 750
	if (err)
		goto cleanup_socket;
751 752

	err = sco_init();
753 754
	if (err)
		goto cleanup_cap;
L
Linus Torvalds 已提交
755

756
	err = mgmt_init();
757 758
	if (err)
		goto cleanup_sco;
759

L
Linus Torvalds 已提交
760
	return 0;
761

762 763 764 765 766
cleanup_sco:
	sco_exit();
cleanup_cap:
	l2cap_exit();
cleanup_socket:
767
	hci_sock_cleanup();
768
unregister_socket:
769
	sock_unregister(PF_BLUETOOTH);
770
cleanup_sysfs:
771 772
	bt_sysfs_cleanup();
	return err;
L
Linus Torvalds 已提交
773 774 775 776
}

static void __exit bt_exit(void)
{
777 778
	mgmt_exit();

779 780 781 782
	sco_exit();

	l2cap_exit();

L
Linus Torvalds 已提交
783 784 785
	hci_sock_cleanup();

	sock_unregister(PF_BLUETOOTH);
786 787

	bt_sysfs_cleanup();
788

789 790
	bt_leds_cleanup();

791
	debugfs_remove_recursive(bt_debugfs);
L
Linus Torvalds 已提交
792 793 794 795 796
}

subsys_initcall(bt_init);
module_exit(bt_exit);

797
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
798 799
MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
MODULE_VERSION(VERSION);
L
Linus Torvalds 已提交
800 801
MODULE_LICENSE("GPL");
MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);