xref: /linux/net/bluetooth/af_bluetooth.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
31da177e4SLinus Torvalds    Copyright (C) 2000-2001 Qualcomm Incorporated
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth address family and sockets. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <linux/module.h>
28ffcecac6SMarcel Holtmann #include <linux/debugfs.h>
299e8305b3SMarcel Holtmann #include <linux/stringify.h>
30174cd4b1SIngo Molnar #include <linux/sched/signal.h>
31174cd4b1SIngo Molnar 
323241ad82SMarcel Holtmann #include <asm/ioctls.h>
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
35256a06c8SMasatake YAMATO #include <linux/proc_fs.h>
361da177e4SLinus Torvalds 
37e64c97b5SMarcel Holtmann #include "leds.h"
38ee485290SMarcel Holtmann #include "selftest.h"
39ee485290SMarcel Holtmann 
401da177e4SLinus Torvalds /* Bluetooth sockets */
41ccf74f23SLuiz Augusto von Dentz #define BT_MAX_PROTO	(BTPROTO_LAST + 1)
42ec1b4cf7SStephen Hemminger static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
43db7aa1c2SMarcel Holtmann static DEFINE_RWLOCK(bt_proto_lock);
4468845cb2SDave Young 
4568845cb2SDave Young static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
4636cbd3dcSJan Engelhardt static const char *const bt_key_strings[BT_MAX_PROTO] = {
4768845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
4868845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
4968845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
5068845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
5168845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
5268845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
5368845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
5468845cb2SDave Young 	"sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
55ccf74f23SLuiz Augusto von Dentz 	"sk_lock-AF_BLUETOOTH-BTPROTO_ISO",
5668845cb2SDave Young };
5768845cb2SDave Young 
58db7aa1c2SMarcel Holtmann static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
5936cbd3dcSJan Engelhardt static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
6068845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_L2CAP",
6168845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_HCI",
6268845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_SCO",
6368845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
6468845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_BNEP",
6568845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_CMTP",
6668845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_HIDP",
6768845cb2SDave Young 	"slock-AF_BLUETOOTH-BTPROTO_AVDTP",
68ccf74f23SLuiz Augusto von Dentz 	"slock-AF_BLUETOOTH-BTPROTO_ISO",
6968845cb2SDave Young };
70db7aa1c2SMarcel Holtmann 
bt_sock_reclassify_lock(struct sock * sk,int proto)71b5a30ddaSOctavian Purdila void bt_sock_reclassify_lock(struct sock *sk, int proto)
72db7aa1c2SMarcel Holtmann {
73b5a30ddaSOctavian Purdila 	BUG_ON(!sk);
74fafc4e1eSHannes Frederic Sowa 	BUG_ON(!sock_allow_reclassification(sk));
75db7aa1c2SMarcel Holtmann 
76db7aa1c2SMarcel Holtmann 	sock_lock_init_class_and_name(sk,
77db7aa1c2SMarcel Holtmann 				      bt_slock_key_strings[proto], &bt_slock_key[proto],
78db7aa1c2SMarcel Holtmann 				      bt_key_strings[proto], &bt_lock_key[proto]);
79db7aa1c2SMarcel Holtmann }
80b5a30ddaSOctavian Purdila EXPORT_SYMBOL(bt_sock_reclassify_lock);
811da177e4SLinus Torvalds 
bt_sock_register(int proto,const struct net_proto_family * ops)82ec1b4cf7SStephen Hemminger int bt_sock_register(int proto, const struct net_proto_family *ops)
831da177e4SLinus Torvalds {
8474da626aSMarcel Holtmann 	int err = 0;
8574da626aSMarcel Holtmann 
861da177e4SLinus Torvalds 	if (proto < 0 || proto >= BT_MAX_PROTO)
871da177e4SLinus Torvalds 		return -EINVAL;
881da177e4SLinus Torvalds 
8974da626aSMarcel Holtmann 	write_lock(&bt_proto_lock);
901da177e4SLinus Torvalds 
9174da626aSMarcel Holtmann 	if (bt_proto[proto])
9274da626aSMarcel Holtmann 		err = -EEXIST;
9374da626aSMarcel Holtmann 	else
941da177e4SLinus Torvalds 		bt_proto[proto] = ops;
9574da626aSMarcel Holtmann 
9674da626aSMarcel Holtmann 	write_unlock(&bt_proto_lock);
9774da626aSMarcel Holtmann 
9874da626aSMarcel Holtmann 	return err;
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds EXPORT_SYMBOL(bt_sock_register);
1011da177e4SLinus Torvalds 
bt_sock_unregister(int proto)102be9f97f0SDavid Herrmann void bt_sock_unregister(int proto)
1031da177e4SLinus Torvalds {
1041da177e4SLinus Torvalds 	if (proto < 0 || proto >= BT_MAX_PROTO)
105be9f97f0SDavid Herrmann 		return;
1061da177e4SLinus Torvalds 
10774da626aSMarcel Holtmann 	write_lock(&bt_proto_lock);
1081da177e4SLinus Torvalds 	bt_proto[proto] = NULL;
10974da626aSMarcel Holtmann 	write_unlock(&bt_proto_lock);
1101da177e4SLinus Torvalds }
1111da177e4SLinus Torvalds EXPORT_SYMBOL(bt_sock_unregister);
1121da177e4SLinus Torvalds 
bt_sock_create(struct net * net,struct socket * sock,int proto,int kern)1133f378b68SEric Paris static int bt_sock_create(struct net *net, struct socket *sock, int proto,
1143f378b68SEric Paris 			  int kern)
1151da177e4SLinus Torvalds {
11674da626aSMarcel Holtmann 	int err;
1171da177e4SLinus Torvalds 
1181b8d7ae4SEric W. Biederman 	if (net != &init_net)
1191b8d7ae4SEric W. Biederman 		return -EAFNOSUPPORT;
1201b8d7ae4SEric W. Biederman 
1211da177e4SLinus Torvalds 	if (proto < 0 || proto >= BT_MAX_PROTO)
1221da177e4SLinus Torvalds 		return -EINVAL;
1231da177e4SLinus Torvalds 
12495a5afcaSJohannes Berg 	if (!bt_proto[proto])
1251da177e4SLinus Torvalds 		request_module("bt-proto-%d", proto);
12674da626aSMarcel Holtmann 
1271da177e4SLinus Torvalds 	err = -EPROTONOSUPPORT;
12874da626aSMarcel Holtmann 
12974da626aSMarcel Holtmann 	read_lock(&bt_proto_lock);
13074da626aSMarcel Holtmann 
1311da177e4SLinus Torvalds 	if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
1323f378b68SEric Paris 		err = bt_proto[proto]->create(net, sock, proto, kern);
133b5a30ddaSOctavian Purdila 		if (!err)
134b5a30ddaSOctavian Purdila 			bt_sock_reclassify_lock(sock->sk, proto);
1351da177e4SLinus Torvalds 		module_put(bt_proto[proto]->owner);
1361da177e4SLinus Torvalds 	}
13774da626aSMarcel Holtmann 
13874da626aSMarcel Holtmann 	read_unlock(&bt_proto_lock);
13974da626aSMarcel Holtmann 
1401da177e4SLinus Torvalds 	return err;
1411da177e4SLinus Torvalds }
1421da177e4SLinus Torvalds 
bt_sock_alloc(struct net * net,struct socket * sock,struct proto * prot,int proto,gfp_t prio,int kern)1436bfa273eSLuiz Augusto von Dentz struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
1446bfa273eSLuiz Augusto von Dentz 			   struct proto *prot, int proto, gfp_t prio, int kern)
1456bfa273eSLuiz Augusto von Dentz {
1466bfa273eSLuiz Augusto von Dentz 	struct sock *sk;
1476bfa273eSLuiz Augusto von Dentz 
1486bfa273eSLuiz Augusto von Dentz 	sk = sk_alloc(net, PF_BLUETOOTH, prio, prot, kern);
1496bfa273eSLuiz Augusto von Dentz 	if (!sk)
1506bfa273eSLuiz Augusto von Dentz 		return NULL;
1516bfa273eSLuiz Augusto von Dentz 
1526bfa273eSLuiz Augusto von Dentz 	sock_init_data(sock, sk);
1536bfa273eSLuiz Augusto von Dentz 	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
1546bfa273eSLuiz Augusto von Dentz 
1556bfa273eSLuiz Augusto von Dentz 	sock_reset_flag(sk, SOCK_ZAPPED);
1566bfa273eSLuiz Augusto von Dentz 
1576bfa273eSLuiz Augusto von Dentz 	sk->sk_protocol = proto;
1586bfa273eSLuiz Augusto von Dentz 	sk->sk_state    = BT_OPEN;
1596bfa273eSLuiz Augusto von Dentz 
160464c702fSLuiz Augusto von Dentz 	/* Init peer information so it can be properly monitored */
161464c702fSLuiz Augusto von Dentz 	if (!kern) {
162464c702fSLuiz Augusto von Dentz 		spin_lock(&sk->sk_peer_lock);
163464c702fSLuiz Augusto von Dentz 		sk->sk_peer_pid  = get_pid(task_tgid(current));
164464c702fSLuiz Augusto von Dentz 		sk->sk_peer_cred = get_current_cred();
165464c702fSLuiz Augusto von Dentz 		spin_unlock(&sk->sk_peer_lock);
166464c702fSLuiz Augusto von Dentz 	}
167464c702fSLuiz Augusto von Dentz 
1686bfa273eSLuiz Augusto von Dentz 	return sk;
1696bfa273eSLuiz Augusto von Dentz }
1706bfa273eSLuiz Augusto von Dentz EXPORT_SYMBOL(bt_sock_alloc);
1716bfa273eSLuiz Augusto von Dentz 
bt_sock_link(struct bt_sock_list * l,struct sock * sk)1721da177e4SLinus Torvalds void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
1731da177e4SLinus Torvalds {
17494f5bfb8SGustavo F. Padovan 	write_lock(&l->lock);
1751da177e4SLinus Torvalds 	sk_add_node(sk, &l->head);
17694f5bfb8SGustavo F. Padovan 	write_unlock(&l->lock);
1771da177e4SLinus Torvalds }
1781da177e4SLinus Torvalds EXPORT_SYMBOL(bt_sock_link);
1791da177e4SLinus Torvalds 
bt_sock_unlink(struct bt_sock_list * l,struct sock * sk)1801da177e4SLinus Torvalds void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
1811da177e4SLinus Torvalds {
18294f5bfb8SGustavo F. Padovan 	write_lock(&l->lock);
1831da177e4SLinus Torvalds 	sk_del_node_init(sk);
18494f5bfb8SGustavo F. Padovan 	write_unlock(&l->lock);
1851da177e4SLinus Torvalds }
1861da177e4SLinus Torvalds EXPORT_SYMBOL(bt_sock_unlink);
1871da177e4SLinus Torvalds 
bt_accept_enqueue(struct sock * parent,struct sock * sk,bool bh)188c4f5627fSMatthias Kaehlcke void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
1891da177e4SLinus Torvalds {
190464c702fSLuiz Augusto von Dentz 	const struct cred *old_cred;
191464c702fSLuiz Augusto von Dentz 	struct pid *old_pid;
192464c702fSLuiz Augusto von Dentz 
1931da177e4SLinus Torvalds 	BT_DBG("parent %p, sk %p", parent, sk);
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds 	sock_hold(sk);
196c4f5627fSMatthias Kaehlcke 
197c4f5627fSMatthias Kaehlcke 	if (bh)
198c4f5627fSMatthias Kaehlcke 		bh_lock_sock_nested(sk);
199c4f5627fSMatthias Kaehlcke 	else
200b71c69c2SPhilipp Puschmann 		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
201c4f5627fSMatthias Kaehlcke 
2021da177e4SLinus Torvalds 	list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
2031da177e4SLinus Torvalds 	bt_sk(sk)->parent = parent;
204c4f5627fSMatthias Kaehlcke 
205464c702fSLuiz Augusto von Dentz 	/* Copy credentials from parent since for incoming connections the
206464c702fSLuiz Augusto von Dentz 	 * socket is allocated by the kernel.
207464c702fSLuiz Augusto von Dentz 	 */
208464c702fSLuiz Augusto von Dentz 	spin_lock(&sk->sk_peer_lock);
209464c702fSLuiz Augusto von Dentz 	old_pid = sk->sk_peer_pid;
210464c702fSLuiz Augusto von Dentz 	old_cred = sk->sk_peer_cred;
211464c702fSLuiz Augusto von Dentz 	sk->sk_peer_pid = get_pid(parent->sk_peer_pid);
212464c702fSLuiz Augusto von Dentz 	sk->sk_peer_cred = get_cred(parent->sk_peer_cred);
213464c702fSLuiz Augusto von Dentz 	spin_unlock(&sk->sk_peer_lock);
214464c702fSLuiz Augusto von Dentz 
215464c702fSLuiz Augusto von Dentz 	put_pid(old_pid);
216464c702fSLuiz Augusto von Dentz 	put_cred(old_cred);
217464c702fSLuiz Augusto von Dentz 
218c4f5627fSMatthias Kaehlcke 	if (bh)
219c4f5627fSMatthias Kaehlcke 		bh_unlock_sock(sk);
220c4f5627fSMatthias Kaehlcke 	else
221e1633762SDean Jenkins 		release_sock(sk);
222c4f5627fSMatthias Kaehlcke 
2237976a11bSEric Dumazet 	sk_acceptq_added(parent);
2241da177e4SLinus Torvalds }
2251da177e4SLinus Torvalds EXPORT_SYMBOL(bt_accept_enqueue);
2261da177e4SLinus Torvalds 
22727bfbc21SDean Jenkins /* Calling function must hold the sk lock.
22827bfbc21SDean Jenkins  * bt_sk(sk)->parent must be non-NULL meaning sk is in the parent list.
22927bfbc21SDean Jenkins  */
bt_accept_unlink(struct sock * sk)2301da177e4SLinus Torvalds void bt_accept_unlink(struct sock *sk)
2311da177e4SLinus Torvalds {
2321da177e4SLinus Torvalds 	BT_DBG("sk %p state %d", sk, sk->sk_state);
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 	list_del_init(&bt_sk(sk)->accept_q);
2357976a11bSEric Dumazet 	sk_acceptq_removed(bt_sk(sk)->parent);
2361da177e4SLinus Torvalds 	bt_sk(sk)->parent = NULL;
2371da177e4SLinus Torvalds 	sock_put(sk);
2381da177e4SLinus Torvalds }
2391da177e4SLinus Torvalds EXPORT_SYMBOL(bt_accept_unlink);
2401da177e4SLinus Torvalds 
bt_accept_dequeue(struct sock * parent,struct socket * newsock)2411da177e4SLinus Torvalds struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
2421da177e4SLinus Torvalds {
2437eb7404fSGeliang Tang 	struct bt_sock *s, *n;
2441da177e4SLinus Torvalds 	struct sock *sk;
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds 	BT_DBG("parent %p", parent);
2471da177e4SLinus Torvalds 
24827bfbc21SDean Jenkins restart:
2497eb7404fSGeliang Tang 	list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) {
2507eb7404fSGeliang Tang 		sk = (struct sock *)s;
2511da177e4SLinus Torvalds 
25227bfbc21SDean Jenkins 		/* Prevent early freeing of sk due to unlink and sock_kill */
25327bfbc21SDean Jenkins 		sock_hold(sk);
2548a154a8fSGustavo F. Padovan 		lock_sock(sk);
2551da177e4SLinus Torvalds 
25627bfbc21SDean Jenkins 		/* Check sk has not already been unlinked via
25727bfbc21SDean Jenkins 		 * bt_accept_unlink() due to serialisation caused by sk locking
25827bfbc21SDean Jenkins 		 */
25927bfbc21SDean Jenkins 		if (!bt_sk(sk)->parent) {
26027bfbc21SDean Jenkins 			BT_DBG("sk %p, already unlinked", sk);
26127bfbc21SDean Jenkins 			release_sock(sk);
26227bfbc21SDean Jenkins 			sock_put(sk);
26327bfbc21SDean Jenkins 
26427bfbc21SDean Jenkins 			/* Restart the loop as sk is no longer in the list
26527bfbc21SDean Jenkins 			 * and also avoid a potential infinite loop because
26627bfbc21SDean Jenkins 			 * list_for_each_entry_safe() is not thread safe.
26727bfbc21SDean Jenkins 			 */
26827bfbc21SDean Jenkins 			goto restart;
26927bfbc21SDean Jenkins 		}
27027bfbc21SDean Jenkins 
27127bfbc21SDean Jenkins 		/* sk is safely in the parent list so reduce reference count */
27227bfbc21SDean Jenkins 		sock_put(sk);
27327bfbc21SDean Jenkins 
2741da177e4SLinus Torvalds 		/* FIXME: Is this check still needed */
2751da177e4SLinus Torvalds 		if (sk->sk_state == BT_CLOSED) {
2761da177e4SLinus Torvalds 			bt_accept_unlink(sk);
2771a11ec89SYichen Zhao 			release_sock(sk);
2781da177e4SLinus Torvalds 			continue;
2791da177e4SLinus Torvalds 		}
2801da177e4SLinus Torvalds 
281c4f912e1SMarcel Holtmann 		if (sk->sk_state == BT_CONNECTED || !newsock ||
282d060991fSVinicius Costa Gomes 		    test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
2831da177e4SLinus Torvalds 			bt_accept_unlink(sk);
2841da177e4SLinus Torvalds 			if (newsock)
2851da177e4SLinus Torvalds 				sock_graft(sk, newsock);
286d37f50e1SAndrei Emeltchenko 
2878a154a8fSGustavo F. Padovan 			release_sock(sk);
2881da177e4SLinus Torvalds 			return sk;
2891da177e4SLinus Torvalds 		}
2901da177e4SLinus Torvalds 
2918a154a8fSGustavo F. Padovan 		release_sock(sk);
2921da177e4SLinus Torvalds 	}
293d37f50e1SAndrei Emeltchenko 
2941da177e4SLinus Torvalds 	return NULL;
2951da177e4SLinus Torvalds }
2961da177e4SLinus Torvalds EXPORT_SYMBOL(bt_accept_dequeue);
2971da177e4SLinus Torvalds 
bt_sock_recvmsg(struct socket * sock,struct msghdr * msg,size_t len,int flags)2981b784140SYing Xue int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
2991b784140SYing Xue 		    int flags)
3001da177e4SLinus Torvalds {
3011da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
3021da177e4SLinus Torvalds 	struct sk_buff *skb;
3031da177e4SLinus Torvalds 	size_t copied;
304b5f34f94SDenis Kenzior 	size_t skblen;
3051da177e4SLinus Torvalds 	int err;
3061da177e4SLinus Torvalds 
307a418b893SMarcel Holtmann 	BT_DBG("sock %p sk %p len %zu", sock, sk, len);
3081da177e4SLinus Torvalds 
309d94a6104SMarcel Holtmann 	if (flags & MSG_OOB)
3101da177e4SLinus Torvalds 		return -EOPNOTSUPP;
3111da177e4SLinus Torvalds 
312f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &err);
3135a08ecceSAndrei Emeltchenko 	if (!skb) {
314f3d33426SHannes Frederic Sowa 		if (sk->sk_shutdown & RCV_SHUTDOWN)
3152e07e834SHyunwoo Kim 			err = 0;
316f3d33426SHannes Frederic Sowa 
3171da177e4SLinus Torvalds 		return err;
3181da177e4SLinus Torvalds 	}
3191da177e4SLinus Torvalds 
320b5f34f94SDenis Kenzior 	skblen = skb->len;
3211da177e4SLinus Torvalds 	copied = skb->len;
3221da177e4SLinus Torvalds 	if (len < copied) {
3231da177e4SLinus Torvalds 		msg->msg_flags |= MSG_TRUNC;
3241da177e4SLinus Torvalds 		copied = len;
3251da177e4SLinus Torvalds 	}
3261da177e4SLinus Torvalds 
327badff6d0SArnaldo Carvalho de Melo 	skb_reset_transport_header(skb);
32851f3d02bSDavid S. Miller 	err = skb_copy_datagram_msg(skb, 0, msg, copied);
329d9763698SMarcel Holtmann 	if (err == 0) {
3306fd1d51cSErin MacNeil 		sock_recv_cmsgs(msg, sk, skb);
3311da177e4SLinus Torvalds 
3329dcbc313SEzequiel Garcia 		if (msg->msg_name && bt_sk(sk)->skb_msg_name)
333d9763698SMarcel Holtmann 			bt_sk(sk)->skb_msg_name(skb, msg->msg_name,
334d9763698SMarcel Holtmann 						&msg->msg_namelen);
33500398e1dSAlain Michaud 
3363f19ffb2SLuiz Augusto von Dentz 		if (test_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags)) {
3373f19ffb2SLuiz Augusto von Dentz 			u8 pkt_status = hci_skb_pkt_status(skb);
3383f19ffb2SLuiz Augusto von Dentz 
3393f19ffb2SLuiz Augusto von Dentz 			put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS,
3403f19ffb2SLuiz Augusto von Dentz 				 sizeof(pkt_status), &pkt_status);
3413f19ffb2SLuiz Augusto von Dentz 		}
342d9763698SMarcel Holtmann 	}
343d9763698SMarcel Holtmann 
3441da177e4SLinus Torvalds 	skb_free_datagram(sk, skb);
3451da177e4SLinus Torvalds 
34690a56f72SLuiz Augusto von Dentz 	if (flags & MSG_TRUNC)
347b5f34f94SDenis Kenzior 		copied = skblen;
348b5f34f94SDenis Kenzior 
3491da177e4SLinus Torvalds 	return err ? : copied;
3501da177e4SLinus Torvalds }
3511da177e4SLinus Torvalds EXPORT_SYMBOL(bt_sock_recvmsg);
3521da177e4SLinus Torvalds 
bt_sock_data_wait(struct sock * sk,long timeo)353796c86eeSMat Martineau static long bt_sock_data_wait(struct sock *sk, long timeo)
354796c86eeSMat Martineau {
355796c86eeSMat Martineau 	DECLARE_WAITQUEUE(wait, current);
356796c86eeSMat Martineau 
357796c86eeSMat Martineau 	add_wait_queue(sk_sleep(sk), &wait);
358796c86eeSMat Martineau 	for (;;) {
359796c86eeSMat Martineau 		set_current_state(TASK_INTERRUPTIBLE);
360796c86eeSMat Martineau 
361796c86eeSMat Martineau 		if (!skb_queue_empty(&sk->sk_receive_queue))
362796c86eeSMat Martineau 			break;
363796c86eeSMat Martineau 
364796c86eeSMat Martineau 		if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
365796c86eeSMat Martineau 			break;
366796c86eeSMat Martineau 
367796c86eeSMat Martineau 		if (signal_pending(current) || !timeo)
368796c86eeSMat Martineau 			break;
369796c86eeSMat Martineau 
3709cd3e072SEric Dumazet 		sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
371796c86eeSMat Martineau 		release_sock(sk);
372796c86eeSMat Martineau 		timeo = schedule_timeout(timeo);
373796c86eeSMat Martineau 		lock_sock(sk);
3749cd3e072SEric Dumazet 		sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
375796c86eeSMat Martineau 	}
376796c86eeSMat Martineau 
377796c86eeSMat Martineau 	__set_current_state(TASK_RUNNING);
378796c86eeSMat Martineau 	remove_wait_queue(sk_sleep(sk), &wait);
379796c86eeSMat Martineau 	return timeo;
380796c86eeSMat Martineau }
381796c86eeSMat Martineau 
bt_sock_stream_recvmsg(struct socket * sock,struct msghdr * msg,size_t size,int flags)3821b784140SYing Xue int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg,
3831b784140SYing Xue 			   size_t size, int flags)
384796c86eeSMat Martineau {
385796c86eeSMat Martineau 	struct sock *sk = sock->sk;
386796c86eeSMat Martineau 	int err = 0;
387796c86eeSMat Martineau 	size_t target, copied = 0;
388796c86eeSMat Martineau 	long timeo;
389796c86eeSMat Martineau 
390796c86eeSMat Martineau 	if (flags & MSG_OOB)
391796c86eeSMat Martineau 		return -EOPNOTSUPP;
392796c86eeSMat Martineau 
393796c86eeSMat Martineau 	BT_DBG("sk %p size %zu", sk, size);
394796c86eeSMat Martineau 
395796c86eeSMat Martineau 	lock_sock(sk);
396796c86eeSMat Martineau 
397796c86eeSMat Martineau 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
398796c86eeSMat Martineau 	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
399796c86eeSMat Martineau 
400796c86eeSMat Martineau 	do {
401796c86eeSMat Martineau 		struct sk_buff *skb;
402796c86eeSMat Martineau 		int chunk;
403796c86eeSMat Martineau 
404796c86eeSMat Martineau 		skb = skb_dequeue(&sk->sk_receive_queue);
405796c86eeSMat Martineau 		if (!skb) {
406796c86eeSMat Martineau 			if (copied >= target)
407796c86eeSMat Martineau 				break;
408796c86eeSMat Martineau 
4095a08ecceSAndrei Emeltchenko 			err = sock_error(sk);
4105a08ecceSAndrei Emeltchenko 			if (err)
411796c86eeSMat Martineau 				break;
412796c86eeSMat Martineau 			if (sk->sk_shutdown & RCV_SHUTDOWN)
413796c86eeSMat Martineau 				break;
414796c86eeSMat Martineau 
415796c86eeSMat Martineau 			err = -EAGAIN;
416796c86eeSMat Martineau 			if (!timeo)
417796c86eeSMat Martineau 				break;
418796c86eeSMat Martineau 
419796c86eeSMat Martineau 			timeo = bt_sock_data_wait(sk, timeo);
420796c86eeSMat Martineau 
421796c86eeSMat Martineau 			if (signal_pending(current)) {
422796c86eeSMat Martineau 				err = sock_intr_errno(timeo);
423796c86eeSMat Martineau 				goto out;
424796c86eeSMat Martineau 			}
425796c86eeSMat Martineau 			continue;
426796c86eeSMat Martineau 		}
427796c86eeSMat Martineau 
428796c86eeSMat Martineau 		chunk = min_t(unsigned int, skb->len, size);
42951f3d02bSDavid S. Miller 		if (skb_copy_datagram_msg(skb, 0, msg, chunk)) {
430796c86eeSMat Martineau 			skb_queue_head(&sk->sk_receive_queue, skb);
431796c86eeSMat Martineau 			if (!copied)
432796c86eeSMat Martineau 				copied = -EFAULT;
433796c86eeSMat Martineau 			break;
434796c86eeSMat Martineau 		}
435796c86eeSMat Martineau 		copied += chunk;
436796c86eeSMat Martineau 		size   -= chunk;
437796c86eeSMat Martineau 
4386fd1d51cSErin MacNeil 		sock_recv_cmsgs(msg, sk, skb);
439796c86eeSMat Martineau 
440796c86eeSMat Martineau 		if (!(flags & MSG_PEEK)) {
4415b668eb3SMat Martineau 			int skb_len = skb_headlen(skb);
4425b668eb3SMat Martineau 
4435b668eb3SMat Martineau 			if (chunk <= skb_len) {
4445b668eb3SMat Martineau 				__skb_pull(skb, chunk);
4455b668eb3SMat Martineau 			} else {
4465b668eb3SMat Martineau 				struct sk_buff *frag;
4475b668eb3SMat Martineau 
4485b668eb3SMat Martineau 				__skb_pull(skb, skb_len);
4495b668eb3SMat Martineau 				chunk -= skb_len;
4505b668eb3SMat Martineau 
4515b668eb3SMat Martineau 				skb_walk_frags(skb, frag) {
4525b668eb3SMat Martineau 					if (chunk <= frag->len) {
4535b668eb3SMat Martineau 						/* Pulling partial data */
4545b668eb3SMat Martineau 						skb->len -= chunk;
4555b668eb3SMat Martineau 						skb->data_len -= chunk;
4565b668eb3SMat Martineau 						__skb_pull(frag, chunk);
4575b668eb3SMat Martineau 						break;
4585b668eb3SMat Martineau 					} else if (frag->len) {
4595b668eb3SMat Martineau 						/* Pulling all frag data */
4605b668eb3SMat Martineau 						chunk -= frag->len;
4615b668eb3SMat Martineau 						skb->len -= frag->len;
4625b668eb3SMat Martineau 						skb->data_len -= frag->len;
4635b668eb3SMat Martineau 						__skb_pull(frag, frag->len);
4645b668eb3SMat Martineau 					}
4655b668eb3SMat Martineau 				}
4665b668eb3SMat Martineau 			}
4675b668eb3SMat Martineau 
468796c86eeSMat Martineau 			if (skb->len) {
469796c86eeSMat Martineau 				skb_queue_head(&sk->sk_receive_queue, skb);
470796c86eeSMat Martineau 				break;
471796c86eeSMat Martineau 			}
472796c86eeSMat Martineau 			kfree_skb(skb);
473796c86eeSMat Martineau 
474796c86eeSMat Martineau 		} else {
475796c86eeSMat Martineau 			/* put message back and return */
476796c86eeSMat Martineau 			skb_queue_head(&sk->sk_receive_queue, skb);
477796c86eeSMat Martineau 			break;
478796c86eeSMat Martineau 		}
479796c86eeSMat Martineau 	} while (size);
480796c86eeSMat Martineau 
481796c86eeSMat Martineau out:
482796c86eeSMat Martineau 	release_sock(sk);
483796c86eeSMat Martineau 	return copied ? : err;
484796c86eeSMat Martineau }
485796c86eeSMat Martineau EXPORT_SYMBOL(bt_sock_stream_recvmsg);
486796c86eeSMat Martineau 
bt_accept_poll(struct sock * parent)487ade994f4SAl Viro static inline __poll_t bt_accept_poll(struct sock *parent)
4881da177e4SLinus Torvalds {
4897eb7404fSGeliang Tang 	struct bt_sock *s, *n;
4901da177e4SLinus Torvalds 	struct sock *sk;
4911da177e4SLinus Torvalds 
4927eb7404fSGeliang Tang 	list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) {
4937eb7404fSGeliang Tang 		sk = (struct sock *)s;
494d5f2d2beSMarcel Holtmann 		if (sk->sk_state == BT_CONNECTED ||
495c5daa683SGustavo Padovan 		    (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
496d5f2d2beSMarcel Holtmann 		     sk->sk_state == BT_CONNECT2))
497a9a08845SLinus Torvalds 			return EPOLLIN | EPOLLRDNORM;
4981da177e4SLinus Torvalds 	}
4991da177e4SLinus Torvalds 
5001da177e4SLinus Torvalds 	return 0;
5011da177e4SLinus Torvalds }
5021da177e4SLinus Torvalds 
bt_sock_poll(struct file * file,struct socket * sock,poll_table * wait)503a11e1d43SLinus Torvalds __poll_t bt_sock_poll(struct file *file, struct socket *sock,
504a11e1d43SLinus Torvalds 		      poll_table *wait)
5051da177e4SLinus Torvalds {
5061da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
507ade994f4SAl Viro 	__poll_t mask = 0;
5081da177e4SLinus Torvalds 
509a11e1d43SLinus Torvalds 	poll_wait(file, sk_sleep(sk), wait);
510a11e1d43SLinus Torvalds 
5111da177e4SLinus Torvalds 	if (sk->sk_state == BT_LISTEN)
5121da177e4SLinus Torvalds 		return bt_accept_poll(sk);
5131da177e4SLinus Torvalds 
5143ef7cf57SEric Dumazet 	if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
515a9a08845SLinus Torvalds 		mask |= EPOLLERR |
516a9a08845SLinus Torvalds 			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
5171da177e4SLinus Torvalds 
518f348d70aSDavide Libenzi 	if (sk->sk_shutdown & RCV_SHUTDOWN)
519a9a08845SLinus Torvalds 		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
520f348d70aSDavide Libenzi 
5211da177e4SLinus Torvalds 	if (sk->sk_shutdown == SHUTDOWN_MASK)
522a9a08845SLinus Torvalds 		mask |= EPOLLHUP;
5231da177e4SLinus Torvalds 
5243ef7cf57SEric Dumazet 	if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
525a9a08845SLinus Torvalds 		mask |= EPOLLIN | EPOLLRDNORM;
5261da177e4SLinus Torvalds 
5271da177e4SLinus Torvalds 	if (sk->sk_state == BT_CLOSED)
528a9a08845SLinus Torvalds 		mask |= EPOLLHUP;
5291da177e4SLinus Torvalds 
5301da177e4SLinus Torvalds 	if (sk->sk_state == BT_CONNECT ||
5311da177e4SLinus Torvalds 	    sk->sk_state == BT_CONNECT2 ||
5321da177e4SLinus Torvalds 	    sk->sk_state == BT_CONFIG)
5331da177e4SLinus Torvalds 		return mask;
5341da177e4SLinus Torvalds 
535c5daa683SGustavo Padovan 	if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
536a9a08845SLinus Torvalds 		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
5371da177e4SLinus Torvalds 	else
5389cd3e072SEric Dumazet 		sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
5391da177e4SLinus Torvalds 
5401da177e4SLinus Torvalds 	return mask;
5411da177e4SLinus Torvalds }
542a11e1d43SLinus Torvalds EXPORT_SYMBOL(bt_sock_poll);
5431da177e4SLinus Torvalds 
bt_sock_ioctl(struct socket * sock,unsigned int cmd,unsigned long arg)5443241ad82SMarcel Holtmann int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
5453241ad82SMarcel Holtmann {
5463241ad82SMarcel Holtmann 	struct sock *sk = sock->sk;
54743cbeee9SMarcel Holtmann 	struct sk_buff *skb;
54843cbeee9SMarcel Holtmann 	long amount;
5493241ad82SMarcel Holtmann 	int err;
5503241ad82SMarcel Holtmann 
5513241ad82SMarcel Holtmann 	BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
5523241ad82SMarcel Holtmann 
5533241ad82SMarcel Holtmann 	switch (cmd) {
55443cbeee9SMarcel Holtmann 	case TIOCOUTQ:
55543cbeee9SMarcel Holtmann 		if (sk->sk_state == BT_LISTEN)
55643cbeee9SMarcel Holtmann 			return -EINVAL;
55743cbeee9SMarcel Holtmann 
55831e6d363SEric Dumazet 		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
55943cbeee9SMarcel Holtmann 		if (amount < 0)
56043cbeee9SMarcel Holtmann 			amount = 0;
56143cbeee9SMarcel Holtmann 		err = put_user(amount, (int __user *)arg);
56243cbeee9SMarcel Holtmann 		break;
56343cbeee9SMarcel Holtmann 
56443cbeee9SMarcel Holtmann 	case TIOCINQ:
56543cbeee9SMarcel Holtmann 		if (sk->sk_state == BT_LISTEN)
56643cbeee9SMarcel Holtmann 			return -EINVAL;
56743cbeee9SMarcel Holtmann 
568*f7b94bdcSLuiz Augusto von Dentz 		spin_lock(&sk->sk_receive_queue.lock);
56943cbeee9SMarcel Holtmann 		skb = skb_peek(&sk->sk_receive_queue);
57043cbeee9SMarcel Holtmann 		amount = skb ? skb->len : 0;
571*f7b94bdcSLuiz Augusto von Dentz 		spin_unlock(&sk->sk_receive_queue.lock);
572*f7b94bdcSLuiz Augusto von Dentz 
57343cbeee9SMarcel Holtmann 		err = put_user(amount, (int __user *)arg);
57443cbeee9SMarcel Holtmann 		break;
57543cbeee9SMarcel Holtmann 
5763241ad82SMarcel Holtmann 	default:
5773241ad82SMarcel Holtmann 		err = -ENOIOCTLCMD;
5783241ad82SMarcel Holtmann 		break;
5793241ad82SMarcel Holtmann 	}
5803241ad82SMarcel Holtmann 
5813241ad82SMarcel Holtmann 	return err;
5823241ad82SMarcel Holtmann }
5833241ad82SMarcel Holtmann EXPORT_SYMBOL(bt_sock_ioctl);
5843241ad82SMarcel Holtmann 
5850fba96f9SJohan Hedberg /* This function expects the sk lock to be held when called */
bt_sock_wait_state(struct sock * sk,int state,unsigned long timeo)5861da177e4SLinus Torvalds int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
5871da177e4SLinus Torvalds {
5881da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(wait, current);
5891da177e4SLinus Torvalds 	int err = 0;
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds 	BT_DBG("sk %p", sk);
5921da177e4SLinus Torvalds 
593aa395145SEric Dumazet 	add_wait_queue(sk_sleep(sk), &wait);
5941da177e4SLinus Torvalds 	set_current_state(TASK_INTERRUPTIBLE);
5959be4e3fbSPeter Hurley 	while (sk->sk_state != state) {
5961da177e4SLinus Torvalds 		if (!timeo) {
597b4c612a4SMarcel Holtmann 			err = -EINPROGRESS;
5981da177e4SLinus Torvalds 			break;
5991da177e4SLinus Torvalds 		}
6001da177e4SLinus Torvalds 
6011da177e4SLinus Torvalds 		if (signal_pending(current)) {
6021da177e4SLinus Torvalds 			err = sock_intr_errno(timeo);
6031da177e4SLinus Torvalds 			break;
6041da177e4SLinus Torvalds 		}
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 		release_sock(sk);
6071da177e4SLinus Torvalds 		timeo = schedule_timeout(timeo);
6081da177e4SLinus Torvalds 		lock_sock(sk);
6099be4e3fbSPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds 		err = sock_error(sk);
612c1cbe4b7SBenjamin LaHaise 		if (err)
6131da177e4SLinus Torvalds 			break;
6141da177e4SLinus Torvalds 	}
6159be4e3fbSPeter Hurley 	__set_current_state(TASK_RUNNING);
616aa395145SEric Dumazet 	remove_wait_queue(sk_sleep(sk), &wait);
6171da177e4SLinus Torvalds 	return err;
6181da177e4SLinus Torvalds }
6191da177e4SLinus Torvalds EXPORT_SYMBOL(bt_sock_wait_state);
6201da177e4SLinus Torvalds 
621e793dcf0SJohan Hedberg /* This function expects the sk lock to be held when called */
bt_sock_wait_ready(struct sock * sk,unsigned int msg_flags)622da891217SGavin Li int bt_sock_wait_ready(struct sock *sk, unsigned int msg_flags)
623e793dcf0SJohan Hedberg {
624e793dcf0SJohan Hedberg 	DECLARE_WAITQUEUE(wait, current);
625e793dcf0SJohan Hedberg 	unsigned long timeo;
626e793dcf0SJohan Hedberg 	int err = 0;
627e793dcf0SJohan Hedberg 
628e793dcf0SJohan Hedberg 	BT_DBG("sk %p", sk);
629e793dcf0SJohan Hedberg 
630da891217SGavin Li 	timeo = sock_sndtimeo(sk, !!(msg_flags & MSG_DONTWAIT));
631e793dcf0SJohan Hedberg 
632e793dcf0SJohan Hedberg 	add_wait_queue(sk_sleep(sk), &wait);
633e793dcf0SJohan Hedberg 	set_current_state(TASK_INTERRUPTIBLE);
634e793dcf0SJohan Hedberg 	while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) {
635e793dcf0SJohan Hedberg 		if (!timeo) {
636e793dcf0SJohan Hedberg 			err = -EAGAIN;
637e793dcf0SJohan Hedberg 			break;
638e793dcf0SJohan Hedberg 		}
639e793dcf0SJohan Hedberg 
640e793dcf0SJohan Hedberg 		if (signal_pending(current)) {
641e793dcf0SJohan Hedberg 			err = sock_intr_errno(timeo);
642e793dcf0SJohan Hedberg 			break;
643e793dcf0SJohan Hedberg 		}
644e793dcf0SJohan Hedberg 
645e793dcf0SJohan Hedberg 		release_sock(sk);
646e793dcf0SJohan Hedberg 		timeo = schedule_timeout(timeo);
647e793dcf0SJohan Hedberg 		lock_sock(sk);
648e793dcf0SJohan Hedberg 		set_current_state(TASK_INTERRUPTIBLE);
649e793dcf0SJohan Hedberg 
650e793dcf0SJohan Hedberg 		err = sock_error(sk);
651e793dcf0SJohan Hedberg 		if (err)
652e793dcf0SJohan Hedberg 			break;
653e793dcf0SJohan Hedberg 	}
654e793dcf0SJohan Hedberg 	__set_current_state(TASK_RUNNING);
655e793dcf0SJohan Hedberg 	remove_wait_queue(sk_sleep(sk), &wait);
656e793dcf0SJohan Hedberg 
657e793dcf0SJohan Hedberg 	return err;
658e793dcf0SJohan Hedberg }
659e793dcf0SJohan Hedberg EXPORT_SYMBOL(bt_sock_wait_ready);
660e793dcf0SJohan Hedberg 
661256a06c8SMasatake YAMATO #ifdef CONFIG_PROC_FS
bt_seq_start(struct seq_file * seq,loff_t * pos)662256a06c8SMasatake YAMATO static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
663256a06c8SMasatake YAMATO 	__acquires(seq->private->l->lock)
664256a06c8SMasatake YAMATO {
665359745d7SMuchun Song 	struct bt_sock_list *l = pde_data(file_inode(seq->file));
666256a06c8SMasatake YAMATO 
667256a06c8SMasatake YAMATO 	read_lock(&l->lock);
668256a06c8SMasatake YAMATO 	return seq_hlist_start_head(&l->head, *pos);
669256a06c8SMasatake YAMATO }
670256a06c8SMasatake YAMATO 
bt_seq_next(struct seq_file * seq,void * v,loff_t * pos)671256a06c8SMasatake YAMATO static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
672256a06c8SMasatake YAMATO {
673359745d7SMuchun Song 	struct bt_sock_list *l = pde_data(file_inode(seq->file));
674256a06c8SMasatake YAMATO 
675256a06c8SMasatake YAMATO 	return seq_hlist_next(v, &l->head, pos);
676256a06c8SMasatake YAMATO }
677256a06c8SMasatake YAMATO 
bt_seq_stop(struct seq_file * seq,void * v)678256a06c8SMasatake YAMATO static void bt_seq_stop(struct seq_file *seq, void *v)
679256a06c8SMasatake YAMATO 	__releases(seq->private->l->lock)
680256a06c8SMasatake YAMATO {
681359745d7SMuchun Song 	struct bt_sock_list *l = pde_data(file_inode(seq->file));
682256a06c8SMasatake YAMATO 
683256a06c8SMasatake YAMATO 	read_unlock(&l->lock);
684256a06c8SMasatake YAMATO }
685256a06c8SMasatake YAMATO 
bt_seq_show(struct seq_file * seq,void * v)686256a06c8SMasatake YAMATO static int bt_seq_show(struct seq_file *seq, void *v)
687256a06c8SMasatake YAMATO {
688359745d7SMuchun Song 	struct bt_sock_list *l = pde_data(file_inode(seq->file));
689256a06c8SMasatake YAMATO 
690256a06c8SMasatake YAMATO 	if (v == SEQ_START_TOKEN) {
691c5605755SMarcel Holtmann 		seq_puts(seq, "sk               RefCnt Rmem   Wmem   User   Inode  Parent");
692256a06c8SMasatake YAMATO 
693256a06c8SMasatake YAMATO 		if (l->custom_seq_show) {
694256a06c8SMasatake YAMATO 			seq_putc(seq, ' ');
695256a06c8SMasatake YAMATO 			l->custom_seq_show(seq, v);
696256a06c8SMasatake YAMATO 		}
697256a06c8SMasatake YAMATO 
698256a06c8SMasatake YAMATO 		seq_putc(seq, '\n');
699256a06c8SMasatake YAMATO 	} else {
70009d5d4aaSAndrei Emeltchenko 		struct sock *sk = sk_entry(v);
70109d5d4aaSAndrei Emeltchenko 		struct bt_sock *bt = bt_sk(sk);
702256a06c8SMasatake YAMATO 
7037028a886SAndrei Emeltchenko 		seq_printf(seq,
7045f6cd79fSMarcel Holtmann 			   "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu",
705256a06c8SMasatake YAMATO 			   sk,
70641c6d650SReshetova, Elena 			   refcount_read(&sk->sk_refcnt),
707256a06c8SMasatake YAMATO 			   sk_rmem_alloc_get(sk),
708256a06c8SMasatake YAMATO 			   sk_wmem_alloc_get(sk),
7091bbb3095SEric W. Biederman 			   from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
710256a06c8SMasatake YAMATO 			   sock_i_ino(sk),
711256a06c8SMasatake YAMATO 			   bt->parent ? sock_i_ino(bt->parent) : 0LU);
712256a06c8SMasatake YAMATO 
713256a06c8SMasatake YAMATO 		if (l->custom_seq_show) {
714256a06c8SMasatake YAMATO 			seq_putc(seq, ' ');
715256a06c8SMasatake YAMATO 			l->custom_seq_show(seq, v);
716256a06c8SMasatake YAMATO 		}
717256a06c8SMasatake YAMATO 
718256a06c8SMasatake YAMATO 		seq_putc(seq, '\n');
719256a06c8SMasatake YAMATO 	}
720256a06c8SMasatake YAMATO 	return 0;
721256a06c8SMasatake YAMATO }
722256a06c8SMasatake YAMATO 
72326b0f4e2SFabian Frederick static const struct seq_operations bt_seq_ops = {
724256a06c8SMasatake YAMATO 	.start = bt_seq_start,
725256a06c8SMasatake YAMATO 	.next  = bt_seq_next,
726256a06c8SMasatake YAMATO 	.stop  = bt_seq_stop,
727256a06c8SMasatake YAMATO 	.show  = bt_seq_show,
728256a06c8SMasatake YAMATO };
729256a06c8SMasatake YAMATO 
bt_procfs_init(struct net * net,const char * name,struct bt_sock_list * sk_list,int (* seq_show)(struct seq_file *,void *))730b0316615SAl Viro int bt_procfs_init(struct net *net, const char *name,
731256a06c8SMasatake YAMATO 		   struct bt_sock_list *sk_list,
732256a06c8SMasatake YAMATO 		   int (*seq_show)(struct seq_file *, void *))
733256a06c8SMasatake YAMATO {
734256a06c8SMasatake YAMATO 	sk_list->custom_seq_show = seq_show;
735256a06c8SMasatake YAMATO 
736a9170e0aSChristoph Hellwig 	if (!proc_create_seq_data(name, 0, net->proc_net, &bt_seq_ops, sk_list))
737256a06c8SMasatake YAMATO 		return -ENOMEM;
738256a06c8SMasatake YAMATO 	return 0;
739256a06c8SMasatake YAMATO }
740256a06c8SMasatake YAMATO 
bt_procfs_cleanup(struct net * net,const char * name)741256a06c8SMasatake YAMATO void bt_procfs_cleanup(struct net *net, const char *name)
742256a06c8SMasatake YAMATO {
743ece31ffdSGao feng 	remove_proc_entry(name, net->proc_net);
744256a06c8SMasatake YAMATO }
745256a06c8SMasatake YAMATO #else
bt_procfs_init(struct net * net,const char * name,struct bt_sock_list * sk_list,int (* seq_show)(struct seq_file *,void *))746b0316615SAl Viro int bt_procfs_init(struct net *net, const char *name,
747256a06c8SMasatake YAMATO 		   struct bt_sock_list *sk_list,
748256a06c8SMasatake YAMATO 		   int (*seq_show)(struct seq_file *, void *))
749256a06c8SMasatake YAMATO {
750256a06c8SMasatake YAMATO 	return 0;
751256a06c8SMasatake YAMATO }
752256a06c8SMasatake YAMATO 
bt_procfs_cleanup(struct net * net,const char * name)753256a06c8SMasatake YAMATO void bt_procfs_cleanup(struct net *net, const char *name)
754256a06c8SMasatake YAMATO {
755256a06c8SMasatake YAMATO }
756256a06c8SMasatake YAMATO #endif
757256a06c8SMasatake YAMATO EXPORT_SYMBOL(bt_procfs_init);
758256a06c8SMasatake YAMATO EXPORT_SYMBOL(bt_procfs_cleanup);
759256a06c8SMasatake YAMATO 
760173e7837Slinzhang static const struct net_proto_family bt_sock_family_ops = {
7611da177e4SLinus Torvalds 	.owner	= THIS_MODULE,
7621da177e4SLinus Torvalds 	.family	= PF_BLUETOOTH,
7631da177e4SLinus Torvalds 	.create	= bt_sock_create,
7641da177e4SLinus Torvalds };
7651da177e4SLinus Torvalds 
766ffcecac6SMarcel Holtmann struct dentry *bt_debugfs;
767ffcecac6SMarcel Holtmann EXPORT_SYMBOL_GPL(bt_debugfs);
768ffcecac6SMarcel Holtmann 
7699e8305b3SMarcel Holtmann #define VERSION __stringify(BT_SUBSYS_VERSION) "." \
7709e8305b3SMarcel Holtmann 		__stringify(BT_SUBSYS_REVISION)
7719e8305b3SMarcel Holtmann 
bt_init(void)7721da177e4SLinus Torvalds static int __init bt_init(void)
7731da177e4SLinus Torvalds {
77427d35284SMarcel Holtmann 	int err;
77527d35284SMarcel Holtmann 
776b4772ef8SEyal Birger 	sock_skb_cb_check_size(sizeof(struct bt_skb_cb));
7777cb9d20fSMarcel Holtmann 
7789e8305b3SMarcel Holtmann 	BT_INFO("Core ver %s", VERSION);
7791da177e4SLinus Torvalds 
780ee485290SMarcel Holtmann 	err = bt_selftest();
781ee485290SMarcel Holtmann 	if (err < 0)
782ee485290SMarcel Holtmann 		return err;
783ee485290SMarcel Holtmann 
784ffcecac6SMarcel Holtmann 	bt_debugfs = debugfs_create_dir("bluetooth", NULL);
785ffcecac6SMarcel Holtmann 
786e64c97b5SMarcel Holtmann 	bt_leds_init();
787e64c97b5SMarcel Holtmann 
78827d35284SMarcel Holtmann 	err = bt_sysfs_init();
78927d35284SMarcel Holtmann 	if (err < 0)
7902f3957c7SChen Zhongjin 		goto cleanup_led;
79127d35284SMarcel Holtmann 
79227d35284SMarcel Holtmann 	err = sock_register(&bt_sock_family_ops);
7931b259904SMarkus Elfring 	if (err)
7941b259904SMarkus Elfring 		goto cleanup_sysfs;
7951da177e4SLinus Torvalds 
7961da177e4SLinus Torvalds 	BT_INFO("HCI device and connection manager initialized");
7971da177e4SLinus Torvalds 
79864274518SGustavo F. Padovan 	err = hci_sock_init();
7991b259904SMarkus Elfring 	if (err)
8001b259904SMarkus Elfring 		goto unregister_socket;
80164274518SGustavo F. Padovan 
80264274518SGustavo F. Padovan 	err = l2cap_init();
8031b259904SMarkus Elfring 	if (err)
8041b259904SMarkus Elfring 		goto cleanup_socket;
80564274518SGustavo F. Padovan 
80664274518SGustavo F. Padovan 	err = sco_init();
8071b259904SMarkus Elfring 	if (err)
8081b259904SMarkus Elfring 		goto cleanup_cap;
8091da177e4SLinus Torvalds 
8106d785aa3SJohan Hedberg 	err = mgmt_init();
8111b259904SMarkus Elfring 	if (err)
8121b259904SMarkus Elfring 		goto cleanup_sco;
8136d785aa3SJohan Hedberg 
8141da177e4SLinus Torvalds 	return 0;
81564274518SGustavo F. Padovan 
8161b259904SMarkus Elfring cleanup_sco:
8171b259904SMarkus Elfring 	sco_exit();
8181b259904SMarkus Elfring cleanup_cap:
8191b259904SMarkus Elfring 	l2cap_exit();
8201b259904SMarkus Elfring cleanup_socket:
82164274518SGustavo F. Padovan 	hci_sock_cleanup();
8221b259904SMarkus Elfring unregister_socket:
82364274518SGustavo F. Padovan 	sock_unregister(PF_BLUETOOTH);
8241b259904SMarkus Elfring cleanup_sysfs:
82564274518SGustavo F. Padovan 	bt_sysfs_cleanup();
8262f3957c7SChen Zhongjin cleanup_led:
8272f3957c7SChen Zhongjin 	bt_leds_cleanup();
82864274518SGustavo F. Padovan 	return err;
8291da177e4SLinus Torvalds }
8301da177e4SLinus Torvalds 
bt_exit(void)8311da177e4SLinus Torvalds static void __exit bt_exit(void)
8321da177e4SLinus Torvalds {
8336d785aa3SJohan Hedberg 	mgmt_exit();
8346d785aa3SJohan Hedberg 
83564274518SGustavo F. Padovan 	sco_exit();
83664274518SGustavo F. Padovan 
83764274518SGustavo F. Padovan 	l2cap_exit();
83864274518SGustavo F. Padovan 
8391da177e4SLinus Torvalds 	hci_sock_cleanup();
8401da177e4SLinus Torvalds 
8411da177e4SLinus Torvalds 	sock_unregister(PF_BLUETOOTH);
84227d35284SMarcel Holtmann 
84327d35284SMarcel Holtmann 	bt_sysfs_cleanup();
844ffcecac6SMarcel Holtmann 
845e64c97b5SMarcel Holtmann 	bt_leds_cleanup();
846e64c97b5SMarcel Holtmann 
847ffcecac6SMarcel Holtmann 	debugfs_remove_recursive(bt_debugfs);
8481da177e4SLinus Torvalds }
8491da177e4SLinus Torvalds 
8501da177e4SLinus Torvalds subsys_initcall(bt_init);
8511da177e4SLinus Torvalds module_exit(bt_exit);
8521da177e4SLinus Torvalds 
85363fbd24eSMarcel Holtmann MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
8549e8305b3SMarcel Holtmann MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
8559e8305b3SMarcel Holtmann MODULE_VERSION(VERSION);
8561da177e4SLinus Torvalds MODULE_LICENSE("GPL");
8571da177e4SLinus Torvalds MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);
858