blob: f6f216e57aa39460443d13e394f750ee7023bf98 [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
44#ifndef CONFIG_BT_SOCK_DEBUG
45#undef BT_DBG
46#define BT_DBG(D...)
47#endif
48
Marcel Holtmann7a9d4022008-11-30 12:17:26 +010049#define VERSION "2.14"
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/* Bluetooth sockets */
52#define BT_MAX_PROTO 8
53static struct net_proto_family *bt_proto[BT_MAX_PROTO];
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010054static DEFINE_RWLOCK(bt_proto_lock);
Dave Young68845cb2008-04-01 23:58:35 -070055
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010056#ifdef CONFIG_DEBUG_LOCK_ALLOC
Dave Young68845cb2008-04-01 23:58:35 -070057static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
58static const char *bt_key_strings[BT_MAX_PROTO] = {
59 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
60 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
61 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
62 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
63 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
64 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
65 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
66 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
67};
68
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010069static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
Dave Young68845cb2008-04-01 23:58:35 -070070static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
71 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
72 "slock-AF_BLUETOOTH-BTPROTO_HCI",
73 "slock-AF_BLUETOOTH-BTPROTO_SCO",
74 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
75 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
76 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
77 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
78 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
79};
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010080
81static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
82{
83 struct sock *sk = sock->sk;
84
85 if (!sk)
86 return;
87
88 BUG_ON(sock_owned_by_user(sk));
89
90 sock_lock_init_class_and_name(sk,
91 bt_slock_key_strings[proto], &bt_slock_key[proto],
92 bt_key_strings[proto], &bt_lock_key[proto]);
93}
94#else
95static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
96{
97}
98#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100int bt_sock_register(int proto, struct net_proto_family *ops)
101{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200102 int err = 0;
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 if (proto < 0 || proto >= BT_MAX_PROTO)
105 return -EINVAL;
106
Marcel Holtmann74da6262006-10-15 17:31:14 +0200107 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Marcel Holtmann74da6262006-10-15 17:31:14 +0200109 if (bt_proto[proto])
110 err = -EEXIST;
111 else
112 bt_proto[proto] = ops;
113
114 write_unlock(&bt_proto_lock);
115
116 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117}
118EXPORT_SYMBOL(bt_sock_register);
119
120int bt_sock_unregister(int proto)
121{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200122 int err = 0;
123
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 if (proto < 0 || proto >= BT_MAX_PROTO)
125 return -EINVAL;
126
Marcel Holtmann74da6262006-10-15 17:31:14 +0200127 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Marcel Holtmann74da6262006-10-15 17:31:14 +0200129 if (!bt_proto[proto])
130 err = -ENOENT;
131 else
132 bt_proto[proto] = NULL;
133
134 write_unlock(&bt_proto_lock);
135
136 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137}
138EXPORT_SYMBOL(bt_sock_unregister);
139
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700140static int bt_sock_create(struct net *net, struct socket *sock, int proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200142 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700144 if (net != &init_net)
145 return -EAFNOSUPPORT;
146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 if (proto < 0 || proto >= BT_MAX_PROTO)
148 return -EINVAL;
149
Johannes Berg95a5afc2008-10-16 15:24:51 -0700150 if (!bt_proto[proto])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 request_module("bt-proto-%d", proto);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 err = -EPROTONOSUPPORT;
Marcel Holtmann74da6262006-10-15 17:31:14 +0200154
155 read_lock(&bt_proto_lock);
156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700158 err = bt_proto[proto]->create(net, sock, proto);
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +0100159 bt_sock_reclassify_lock(sock, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 module_put(bt_proto[proto]->owner);
161 }
Marcel Holtmann74da6262006-10-15 17:31:14 +0200162
163 read_unlock(&bt_proto_lock);
164
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900165 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166}
167
168void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
169{
170 write_lock_bh(&l->lock);
171 sk_add_node(sk, &l->head);
172 write_unlock_bh(&l->lock);
173}
174EXPORT_SYMBOL(bt_sock_link);
175
176void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
177{
178 write_lock_bh(&l->lock);
179 sk_del_node_init(sk);
180 write_unlock_bh(&l->lock);
181}
182EXPORT_SYMBOL(bt_sock_unlink);
183
184void bt_accept_enqueue(struct sock *parent, struct sock *sk)
185{
186 BT_DBG("parent %p, sk %p", parent, sk);
187
188 sock_hold(sk);
189 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
190 bt_sk(sk)->parent = parent;
191 parent->sk_ack_backlog++;
192}
193EXPORT_SYMBOL(bt_accept_enqueue);
194
195void bt_accept_unlink(struct sock *sk)
196{
197 BT_DBG("sk %p state %d", sk, sk->sk_state);
198
199 list_del_init(&bt_sk(sk)->accept_q);
200 bt_sk(sk)->parent->sk_ack_backlog--;
201 bt_sk(sk)->parent = NULL;
202 sock_put(sk);
203}
204EXPORT_SYMBOL(bt_accept_unlink);
205
206struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
207{
208 struct list_head *p, *n;
209 struct sock *sk;
210
211 BT_DBG("parent %p", parent);
212
213 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
214 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
215
216 lock_sock(sk);
217
218 /* FIXME: Is this check still needed */
219 if (sk->sk_state == BT_CLOSED) {
220 release_sock(sk);
221 bt_accept_unlink(sk);
222 continue;
223 }
224
225 if (sk->sk_state == BT_CONNECTED || !newsock) {
226 bt_accept_unlink(sk);
227 if (newsock)
228 sock_graft(sk, newsock);
229 release_sock(sk);
230 return sk;
231 }
232
233 release_sock(sk);
234 }
235 return NULL;
236}
237EXPORT_SYMBOL(bt_accept_dequeue);
238
239int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
240 struct msghdr *msg, size_t len, int flags)
241{
242 int noblock = flags & MSG_DONTWAIT;
243 struct sock *sk = sock->sk;
244 struct sk_buff *skb;
245 size_t copied;
246 int err;
247
248 BT_DBG("sock %p sk %p len %d", sock, sk, len);
249
250 if (flags & (MSG_OOB))
251 return -EOPNOTSUPP;
252
253 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) {
254 if (sk->sk_shutdown & RCV_SHUTDOWN)
255 return 0;
256 return err;
257 }
258
259 msg->msg_namelen = 0;
260
261 copied = skb->len;
262 if (len < copied) {
263 msg->msg_flags |= MSG_TRUNC;
264 copied = len;
265 }
266
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300267 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200269 if (err == 0)
270 sock_recv_timestamp(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 skb_free_datagram(sk, skb);
273
274 return err ? : copied;
275}
276EXPORT_SYMBOL(bt_sock_recvmsg);
277
278static inline unsigned int bt_accept_poll(struct sock *parent)
279{
280 struct list_head *p, *n;
281 struct sock *sk;
282
283 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
284 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
285 if (sk->sk_state == BT_CONNECTED)
286 return POLLIN | POLLRDNORM;
287 }
288
289 return 0;
290}
291
292unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
293{
294 struct sock *sk = sock->sk;
295 unsigned int mask = 0;
296
297 BT_DBG("sock %p, sk %p", sock, sk);
298
299 poll_wait(file, sk->sk_sleep, wait);
300
301 if (sk->sk_state == BT_LISTEN)
302 return bt_accept_poll(sk);
303
304 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
305 mask |= POLLERR;
306
Davide Libenzif348d702006-03-25 03:07:39 -0800307 if (sk->sk_shutdown & RCV_SHUTDOWN)
308 mask |= POLLRDHUP;
309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 if (sk->sk_shutdown == SHUTDOWN_MASK)
311 mask |= POLLHUP;
312
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900313 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 (sk->sk_shutdown & RCV_SHUTDOWN))
315 mask |= POLLIN | POLLRDNORM;
316
317 if (sk->sk_state == BT_CLOSED)
318 mask |= POLLHUP;
319
320 if (sk->sk_state == BT_CONNECT ||
321 sk->sk_state == BT_CONNECT2 ||
322 sk->sk_state == BT_CONFIG)
323 return mask;
324
325 if (sock_writeable(sk))
326 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
327 else
328 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
329
330 return mask;
331}
332EXPORT_SYMBOL(bt_sock_poll);
333
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200334int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
335{
336 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200337 struct sk_buff *skb;
338 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200339 int err;
340
341 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
342
343 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200344 case TIOCOUTQ:
345 if (sk->sk_state == BT_LISTEN)
346 return -EINVAL;
347
348 amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
349 if (amount < 0)
350 amount = 0;
351 err = put_user(amount, (int __user *) arg);
352 break;
353
354 case TIOCINQ:
355 if (sk->sk_state == BT_LISTEN)
356 return -EINVAL;
357
358 lock_sock(sk);
359 skb = skb_peek(&sk->sk_receive_queue);
360 amount = skb ? skb->len : 0;
361 release_sock(sk);
362 err = put_user(amount, (int __user *) arg);
363 break;
364
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200365 case SIOCGSTAMP:
366 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
367 break;
368
369 case SIOCGSTAMPNS:
370 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
371 break;
372
373 default:
374 err = -ENOIOCTLCMD;
375 break;
376 }
377
378 return err;
379}
380EXPORT_SYMBOL(bt_sock_ioctl);
381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
383{
384 DECLARE_WAITQUEUE(wait, current);
385 int err = 0;
386
387 BT_DBG("sk %p", sk);
388
389 add_wait_queue(sk->sk_sleep, &wait);
390 while (sk->sk_state != state) {
391 set_current_state(TASK_INTERRUPTIBLE);
392
393 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200394 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 break;
396 }
397
398 if (signal_pending(current)) {
399 err = sock_intr_errno(timeo);
400 break;
401 }
402
403 release_sock(sk);
404 timeo = schedule_timeout(timeo);
405 lock_sock(sk);
406
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800407 err = sock_error(sk);
408 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
411 set_current_state(TASK_RUNNING);
412 remove_wait_queue(sk->sk_sleep, &wait);
413 return err;
414}
415EXPORT_SYMBOL(bt_sock_wait_state);
416
417static struct net_proto_family bt_sock_family_ops = {
418 .owner = THIS_MODULE,
419 .family = PF_BLUETOOTH,
420 .create = bt_sock_create,
421};
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423static int __init bt_init(void)
424{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200425 int err;
426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 BT_INFO("Core ver %s", VERSION);
428
Marcel Holtmann27d35282006-07-03 10:02:37 +0200429 err = bt_sysfs_init();
430 if (err < 0)
431 return err;
432
433 err = sock_register(&bt_sock_family_ops);
434 if (err < 0) {
435 bt_sysfs_cleanup();
436 return err;
437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
439 BT_INFO("HCI device and connection manager initialized");
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 hci_sock_init();
442
443 return 0;
444}
445
446static void __exit bt_exit(void)
447{
448 hci_sock_cleanup();
449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200451
452 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453}
454
455subsys_initcall(bt_init);
456module_exit(bt_exit);
457
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200458MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
460MODULE_VERSION(VERSION);
461MODULE_LICENSE("GPL");
462MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);