blob: 7c0031ff8cfbbc6b672880f445d33bf6632e8256 [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>
28
29#include <linux/types.h>
30#include <linux/list.h>
31#include <linux/errno.h>
32#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/sched.h>
34#include <linux/slab.h>
35#include <linux/skbuff.h>
36#include <linux/init.h>
37#include <linux/poll.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <net/sock.h>
Marcel Holtmann3241ad82008-07-14 20:13:50 +020039#include <asm/ioctls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/kmod.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#include <net/bluetooth/bluetooth.h>
43
Marcel Holtmann7a9d4022008-11-30 12:17:26 +010044#define VERSION "2.14"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46/* Bluetooth sockets */
47#define BT_MAX_PROTO 8
48static struct net_proto_family *bt_proto[BT_MAX_PROTO];
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010049static DEFINE_RWLOCK(bt_proto_lock);
Dave Young68845cb2008-04-01 23:58:35 -070050
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010051#ifdef CONFIG_DEBUG_LOCK_ALLOC
Dave Young68845cb2008-04-01 23:58:35 -070052static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
53static const char *bt_key_strings[BT_MAX_PROTO] = {
54 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
55 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
56 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
57 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
58 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
59 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
60 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
61 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
62};
63
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010064static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
Dave Young68845cb2008-04-01 23:58:35 -070065static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
66 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
67 "slock-AF_BLUETOOTH-BTPROTO_HCI",
68 "slock-AF_BLUETOOTH-BTPROTO_SCO",
69 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
70 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
71 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
72 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
73 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
74};
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010075
76static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
77{
78 struct sock *sk = sock->sk;
79
80 if (!sk)
81 return;
82
83 BUG_ON(sock_owned_by_user(sk));
84
85 sock_lock_init_class_and_name(sk,
86 bt_slock_key_strings[proto], &bt_slock_key[proto],
87 bt_key_strings[proto], &bt_lock_key[proto]);
88}
89#else
90static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
91{
92}
93#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95int bt_sock_register(int proto, struct net_proto_family *ops)
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 = -EEXIST;
106 else
107 bt_proto[proto] = ops;
108
109 write_unlock(&bt_proto_lock);
110
111 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112}
113EXPORT_SYMBOL(bt_sock_register);
114
115int bt_sock_unregister(int proto)
116{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200117 int err = 0;
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 if (proto < 0 || proto >= BT_MAX_PROTO)
120 return -EINVAL;
121
Marcel Holtmann74da6262006-10-15 17:31:14 +0200122 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Marcel Holtmann74da6262006-10-15 17:31:14 +0200124 if (!bt_proto[proto])
125 err = -ENOENT;
126 else
127 bt_proto[proto] = NULL;
128
129 write_unlock(&bt_proto_lock);
130
131 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132}
133EXPORT_SYMBOL(bt_sock_unregister);
134
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700135static int bt_sock_create(struct net *net, struct socket *sock, int proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200137 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700139 if (net != &init_net)
140 return -EAFNOSUPPORT;
141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 if (proto < 0 || proto >= BT_MAX_PROTO)
143 return -EINVAL;
144
Johannes Berg95a5afc2008-10-16 15:24:51 -0700145 if (!bt_proto[proto])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 request_module("bt-proto-%d", proto);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 err = -EPROTONOSUPPORT;
Marcel Holtmann74da6262006-10-15 17:31:14 +0200149
150 read_lock(&bt_proto_lock);
151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700153 err = bt_proto[proto]->create(net, sock, proto);
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +0100154 bt_sock_reclassify_lock(sock, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 module_put(bt_proto[proto]->owner);
156 }
Marcel Holtmann74da6262006-10-15 17:31:14 +0200157
158 read_unlock(&bt_proto_lock);
159
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900160 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161}
162
163void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
164{
165 write_lock_bh(&l->lock);
166 sk_add_node(sk, &l->head);
167 write_unlock_bh(&l->lock);
168}
169EXPORT_SYMBOL(bt_sock_link);
170
171void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
172{
173 write_lock_bh(&l->lock);
174 sk_del_node_init(sk);
175 write_unlock_bh(&l->lock);
176}
177EXPORT_SYMBOL(bt_sock_unlink);
178
179void bt_accept_enqueue(struct sock *parent, struct sock *sk)
180{
181 BT_DBG("parent %p, sk %p", parent, sk);
182
183 sock_hold(sk);
184 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
185 bt_sk(sk)->parent = parent;
186 parent->sk_ack_backlog++;
187}
188EXPORT_SYMBOL(bt_accept_enqueue);
189
190void bt_accept_unlink(struct sock *sk)
191{
192 BT_DBG("sk %p state %d", sk, sk->sk_state);
193
194 list_del_init(&bt_sk(sk)->accept_q);
195 bt_sk(sk)->parent->sk_ack_backlog--;
196 bt_sk(sk)->parent = NULL;
197 sock_put(sk);
198}
199EXPORT_SYMBOL(bt_accept_unlink);
200
201struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
202{
203 struct list_head *p, *n;
204 struct sock *sk;
205
206 BT_DBG("parent %p", parent);
207
208 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
209 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
210
211 lock_sock(sk);
212
213 /* FIXME: Is this check still needed */
214 if (sk->sk_state == BT_CLOSED) {
215 release_sock(sk);
216 bt_accept_unlink(sk);
217 continue;
218 }
219
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100220 if (sk->sk_state == BT_CONNECTED || !newsock ||
221 bt_sk(parent)->defer_setup) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 bt_accept_unlink(sk);
223 if (newsock)
224 sock_graft(sk, newsock);
225 release_sock(sk);
226 return sk;
227 }
228
229 release_sock(sk);
230 }
231 return NULL;
232}
233EXPORT_SYMBOL(bt_accept_dequeue);
234
235int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100236 struct msghdr *msg, size_t len, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 int noblock = flags & MSG_DONTWAIT;
239 struct sock *sk = sock->sk;
240 struct sk_buff *skb;
241 size_t copied;
242 int err;
243
Marcel Holtmanna418b892008-11-30 12:17:28 +0100244 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246 if (flags & (MSG_OOB))
247 return -EOPNOTSUPP;
248
249 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) {
250 if (sk->sk_shutdown & RCV_SHUTDOWN)
251 return 0;
252 return err;
253 }
254
255 msg->msg_namelen = 0;
256
257 copied = skb->len;
258 if (len < copied) {
259 msg->msg_flags |= MSG_TRUNC;
260 copied = len;
261 }
262
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300263 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200265 if (err == 0)
266 sock_recv_timestamp(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268 skb_free_datagram(sk, skb);
269
270 return err ? : copied;
271}
272EXPORT_SYMBOL(bt_sock_recvmsg);
273
274static inline unsigned int bt_accept_poll(struct sock *parent)
275{
276 struct list_head *p, *n;
277 struct sock *sk;
278
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100279 if (bt_sk(parent)->defer_setup)
280 return POLLIN | POLLRDNORM;
281
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
283 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
284 if (sk->sk_state == BT_CONNECTED)
285 return POLLIN | POLLRDNORM;
286 }
287
288 return 0;
289}
290
291unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
292{
293 struct sock *sk = sock->sk;
294 unsigned int mask = 0;
295
296 BT_DBG("sock %p, sk %p", sock, sk);
297
298 poll_wait(file, sk->sk_sleep, wait);
299
300 if (sk->sk_state == BT_LISTEN)
301 return bt_accept_poll(sk);
302
303 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
304 mask |= POLLERR;
305
Davide Libenzif348d702006-03-25 03:07:39 -0800306 if (sk->sk_shutdown & RCV_SHUTDOWN)
307 mask |= POLLRDHUP;
308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 if (sk->sk_shutdown == SHUTDOWN_MASK)
310 mask |= POLLHUP;
311
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900312 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 (sk->sk_shutdown & RCV_SHUTDOWN))
314 mask |= POLLIN | POLLRDNORM;
315
316 if (sk->sk_state == BT_CLOSED)
317 mask |= POLLHUP;
318
319 if (sk->sk_state == BT_CONNECT ||
320 sk->sk_state == BT_CONNECT2 ||
321 sk->sk_state == BT_CONFIG)
322 return mask;
323
324 if (sock_writeable(sk))
325 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
326 else
327 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
328
329 return mask;
330}
331EXPORT_SYMBOL(bt_sock_poll);
332
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200333int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
334{
335 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200336 struct sk_buff *skb;
337 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200338 int err;
339
340 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
341
342 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200343 case TIOCOUTQ:
344 if (sk->sk_state == BT_LISTEN)
345 return -EINVAL;
346
347 amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
348 if (amount < 0)
349 amount = 0;
350 err = put_user(amount, (int __user *) arg);
351 break;
352
353 case TIOCINQ:
354 if (sk->sk_state == BT_LISTEN)
355 return -EINVAL;
356
357 lock_sock(sk);
358 skb = skb_peek(&sk->sk_receive_queue);
359 amount = skb ? skb->len : 0;
360 release_sock(sk);
361 err = put_user(amount, (int __user *) arg);
362 break;
363
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200364 case SIOCGSTAMP:
365 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
366 break;
367
368 case SIOCGSTAMPNS:
369 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
370 break;
371
372 default:
373 err = -ENOIOCTLCMD;
374 break;
375 }
376
377 return err;
378}
379EXPORT_SYMBOL(bt_sock_ioctl);
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
382{
383 DECLARE_WAITQUEUE(wait, current);
384 int err = 0;
385
386 BT_DBG("sk %p", sk);
387
388 add_wait_queue(sk->sk_sleep, &wait);
389 while (sk->sk_state != state) {
390 set_current_state(TASK_INTERRUPTIBLE);
391
392 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200393 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 break;
395 }
396
397 if (signal_pending(current)) {
398 err = sock_intr_errno(timeo);
399 break;
400 }
401
402 release_sock(sk);
403 timeo = schedule_timeout(timeo);
404 lock_sock(sk);
405
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800406 err = sock_error(sk);
407 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 }
410 set_current_state(TASK_RUNNING);
411 remove_wait_queue(sk->sk_sleep, &wait);
412 return err;
413}
414EXPORT_SYMBOL(bt_sock_wait_state);
415
416static struct net_proto_family bt_sock_family_ops = {
417 .owner = THIS_MODULE,
418 .family = PF_BLUETOOTH,
419 .create = bt_sock_create,
420};
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422static int __init bt_init(void)
423{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200424 int err;
425
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 BT_INFO("Core ver %s", VERSION);
427
Marcel Holtmann27d35282006-07-03 10:02:37 +0200428 err = bt_sysfs_init();
429 if (err < 0)
430 return err;
431
432 err = sock_register(&bt_sock_family_ops);
433 if (err < 0) {
434 bt_sysfs_cleanup();
435 return err;
436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 BT_INFO("HCI device and connection manager initialized");
439
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 hci_sock_init();
441
442 return 0;
443}
444
445static void __exit bt_exit(void)
446{
447 hci_sock_cleanup();
448
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200450
451 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
454subsys_initcall(bt_init);
455module_exit(bt_exit);
456
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200457MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
459MODULE_VERSION(VERSION);
460MODULE_LICENSE("GPL");
461MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);