blob: 8f9431a12c6f36ed5f8d3ad2b28f765120824d7b [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 Holtmanne7c29cb2008-09-09 07:19:20 +020049#define VERSION "2.13"
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];
Dave Young68845cb2008-04-01 23:58:35 -070054
55static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
56static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
57static const char *bt_key_strings[BT_MAX_PROTO] = {
58 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
59 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
60 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
61 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
62 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
63 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
64 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
65 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
66};
67
68static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
69 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
70 "slock-AF_BLUETOOTH-BTPROTO_HCI",
71 "slock-AF_BLUETOOTH-BTPROTO_SCO",
72 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
73 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
74 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
75 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
76 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
77};
Marcel Holtmann74da6262006-10-15 17:31:14 +020078static DEFINE_RWLOCK(bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80int bt_sock_register(int proto, struct net_proto_family *ops)
81{
Marcel Holtmann74da6262006-10-15 17:31:14 +020082 int err = 0;
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 if (proto < 0 || proto >= BT_MAX_PROTO)
85 return -EINVAL;
86
Marcel Holtmann74da6262006-10-15 17:31:14 +020087 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
Marcel Holtmann74da6262006-10-15 17:31:14 +020089 if (bt_proto[proto])
90 err = -EEXIST;
91 else
92 bt_proto[proto] = ops;
93
94 write_unlock(&bt_proto_lock);
95
96 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097}
98EXPORT_SYMBOL(bt_sock_register);
99
100int bt_sock_unregister(int proto)
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 = -ENOENT;
111 else
112 bt_proto[proto] = NULL;
113
114 write_unlock(&bt_proto_lock);
115
116 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117}
118EXPORT_SYMBOL(bt_sock_unregister);
119
Dave Young68845cb2008-04-01 23:58:35 -0700120static void bt_reclassify_sock_lock(struct socket *sock, int proto)
121{
122 struct sock *sk = sock->sk;
123
124 if (!sk)
125 return;
126 BUG_ON(sock_owned_by_user(sk));
127
128 sock_lock_init_class_and_name(sk,
129 bt_slock_key_strings[proto],
130 &bt_slock_key[proto],
131 bt_key_strings[proto],
132 &bt_lock_key[proto]);
133}
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);
Dave Young68845cb2008-04-01 23:58:35 -0700154 bt_reclassify_sock_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
220 if (sk->sk_state == BT_CONNECTED || !newsock) {
221 bt_accept_unlink(sk);
222 if (newsock)
223 sock_graft(sk, newsock);
224 release_sock(sk);
225 return sk;
226 }
227
228 release_sock(sk);
229 }
230 return NULL;
231}
232EXPORT_SYMBOL(bt_accept_dequeue);
233
234int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
235 struct msghdr *msg, size_t len, int flags)
236{
237 int noblock = flags & MSG_DONTWAIT;
238 struct sock *sk = sock->sk;
239 struct sk_buff *skb;
240 size_t copied;
241 int err;
242
243 BT_DBG("sock %p sk %p len %d", sock, sk, len);
244
245 if (flags & (MSG_OOB))
246 return -EOPNOTSUPP;
247
248 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) {
249 if (sk->sk_shutdown & RCV_SHUTDOWN)
250 return 0;
251 return err;
252 }
253
254 msg->msg_namelen = 0;
255
256 copied = skb->len;
257 if (len < copied) {
258 msg->msg_flags |= MSG_TRUNC;
259 copied = len;
260 }
261
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300262 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200264 if (err == 0)
265 sock_recv_timestamp(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267 skb_free_datagram(sk, skb);
268
269 return err ? : copied;
270}
271EXPORT_SYMBOL(bt_sock_recvmsg);
272
273static inline unsigned int bt_accept_poll(struct sock *parent)
274{
275 struct list_head *p, *n;
276 struct sock *sk;
277
278 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
279 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
280 if (sk->sk_state == BT_CONNECTED)
281 return POLLIN | POLLRDNORM;
282 }
283
284 return 0;
285}
286
287unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
288{
289 struct sock *sk = sock->sk;
290 unsigned int mask = 0;
291
292 BT_DBG("sock %p, sk %p", sock, sk);
293
294 poll_wait(file, sk->sk_sleep, wait);
295
296 if (sk->sk_state == BT_LISTEN)
297 return bt_accept_poll(sk);
298
299 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
300 mask |= POLLERR;
301
Davide Libenzif348d702006-03-25 03:07:39 -0800302 if (sk->sk_shutdown & RCV_SHUTDOWN)
303 mask |= POLLRDHUP;
304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 if (sk->sk_shutdown == SHUTDOWN_MASK)
306 mask |= POLLHUP;
307
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900308 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 (sk->sk_shutdown & RCV_SHUTDOWN))
310 mask |= POLLIN | POLLRDNORM;
311
312 if (sk->sk_state == BT_CLOSED)
313 mask |= POLLHUP;
314
315 if (sk->sk_state == BT_CONNECT ||
316 sk->sk_state == BT_CONNECT2 ||
317 sk->sk_state == BT_CONFIG)
318 return mask;
319
320 if (sock_writeable(sk))
321 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
322 else
323 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
324
325 return mask;
326}
327EXPORT_SYMBOL(bt_sock_poll);
328
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200329int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
330{
331 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200332 struct sk_buff *skb;
333 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200334 int err;
335
336 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
337
338 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200339 case TIOCOUTQ:
340 if (sk->sk_state == BT_LISTEN)
341 return -EINVAL;
342
343 amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
344 if (amount < 0)
345 amount = 0;
346 err = put_user(amount, (int __user *) arg);
347 break;
348
349 case TIOCINQ:
350 if (sk->sk_state == BT_LISTEN)
351 return -EINVAL;
352
353 lock_sock(sk);
354 skb = skb_peek(&sk->sk_receive_queue);
355 amount = skb ? skb->len : 0;
356 release_sock(sk);
357 err = put_user(amount, (int __user *) arg);
358 break;
359
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200360 case SIOCGSTAMP:
361 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
362 break;
363
364 case SIOCGSTAMPNS:
365 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
366 break;
367
368 default:
369 err = -ENOIOCTLCMD;
370 break;
371 }
372
373 return err;
374}
375EXPORT_SYMBOL(bt_sock_ioctl);
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
378{
379 DECLARE_WAITQUEUE(wait, current);
380 int err = 0;
381
382 BT_DBG("sk %p", sk);
383
384 add_wait_queue(sk->sk_sleep, &wait);
385 while (sk->sk_state != state) {
386 set_current_state(TASK_INTERRUPTIBLE);
387
388 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200389 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 break;
391 }
392
393 if (signal_pending(current)) {
394 err = sock_intr_errno(timeo);
395 break;
396 }
397
398 release_sock(sk);
399 timeo = schedule_timeout(timeo);
400 lock_sock(sk);
401
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800402 err = sock_error(sk);
403 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 }
406 set_current_state(TASK_RUNNING);
407 remove_wait_queue(sk->sk_sleep, &wait);
408 return err;
409}
410EXPORT_SYMBOL(bt_sock_wait_state);
411
412static struct net_proto_family bt_sock_family_ops = {
413 .owner = THIS_MODULE,
414 .family = PF_BLUETOOTH,
415 .create = bt_sock_create,
416};
417
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418static int __init bt_init(void)
419{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200420 int err;
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 BT_INFO("Core ver %s", VERSION);
423
Marcel Holtmann27d35282006-07-03 10:02:37 +0200424 err = bt_sysfs_init();
425 if (err < 0)
426 return err;
427
428 err = sock_register(&bt_sock_family_ops);
429 if (err < 0) {
430 bt_sysfs_cleanup();
431 return err;
432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
434 BT_INFO("HCI device and connection manager initialized");
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 hci_sock_init();
437
438 return 0;
439}
440
441static void __exit bt_exit(void)
442{
443 hci_sock_cleanup();
444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200446
447 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448}
449
450subsys_initcall(bt_init);
451module_exit(bt_exit);
452
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200453MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
455MODULE_VERSION(VERSION);
456MODULE_LICENSE("GPL");
457MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);