blob: d62579b67959cd935f1f20c8c128dcabd9436f37 [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 HCI sockets. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080030#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
32#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/slab.h>
34#include <linux/poll.h>
35#include <linux/fcntl.h>
36#include <linux/init.h>
37#include <linux/skbuff.h>
38#include <linux/workqueue.h>
39#include <linux/interrupt.h>
Marcel Holtmann767c5eb2007-09-09 08:39:34 +020040#include <linux/compat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/socket.h>
42#include <linux/ioctl.h>
43#include <net/sock.h>
44
45#include <asm/system.h>
46#include <asm/uaccess.h>
47#include <asm/unaligned.h>
48
49#include <net/bluetooth/bluetooth.h>
50#include <net/bluetooth/hci_core.h>
51
52#ifndef CONFIG_BT_HCI_SOCK_DEBUG
53#undef BT_DBG
54#define BT_DBG(D...)
55#endif
56
57/* ----- HCI socket interface ----- */
58
59static inline int hci_test_bit(int nr, void *addr)
60{
61 return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
62}
63
64/* Security filter */
65static struct hci_sec_filter hci_sec_filter = {
66 /* Packet types */
67 0x10,
68 /* Events */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020069 { 0x1000d9fe, 0x0000b00c },
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 /* Commands */
71 {
72 { 0x0 },
73 /* OGF_LINK_CTL */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020074 { 0xbe000006, 0x00000001, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 /* OGF_LINK_POLICY */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020076 { 0x00005200, 0x00000000, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 /* OGF_HOST_CTL */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020078 { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 /* OGF_INFO_PARAM */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020080 { 0x000002be, 0x00000000, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 /* OGF_STATUS_PARAM */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020082 { 0x000000ea, 0x00000000, 0x00000000, 0x00 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 }
84};
85
86static struct bt_sock_list hci_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070087 .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088};
89
90/* Send frame to RAW socket */
91void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
92{
93 struct sock *sk;
94 struct hlist_node *node;
95
96 BT_DBG("hdev %p len %d", hdev, skb->len);
97
98 read_lock(&hci_sk_list.lock);
99 sk_for_each(sk, node, &hci_sk_list.head) {
100 struct hci_filter *flt;
101 struct sk_buff *nskb;
102
103 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
104 continue;
105
106 /* Don't send frame to the socket it came from */
107 if (skb->sk == sk)
108 continue;
109
110 /* Apply filter */
111 flt = &hci_pi(sk)->filter;
112
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700113 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
114 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 continue;
116
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700117 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
119
120 if (!hci_test_bit(evt, &flt->event_mask))
121 continue;
122
David S. Miller4498c802006-11-21 16:17:41 -0800123 if (flt->opcode &&
124 ((evt == HCI_EV_CMD_COMPLETE &&
125 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800126 get_unaligned((__le16 *)(skb->data + 3))) ||
David S. Miller4498c802006-11-21 16:17:41 -0800127 (evt == HCI_EV_CMD_STATUS &&
128 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800129 get_unaligned((__le16 *)(skb->data + 4)))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 continue;
131 }
132
133 if (!(nskb = skb_clone(skb, GFP_ATOMIC)))
134 continue;
135
136 /* Put type byte before the data */
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700137 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139 if (sock_queue_rcv_skb(sk, nskb))
140 kfree_skb(nskb);
141 }
142 read_unlock(&hci_sk_list.lock);
143}
144
145static int hci_sock_release(struct socket *sock)
146{
147 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100148 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 BT_DBG("sock %p sk %p", sock, sk);
151
152 if (!sk)
153 return 0;
154
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100155 hdev = hci_pi(sk)->hdev;
156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 bt_sock_unlink(&hci_sk_list, sk);
158
159 if (hdev) {
160 atomic_dec(&hdev->promisc);
161 hci_dev_put(hdev);
162 }
163
164 sock_orphan(sk);
165
166 skb_queue_purge(&sk->sk_receive_queue);
167 skb_queue_purge(&sk->sk_write_queue);
168
169 sock_put(sk);
170 return 0;
171}
172
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900173/* Ioctls that require bound socket */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
175{
176 struct hci_dev *hdev = hci_pi(sk)->hdev;
177
178 if (!hdev)
179 return -EBADFD;
180
181 switch (cmd) {
182 case HCISETRAW:
183 if (!capable(CAP_NET_ADMIN))
184 return -EACCES;
185
186 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
187 return -EPERM;
188
189 if (arg)
190 set_bit(HCI_RAW, &hdev->flags);
191 else
192 clear_bit(HCI_RAW, &hdev->flags);
193
194 return 0;
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 case HCIGETCONNINFO:
Marcel Holtmann40be4922008-07-14 20:13:50 +0200197 return hci_get_conn_info(hdev, (void __user *) arg);
198
199 case HCIGETAUTHINFO:
200 return hci_get_auth_info(hdev, (void __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 default:
203 if (hdev->ioctl)
204 return hdev->ioctl(hdev, cmd, arg);
205 return -EINVAL;
206 }
207}
208
209static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
210{
211 struct sock *sk = sock->sk;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200212 void __user *argp = (void __user *) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 int err;
214
215 BT_DBG("cmd %x arg %lx", cmd, arg);
216
217 switch (cmd) {
218 case HCIGETDEVLIST:
219 return hci_get_dev_list(argp);
220
221 case HCIGETDEVINFO:
222 return hci_get_dev_info(argp);
223
224 case HCIGETCONNLIST:
225 return hci_get_conn_list(argp);
226
227 case HCIDEVUP:
228 if (!capable(CAP_NET_ADMIN))
229 return -EACCES;
230 return hci_dev_open(arg);
231
232 case HCIDEVDOWN:
233 if (!capable(CAP_NET_ADMIN))
234 return -EACCES;
235 return hci_dev_close(arg);
236
237 case HCIDEVRESET:
238 if (!capable(CAP_NET_ADMIN))
239 return -EACCES;
240 return hci_dev_reset(arg);
241
242 case HCIDEVRESTAT:
243 if (!capable(CAP_NET_ADMIN))
244 return -EACCES;
245 return hci_dev_reset_stat(arg);
246
247 case HCISETSCAN:
248 case HCISETAUTH:
249 case HCISETENCRYPT:
250 case HCISETPTYPE:
251 case HCISETLINKPOL:
252 case HCISETLINKMODE:
253 case HCISETACLMTU:
254 case HCISETSCOMTU:
255 if (!capable(CAP_NET_ADMIN))
256 return -EACCES;
257 return hci_dev_cmd(cmd, argp);
258
259 case HCIINQUIRY:
260 return hci_inquiry(argp);
261
262 default:
263 lock_sock(sk);
264 err = hci_sock_bound_ioctl(sk, cmd, arg);
265 release_sock(sk);
266 return err;
267 }
268}
269
270static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
271{
272 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
273 struct sock *sk = sock->sk;
274 struct hci_dev *hdev = NULL;
275 int err = 0;
276
277 BT_DBG("sock %p sk %p", sock, sk);
278
279 if (!haddr || haddr->hci_family != AF_BLUETOOTH)
280 return -EINVAL;
281
282 lock_sock(sk);
283
284 if (hci_pi(sk)->hdev) {
285 err = -EALREADY;
286 goto done;
287 }
288
289 if (haddr->hci_dev != HCI_DEV_NONE) {
290 if (!(hdev = hci_dev_get(haddr->hci_dev))) {
291 err = -ENODEV;
292 goto done;
293 }
294
295 atomic_inc(&hdev->promisc);
296 }
297
298 hci_pi(sk)->hdev = hdev;
299 sk->sk_state = BT_BOUND;
300
301done:
302 release_sock(sk);
303 return err;
304}
305
306static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
307{
308 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
309 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100310 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
312 BT_DBG("sock %p sk %p", sock, sk);
313
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100314 if (!hdev)
315 return -EBADFD;
316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 lock_sock(sk);
318
319 *addr_len = sizeof(*haddr);
320 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100321 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 release_sock(sk);
324 return 0;
325}
326
327static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
328{
329 __u32 mask = hci_pi(sk)->cmsg_mask;
330
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700331 if (mask & HCI_CMSG_DIR) {
332 int incoming = bt_cb(skb)->incoming;
333 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700336 if (mask & HCI_CMSG_TSTAMP) {
337 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200338 void *data;
339 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700340
341 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200342
David S. Miller1da97f82007-09-12 14:10:58 +0200343 data = &tv;
344 len = sizeof(tv);
345#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200346 if (msg->msg_flags & MSG_CMSG_COMPAT) {
347 struct compat_timeval ctv;
348 ctv.tv_sec = tv.tv_sec;
349 ctv.tv_usec = tv.tv_usec;
350 data = &ctv;
351 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200352 }
David S. Miller1da97f82007-09-12 14:10:58 +0200353#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200354
355 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900358
359static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 struct msghdr *msg, size_t len, int flags)
361{
362 int noblock = flags & MSG_DONTWAIT;
363 struct sock *sk = sock->sk;
364 struct sk_buff *skb;
365 int copied, err;
366
367 BT_DBG("sock %p, sk %p", sock, sk);
368
369 if (flags & (MSG_OOB))
370 return -EOPNOTSUPP;
371
372 if (sk->sk_state == BT_CLOSED)
373 return 0;
374
375 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err)))
376 return err;
377
378 msg->msg_namelen = 0;
379
380 copied = skb->len;
381 if (len < copied) {
382 msg->msg_flags |= MSG_TRUNC;
383 copied = len;
384 }
385
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300386 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
388
389 hci_sock_cmsg(sk, msg, skb);
390
391 skb_free_datagram(sk, skb);
392
393 return err ? : copied;
394}
395
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900396static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 struct msghdr *msg, size_t len)
398{
399 struct sock *sk = sock->sk;
400 struct hci_dev *hdev;
401 struct sk_buff *skb;
402 int err;
403
404 BT_DBG("sock %p sk %p", sock, sk);
405
406 if (msg->msg_flags & MSG_OOB)
407 return -EOPNOTSUPP;
408
409 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
410 return -EINVAL;
411
412 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
413 return -EINVAL;
414
415 lock_sock(sk);
416
417 if (!(hdev = hci_pi(sk)->hdev)) {
418 err = -EBADFD;
419 goto done;
420 }
421
422 if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
423 goto done;
424
425 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
426 err = -EFAULT;
427 goto drop;
428 }
429
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700430 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 skb_pull(skb, 1);
432 skb->dev = (void *) hdev;
433
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700434 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700435 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 u16 ogf = hci_opcode_ogf(opcode);
437 u16 ocf = hci_opcode_ocf(opcode);
438
439 if (((ogf > HCI_SFLT_MAX_OGF) ||
440 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
441 !capable(CAP_NET_RAW)) {
442 err = -EPERM;
443 goto drop;
444 }
445
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200446 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 skb_queue_tail(&hdev->raw_q, skb);
448 hci_sched_tx(hdev);
449 } else {
450 skb_queue_tail(&hdev->cmd_q, skb);
451 hci_sched_cmd(hdev);
452 }
453 } else {
454 if (!capable(CAP_NET_RAW)) {
455 err = -EPERM;
456 goto drop;
457 }
458
459 skb_queue_tail(&hdev->raw_q, skb);
460 hci_sched_tx(hdev);
461 }
462
463 err = len;
464
465done:
466 release_sock(sk);
467 return err;
468
469drop:
470 kfree_skb(skb);
471 goto done;
472}
473
474static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
475{
476 struct hci_ufilter uf = { .opcode = 0 };
477 struct sock *sk = sock->sk;
478 int err = 0, opt = 0;
479
480 BT_DBG("sk %p, opt %d", sk, optname);
481
482 lock_sock(sk);
483
484 switch (optname) {
485 case HCI_DATA_DIR:
486 if (get_user(opt, (int __user *)optval)) {
487 err = -EFAULT;
488 break;
489 }
490
491 if (opt)
492 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
493 else
494 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
495 break;
496
497 case HCI_TIME_STAMP:
498 if (get_user(opt, (int __user *)optval)) {
499 err = -EFAULT;
500 break;
501 }
502
503 if (opt)
504 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
505 else
506 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
507 break;
508
509 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200510 {
511 struct hci_filter *f = &hci_pi(sk)->filter;
512
513 uf.type_mask = f->type_mask;
514 uf.opcode = f->opcode;
515 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
516 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
517 }
518
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 len = min_t(unsigned int, len, sizeof(uf));
520 if (copy_from_user(&uf, optval, len)) {
521 err = -EFAULT;
522 break;
523 }
524
525 if (!capable(CAP_NET_RAW)) {
526 uf.type_mask &= hci_sec_filter.type_mask;
527 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
528 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
529 }
530
531 {
532 struct hci_filter *f = &hci_pi(sk)->filter;
533
534 f->type_mask = uf.type_mask;
535 f->opcode = uf.opcode;
536 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
537 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
538 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900539 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
541 default:
542 err = -ENOPROTOOPT;
543 break;
544 }
545
546 release_sock(sk);
547 return err;
548}
549
550static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
551{
552 struct hci_ufilter uf;
553 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900554 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
556 if (get_user(len, optlen))
557 return -EFAULT;
558
559 switch (optname) {
560 case HCI_DATA_DIR:
561 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
562 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900563 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 opt = 0;
565
566 if (put_user(opt, optval))
567 return -EFAULT;
568 break;
569
570 case HCI_TIME_STAMP:
571 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
572 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900573 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 opt = 0;
575
576 if (put_user(opt, optval))
577 return -EFAULT;
578 break;
579
580 case HCI_FILTER:
581 {
582 struct hci_filter *f = &hci_pi(sk)->filter;
583
584 uf.type_mask = f->type_mask;
585 uf.opcode = f->opcode;
586 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
587 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
588 }
589
590 len = min_t(unsigned int, len, sizeof(uf));
591 if (copy_to_user(optval, &uf, len))
592 return -EFAULT;
593 break;
594
595 default:
596 return -ENOPROTOOPT;
597 break;
598 }
599
600 return 0;
601}
602
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800603static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 .family = PF_BLUETOOTH,
605 .owner = THIS_MODULE,
606 .release = hci_sock_release,
607 .bind = hci_sock_bind,
608 .getname = hci_sock_getname,
609 .sendmsg = hci_sock_sendmsg,
610 .recvmsg = hci_sock_recvmsg,
611 .ioctl = hci_sock_ioctl,
612 .poll = datagram_poll,
613 .listen = sock_no_listen,
614 .shutdown = sock_no_shutdown,
615 .setsockopt = hci_sock_setsockopt,
616 .getsockopt = hci_sock_getsockopt,
617 .connect = sock_no_connect,
618 .socketpair = sock_no_socketpair,
619 .accept = sock_no_accept,
620 .mmap = sock_no_mmap
621};
622
623static struct proto hci_sk_proto = {
624 .name = "HCI",
625 .owner = THIS_MODULE,
626 .obj_size = sizeof(struct hci_pinfo)
627};
628
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700629static int hci_sock_create(struct net *net, struct socket *sock, int protocol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 struct sock *sk;
632
633 BT_DBG("sock %p", sock);
634
635 if (sock->type != SOCK_RAW)
636 return -ESOCKTNOSUPPORT;
637
638 sock->ops = &hci_sock_ops;
639
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700640 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 if (!sk)
642 return -ENOMEM;
643
644 sock_init_data(sock, sk);
645
646 sock_reset_flag(sk, SOCK_ZAPPED);
647
648 sk->sk_protocol = protocol;
649
650 sock->state = SS_UNCONNECTED;
651 sk->sk_state = BT_OPEN;
652
653 bt_sock_link(&hci_sk_list, sk);
654 return 0;
655}
656
657static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
658{
659 struct hci_dev *hdev = (struct hci_dev *) ptr;
660 struct hci_ev_si_device ev;
661
662 BT_DBG("hdev %s event %ld", hdev->name, event);
663
664 /* Send event to sockets */
665 ev.event = event;
666 ev.dev_id = hdev->id;
667 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
668
669 if (event == HCI_DEV_UNREG) {
670 struct sock *sk;
671 struct hlist_node *node;
672
673 /* Detach sockets from device */
674 read_lock(&hci_sk_list.lock);
675 sk_for_each(sk, node, &hci_sk_list.head) {
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700676 local_bh_disable();
677 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 if (hci_pi(sk)->hdev == hdev) {
679 hci_pi(sk)->hdev = NULL;
680 sk->sk_err = EPIPE;
681 sk->sk_state = BT_OPEN;
682 sk->sk_state_change(sk);
683
684 hci_dev_put(hdev);
685 }
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700686 bh_unlock_sock(sk);
687 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 }
689 read_unlock(&hci_sk_list.lock);
690 }
691
692 return NOTIFY_DONE;
693}
694
695static struct net_proto_family hci_sock_family_ops = {
696 .family = PF_BLUETOOTH,
697 .owner = THIS_MODULE,
698 .create = hci_sock_create,
699};
700
701static struct notifier_block hci_sock_nblock = {
702 .notifier_call = hci_sock_dev_event
703};
704
705int __init hci_sock_init(void)
706{
707 int err;
708
709 err = proto_register(&hci_sk_proto, 0);
710 if (err < 0)
711 return err;
712
713 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
714 if (err < 0)
715 goto error;
716
717 hci_register_notifier(&hci_sock_nblock);
718
719 BT_INFO("HCI socket layer initialized");
720
721 return 0;
722
723error:
724 BT_ERR("HCI socket registration failed");
725 proto_unregister(&hci_sk_proto);
726 return err;
727}
728
Tobias Klauser04005dd2008-03-05 18:47:03 -0800729void __exit hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
731 if (bt_sock_unregister(BTPROTO_HCI) < 0)
732 BT_ERR("HCI socket unregistration failed");
733
734 hci_unregister_notifier(&hci_sock_nblock);
735
736 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737}