blob: d366423c8392473e43c8cf2248e33a626bee3eaa [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>
39
40#if defined(CONFIG_KMOD)
41#include <linux/kmod.h>
42#endif
43
44#include <net/bluetooth/bluetooth.h>
45
46#ifndef CONFIG_BT_SOCK_DEBUG
47#undef BT_DBG
48#define BT_DBG(D...)
49#endif
50
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020051#define VERSION "2.11"
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
53/* Bluetooth sockets */
54#define BT_MAX_PROTO 8
55static struct net_proto_family *bt_proto[BT_MAX_PROTO];
Dave Young68845cb2008-04-01 23:58:35 -070056
57static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
58static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
59static const char *bt_key_strings[BT_MAX_PROTO] = {
60 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
61 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
62 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
63 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
64 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
65 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
66 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
67 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
68};
69
70static 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 Holtmann74da6262006-10-15 17:31:14 +020080static DEFINE_RWLOCK(bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
82int bt_sock_register(int proto, struct net_proto_family *ops)
83{
Marcel Holtmann74da6262006-10-15 17:31:14 +020084 int err = 0;
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 if (proto < 0 || proto >= BT_MAX_PROTO)
87 return -EINVAL;
88
Marcel Holtmann74da6262006-10-15 17:31:14 +020089 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
Marcel Holtmann74da6262006-10-15 17:31:14 +020091 if (bt_proto[proto])
92 err = -EEXIST;
93 else
94 bt_proto[proto] = ops;
95
96 write_unlock(&bt_proto_lock);
97
98 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099}
100EXPORT_SYMBOL(bt_sock_register);
101
102int bt_sock_unregister(int proto)
103{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200104 int err = 0;
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 if (proto < 0 || proto >= BT_MAX_PROTO)
107 return -EINVAL;
108
Marcel Holtmann74da6262006-10-15 17:31:14 +0200109 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Marcel Holtmann74da6262006-10-15 17:31:14 +0200111 if (!bt_proto[proto])
112 err = -ENOENT;
113 else
114 bt_proto[proto] = NULL;
115
116 write_unlock(&bt_proto_lock);
117
118 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
120EXPORT_SYMBOL(bt_sock_unregister);
121
Dave Young68845cb2008-04-01 23:58:35 -0700122static void bt_reclassify_sock_lock(struct socket *sock, int proto)
123{
124 struct sock *sk = sock->sk;
125
126 if (!sk)
127 return;
128 BUG_ON(sock_owned_by_user(sk));
129
130 sock_lock_init_class_and_name(sk,
131 bt_slock_key_strings[proto],
132 &bt_slock_key[proto],
133 bt_key_strings[proto],
134 &bt_lock_key[proto]);
135}
136
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700137static int bt_sock_create(struct net *net, struct socket *sock, int proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200139 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700141 if (net != &init_net)
142 return -EAFNOSUPPORT;
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 if (proto < 0 || proto >= BT_MAX_PROTO)
145 return -EINVAL;
146
147#if defined(CONFIG_KMOD)
148 if (!bt_proto[proto]) {
149 request_module("bt-proto-%d", proto);
150 }
151#endif
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);
Dave Young68845cb2008-04-01 23:58:35 -0700159 bt_reclassify_sock_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);
269
270 skb_free_datagram(sk, skb);
271
272 return err ? : copied;
273}
274EXPORT_SYMBOL(bt_sock_recvmsg);
275
276static inline unsigned int bt_accept_poll(struct sock *parent)
277{
278 struct list_head *p, *n;
279 struct sock *sk;
280
281 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
282 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
283 if (sk->sk_state == BT_CONNECTED)
284 return POLLIN | POLLRDNORM;
285 }
286
287 return 0;
288}
289
290unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
291{
292 struct sock *sk = sock->sk;
293 unsigned int mask = 0;
294
295 BT_DBG("sock %p, sk %p", sock, sk);
296
297 poll_wait(file, sk->sk_sleep, wait);
298
299 if (sk->sk_state == BT_LISTEN)
300 return bt_accept_poll(sk);
301
302 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
303 mask |= POLLERR;
304
Davide Libenzif348d702006-03-25 03:07:39 -0800305 if (sk->sk_shutdown & RCV_SHUTDOWN)
306 mask |= POLLRDHUP;
307
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 if (sk->sk_shutdown == SHUTDOWN_MASK)
309 mask |= POLLHUP;
310
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900311 if (!skb_queue_empty(&sk->sk_receive_queue) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 (sk->sk_shutdown & RCV_SHUTDOWN))
313 mask |= POLLIN | POLLRDNORM;
314
315 if (sk->sk_state == BT_CLOSED)
316 mask |= POLLHUP;
317
318 if (sk->sk_state == BT_CONNECT ||
319 sk->sk_state == BT_CONNECT2 ||
320 sk->sk_state == BT_CONFIG)
321 return mask;
322
323 if (sock_writeable(sk))
324 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
325 else
326 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
327
328 return mask;
329}
330EXPORT_SYMBOL(bt_sock_poll);
331
332int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
333{
334 DECLARE_WAITQUEUE(wait, current);
335 int err = 0;
336
337 BT_DBG("sk %p", sk);
338
339 add_wait_queue(sk->sk_sleep, &wait);
340 while (sk->sk_state != state) {
341 set_current_state(TASK_INTERRUPTIBLE);
342
343 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200344 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 break;
346 }
347
348 if (signal_pending(current)) {
349 err = sock_intr_errno(timeo);
350 break;
351 }
352
353 release_sock(sk);
354 timeo = schedule_timeout(timeo);
355 lock_sock(sk);
356
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800357 err = sock_error(sk);
358 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 }
361 set_current_state(TASK_RUNNING);
362 remove_wait_queue(sk->sk_sleep, &wait);
363 return err;
364}
365EXPORT_SYMBOL(bt_sock_wait_state);
366
367static struct net_proto_family bt_sock_family_ops = {
368 .owner = THIS_MODULE,
369 .family = PF_BLUETOOTH,
370 .create = bt_sock_create,
371};
372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373static int __init bt_init(void)
374{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200375 int err;
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 BT_INFO("Core ver %s", VERSION);
378
Marcel Holtmann27d35282006-07-03 10:02:37 +0200379 err = bt_sysfs_init();
380 if (err < 0)
381 return err;
382
383 err = sock_register(&bt_sock_family_ops);
384 if (err < 0) {
385 bt_sysfs_cleanup();
386 return err;
387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
389 BT_INFO("HCI device and connection manager initialized");
390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 hci_sock_init();
392
393 return 0;
394}
395
396static void __exit bt_exit(void)
397{
398 hci_sock_cleanup();
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200401
402 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403}
404
405subsys_initcall(bt_init);
406module_exit(bt_exit);
407
408MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
409MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
410MODULE_VERSION(VERSION);
411MODULE_LICENSE("GPL");
412MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);