blob: b3753bad2a554535a347599e97210e45395f6819 [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>
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020046#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <asm/unaligned.h>
48
49#include <net/bluetooth/bluetooth.h>
50#include <net/bluetooth/hci_core.h>
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052/* ----- HCI socket interface ----- */
53
54static inline int hci_test_bit(int nr, void *addr)
55{
56 return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
57}
58
59/* Security filter */
60static struct hci_sec_filter hci_sec_filter = {
61 /* Packet types */
62 0x10,
63 /* Events */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020064 { 0x1000d9fe, 0x0000b00c },
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 /* Commands */
66 {
67 { 0x0 },
68 /* OGF_LINK_CTL */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020069 { 0xbe000006, 0x00000001, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 /* OGF_LINK_POLICY */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020071 { 0x00005200, 0x00000000, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 /* OGF_HOST_CTL */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020073 { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 /* OGF_INFO_PARAM */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020075 { 0x000002be, 0x00000000, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 /* OGF_STATUS_PARAM */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020077 { 0x000000ea, 0x00000000, 0x00000000, 0x00 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 }
79};
80
81static struct bt_sock_list hci_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070082 .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070083};
84
85/* Send frame to RAW socket */
86void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
87{
88 struct sock *sk;
89 struct hlist_node *node;
90
91 BT_DBG("hdev %p len %d", hdev, skb->len);
92
93 read_lock(&hci_sk_list.lock);
94 sk_for_each(sk, node, &hci_sk_list.head) {
95 struct hci_filter *flt;
96 struct sk_buff *nskb;
97
98 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
99 continue;
100
101 /* Don't send frame to the socket it came from */
102 if (skb->sk == sk)
103 continue;
104
105 /* Apply filter */
106 flt = &hci_pi(sk)->filter;
107
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700108 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
109 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 continue;
111
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700112 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
114
115 if (!hci_test_bit(evt, &flt->event_mask))
116 continue;
117
David S. Miller4498c802006-11-21 16:17:41 -0800118 if (flt->opcode &&
119 ((evt == HCI_EV_CMD_COMPLETE &&
120 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800121 get_unaligned((__le16 *)(skb->data + 3))) ||
David S. Miller4498c802006-11-21 16:17:41 -0800122 (evt == HCI_EV_CMD_STATUS &&
123 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800124 get_unaligned((__le16 *)(skb->data + 4)))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 continue;
126 }
127
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200128 nskb = skb_clone(skb, GFP_ATOMIC);
129 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 continue;
131
132 /* Put type byte before the data */
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700133 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
135 if (sock_queue_rcv_skb(sk, nskb))
136 kfree_skb(nskb);
137 }
138 read_unlock(&hci_sk_list.lock);
139}
140
141static int hci_sock_release(struct socket *sock)
142{
143 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100144 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
146 BT_DBG("sock %p sk %p", sock, sk);
147
148 if (!sk)
149 return 0;
150
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100151 hdev = hci_pi(sk)->hdev;
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 bt_sock_unlink(&hci_sk_list, sk);
154
155 if (hdev) {
156 atomic_dec(&hdev->promisc);
157 hci_dev_put(hdev);
158 }
159
160 sock_orphan(sk);
161
162 skb_queue_purge(&sk->sk_receive_queue);
163 skb_queue_purge(&sk->sk_write_queue);
164
165 sock_put(sk);
166 return 0;
167}
168
Johan Hedbergf0358562010-05-18 13:20:32 +0200169struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
170{
171 struct list_head *p;
Johan Hedbergf0358562010-05-18 13:20:32 +0200172
David Millerea4bd8b2010-07-30 21:54:49 -0700173 list_for_each(p, &hdev->blacklist) {
Johan Hedbergf0358562010-05-18 13:20:32 +0200174 struct bdaddr_list *b;
175
176 b = list_entry(p, struct bdaddr_list, list);
177
178 if (bacmp(bdaddr, &b->bdaddr) == 0)
179 return b;
180 }
181
182 return NULL;
183}
184
185static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
186{
187 bdaddr_t bdaddr;
188 struct bdaddr_list *entry;
189
190 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
191 return -EFAULT;
192
193 if (bacmp(&bdaddr, BDADDR_ANY) == 0)
194 return -EBADF;
195
196 if (hci_blacklist_lookup(hdev, &bdaddr))
197 return -EEXIST;
198
199 entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
200 if (!entry)
201 return -ENOMEM;
202
203 bacpy(&entry->bdaddr, &bdaddr);
204
David Millerea4bd8b2010-07-30 21:54:49 -0700205 list_add(&entry->list, &hdev->blacklist);
Johan Hedbergf0358562010-05-18 13:20:32 +0200206
207 return 0;
208}
209
210int hci_blacklist_clear(struct hci_dev *hdev)
211{
212 struct list_head *p, *n;
Johan Hedbergf0358562010-05-18 13:20:32 +0200213
David Millerea4bd8b2010-07-30 21:54:49 -0700214 list_for_each_safe(p, n, &hdev->blacklist) {
Johan Hedbergf0358562010-05-18 13:20:32 +0200215 struct bdaddr_list *b;
216
217 b = list_entry(p, struct bdaddr_list, list);
218
219 list_del(p);
220 kfree(b);
221 }
222
223 return 0;
224}
225
226static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
227{
228 bdaddr_t bdaddr;
229 struct bdaddr_list *entry;
230
231 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
232 return -EFAULT;
233
234 if (bacmp(&bdaddr, BDADDR_ANY) == 0)
235 return hci_blacklist_clear(hdev);
236
237 entry = hci_blacklist_lookup(hdev, &bdaddr);
238 if (!entry)
239 return -ENOENT;
240
241 list_del(&entry->list);
242 kfree(entry);
243
244 return 0;
245}
246
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900247/* Ioctls that require bound socket */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
249{
250 struct hci_dev *hdev = hci_pi(sk)->hdev;
251
252 if (!hdev)
253 return -EBADFD;
254
255 switch (cmd) {
256 case HCISETRAW:
257 if (!capable(CAP_NET_ADMIN))
258 return -EACCES;
259
260 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
261 return -EPERM;
262
263 if (arg)
264 set_bit(HCI_RAW, &hdev->flags);
265 else
266 clear_bit(HCI_RAW, &hdev->flags);
267
268 return 0;
269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 case HCIGETCONNINFO:
Marcel Holtmann40be4922008-07-14 20:13:50 +0200271 return hci_get_conn_info(hdev, (void __user *) arg);
272
273 case HCIGETAUTHINFO:
274 return hci_get_auth_info(hdev, (void __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Johan Hedbergf0358562010-05-18 13:20:32 +0200276 case HCIBLOCKADDR:
277 if (!capable(CAP_NET_ADMIN))
278 return -EACCES;
279 return hci_blacklist_add(hdev, (void __user *) arg);
280
281 case HCIUNBLOCKADDR:
282 if (!capable(CAP_NET_ADMIN))
283 return -EACCES;
284 return hci_blacklist_del(hdev, (void __user *) arg);
285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 default:
287 if (hdev->ioctl)
288 return hdev->ioctl(hdev, cmd, arg);
289 return -EINVAL;
290 }
291}
292
293static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
294{
295 struct sock *sk = sock->sk;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200296 void __user *argp = (void __user *) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 int err;
298
299 BT_DBG("cmd %x arg %lx", cmd, arg);
300
301 switch (cmd) {
302 case HCIGETDEVLIST:
303 return hci_get_dev_list(argp);
304
305 case HCIGETDEVINFO:
306 return hci_get_dev_info(argp);
307
308 case HCIGETCONNLIST:
309 return hci_get_conn_list(argp);
310
311 case HCIDEVUP:
312 if (!capable(CAP_NET_ADMIN))
313 return -EACCES;
314 return hci_dev_open(arg);
315
316 case HCIDEVDOWN:
317 if (!capable(CAP_NET_ADMIN))
318 return -EACCES;
319 return hci_dev_close(arg);
320
321 case HCIDEVRESET:
322 if (!capable(CAP_NET_ADMIN))
323 return -EACCES;
324 return hci_dev_reset(arg);
325
326 case HCIDEVRESTAT:
327 if (!capable(CAP_NET_ADMIN))
328 return -EACCES;
329 return hci_dev_reset_stat(arg);
330
331 case HCISETSCAN:
332 case HCISETAUTH:
333 case HCISETENCRYPT:
334 case HCISETPTYPE:
335 case HCISETLINKPOL:
336 case HCISETLINKMODE:
337 case HCISETACLMTU:
338 case HCISETSCOMTU:
339 if (!capable(CAP_NET_ADMIN))
340 return -EACCES;
341 return hci_dev_cmd(cmd, argp);
342
343 case HCIINQUIRY:
344 return hci_inquiry(argp);
345
346 default:
347 lock_sock(sk);
348 err = hci_sock_bound_ioctl(sk, cmd, arg);
349 release_sock(sk);
350 return err;
351 }
352}
353
354static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
355{
356 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
357 struct sock *sk = sock->sk;
358 struct hci_dev *hdev = NULL;
359 int err = 0;
360
361 BT_DBG("sock %p sk %p", sock, sk);
362
363 if (!haddr || haddr->hci_family != AF_BLUETOOTH)
364 return -EINVAL;
365
366 lock_sock(sk);
367
368 if (hci_pi(sk)->hdev) {
369 err = -EALREADY;
370 goto done;
371 }
372
373 if (haddr->hci_dev != HCI_DEV_NONE) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200374 hdev = hci_dev_get(haddr->hci_dev);
375 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 err = -ENODEV;
377 goto done;
378 }
379
380 atomic_inc(&hdev->promisc);
381 }
382
383 hci_pi(sk)->hdev = hdev;
384 sk->sk_state = BT_BOUND;
385
386done:
387 release_sock(sk);
388 return err;
389}
390
391static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
392{
393 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
394 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100395 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 BT_DBG("sock %p sk %p", sock, sk);
398
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100399 if (!hdev)
400 return -EBADFD;
401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 lock_sock(sk);
403
404 *addr_len = sizeof(*haddr);
405 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100406 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
408 release_sock(sk);
409 return 0;
410}
411
412static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
413{
414 __u32 mask = hci_pi(sk)->cmsg_mask;
415
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700416 if (mask & HCI_CMSG_DIR) {
417 int incoming = bt_cb(skb)->incoming;
418 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700421 if (mask & HCI_CMSG_TSTAMP) {
Johann Felix Sodenf6e623a2010-02-15 22:23:48 +0100422#ifdef CONFIG_COMPAT
423 struct compat_timeval ctv;
424#endif
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700425 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200426 void *data;
427 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700428
429 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200430
David S. Miller1da97f82007-09-12 14:10:58 +0200431 data = &tv;
432 len = sizeof(tv);
433#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200434 if (msg->msg_flags & MSG_CMSG_COMPAT) {
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200435 ctv.tv_sec = tv.tv_sec;
436 ctv.tv_usec = tv.tv_usec;
437 data = &ctv;
438 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200439 }
David S. Miller1da97f82007-09-12 14:10:58 +0200440#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200441
442 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900445
446static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 struct msghdr *msg, size_t len, int flags)
448{
449 int noblock = flags & MSG_DONTWAIT;
450 struct sock *sk = sock->sk;
451 struct sk_buff *skb;
452 int copied, err;
453
454 BT_DBG("sock %p, sk %p", sock, sk);
455
456 if (flags & (MSG_OOB))
457 return -EOPNOTSUPP;
458
459 if (sk->sk_state == BT_CLOSED)
460 return 0;
461
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200462 skb = skb_recv_datagram(sk, flags, noblock, &err);
463 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 return err;
465
466 msg->msg_namelen = 0;
467
468 copied = skb->len;
469 if (len < copied) {
470 msg->msg_flags |= MSG_TRUNC;
471 copied = len;
472 }
473
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300474 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
476
477 hci_sock_cmsg(sk, msg, skb);
478
479 skb_free_datagram(sk, skb);
480
481 return err ? : copied;
482}
483
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900484static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 struct msghdr *msg, size_t len)
486{
487 struct sock *sk = sock->sk;
488 struct hci_dev *hdev;
489 struct sk_buff *skb;
490 int err;
491
492 BT_DBG("sock %p sk %p", sock, sk);
493
494 if (msg->msg_flags & MSG_OOB)
495 return -EOPNOTSUPP;
496
497 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
498 return -EINVAL;
499
500 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
501 return -EINVAL;
502
503 lock_sock(sk);
504
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200505 hdev = hci_pi(sk)->hdev;
506 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 err = -EBADFD;
508 goto done;
509 }
510
Marcel Holtmann7e21add2009-11-18 01:05:00 +0100511 if (!test_bit(HCI_UP, &hdev->flags)) {
512 err = -ENETDOWN;
513 goto done;
514 }
515
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200516 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
517 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 goto done;
519
520 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
521 err = -EFAULT;
522 goto drop;
523 }
524
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700525 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 skb_pull(skb, 1);
527 skb->dev = (void *) hdev;
528
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700529 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700530 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 u16 ogf = hci_opcode_ogf(opcode);
532 u16 ocf = hci_opcode_ocf(opcode);
533
534 if (((ogf > HCI_SFLT_MAX_OGF) ||
535 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
536 !capable(CAP_NET_RAW)) {
537 err = -EPERM;
538 goto drop;
539 }
540
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200541 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100543 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 } else {
545 skb_queue_tail(&hdev->cmd_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100546 tasklet_schedule(&hdev->cmd_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
548 } else {
549 if (!capable(CAP_NET_RAW)) {
550 err = -EPERM;
551 goto drop;
552 }
553
554 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100555 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 }
557
558 err = len;
559
560done:
561 release_sock(sk);
562 return err;
563
564drop:
565 kfree_skb(skb);
566 goto done;
567}
568
David S. Millerb7058842009-09-30 16:12:20 -0700569static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
571 struct hci_ufilter uf = { .opcode = 0 };
572 struct sock *sk = sock->sk;
573 int err = 0, opt = 0;
574
575 BT_DBG("sk %p, opt %d", sk, optname);
576
577 lock_sock(sk);
578
579 switch (optname) {
580 case HCI_DATA_DIR:
581 if (get_user(opt, (int __user *)optval)) {
582 err = -EFAULT;
583 break;
584 }
585
586 if (opt)
587 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
588 else
589 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
590 break;
591
592 case HCI_TIME_STAMP:
593 if (get_user(opt, (int __user *)optval)) {
594 err = -EFAULT;
595 break;
596 }
597
598 if (opt)
599 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
600 else
601 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
602 break;
603
604 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200605 {
606 struct hci_filter *f = &hci_pi(sk)->filter;
607
608 uf.type_mask = f->type_mask;
609 uf.opcode = f->opcode;
610 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
611 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
612 }
613
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 len = min_t(unsigned int, len, sizeof(uf));
615 if (copy_from_user(&uf, optval, len)) {
616 err = -EFAULT;
617 break;
618 }
619
620 if (!capable(CAP_NET_RAW)) {
621 uf.type_mask &= hci_sec_filter.type_mask;
622 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
623 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
624 }
625
626 {
627 struct hci_filter *f = &hci_pi(sk)->filter;
628
629 f->type_mask = uf.type_mask;
630 f->opcode = uf.opcode;
631 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
632 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
633 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900634 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636 default:
637 err = -ENOPROTOOPT;
638 break;
639 }
640
641 release_sock(sk);
642 return err;
643}
644
645static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
646{
647 struct hci_ufilter uf;
648 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900649 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
651 if (get_user(len, optlen))
652 return -EFAULT;
653
654 switch (optname) {
655 case HCI_DATA_DIR:
656 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
657 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900658 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 opt = 0;
660
661 if (put_user(opt, optval))
662 return -EFAULT;
663 break;
664
665 case HCI_TIME_STAMP:
666 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
667 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900668 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 opt = 0;
670
671 if (put_user(opt, optval))
672 return -EFAULT;
673 break;
674
675 case HCI_FILTER:
676 {
677 struct hci_filter *f = &hci_pi(sk)->filter;
678
679 uf.type_mask = f->type_mask;
680 uf.opcode = f->opcode;
681 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
682 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
683 }
684
685 len = min_t(unsigned int, len, sizeof(uf));
686 if (copy_to_user(optval, &uf, len))
687 return -EFAULT;
688 break;
689
690 default:
691 return -ENOPROTOOPT;
692 break;
693 }
694
695 return 0;
696}
697
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800698static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 .family = PF_BLUETOOTH,
700 .owner = THIS_MODULE,
701 .release = hci_sock_release,
702 .bind = hci_sock_bind,
703 .getname = hci_sock_getname,
704 .sendmsg = hci_sock_sendmsg,
705 .recvmsg = hci_sock_recvmsg,
706 .ioctl = hci_sock_ioctl,
707 .poll = datagram_poll,
708 .listen = sock_no_listen,
709 .shutdown = sock_no_shutdown,
710 .setsockopt = hci_sock_setsockopt,
711 .getsockopt = hci_sock_getsockopt,
712 .connect = sock_no_connect,
713 .socketpair = sock_no_socketpair,
714 .accept = sock_no_accept,
715 .mmap = sock_no_mmap
716};
717
718static struct proto hci_sk_proto = {
719 .name = "HCI",
720 .owner = THIS_MODULE,
721 .obj_size = sizeof(struct hci_pinfo)
722};
723
Eric Paris3f378b62009-11-05 22:18:14 -0800724static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
725 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
727 struct sock *sk;
728
729 BT_DBG("sock %p", sock);
730
731 if (sock->type != SOCK_RAW)
732 return -ESOCKTNOSUPPORT;
733
734 sock->ops = &hci_sock_ops;
735
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700736 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 if (!sk)
738 return -ENOMEM;
739
740 sock_init_data(sock, sk);
741
742 sock_reset_flag(sk, SOCK_ZAPPED);
743
744 sk->sk_protocol = protocol;
745
746 sock->state = SS_UNCONNECTED;
747 sk->sk_state = BT_OPEN;
748
749 bt_sock_link(&hci_sk_list, sk);
750 return 0;
751}
752
753static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
754{
755 struct hci_dev *hdev = (struct hci_dev *) ptr;
756 struct hci_ev_si_device ev;
757
758 BT_DBG("hdev %s event %ld", hdev->name, event);
759
760 /* Send event to sockets */
761 ev.event = event;
762 ev.dev_id = hdev->id;
763 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
764
765 if (event == HCI_DEV_UNREG) {
766 struct sock *sk;
767 struct hlist_node *node;
768
769 /* Detach sockets from device */
770 read_lock(&hci_sk_list.lock);
771 sk_for_each(sk, node, &hci_sk_list.head) {
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700772 local_bh_disable();
773 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 if (hci_pi(sk)->hdev == hdev) {
775 hci_pi(sk)->hdev = NULL;
776 sk->sk_err = EPIPE;
777 sk->sk_state = BT_OPEN;
778 sk->sk_state_change(sk);
779
780 hci_dev_put(hdev);
781 }
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700782 bh_unlock_sock(sk);
783 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 }
785 read_unlock(&hci_sk_list.lock);
786 }
787
788 return NOTIFY_DONE;
789}
790
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +0000791static const struct net_proto_family hci_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 .family = PF_BLUETOOTH,
793 .owner = THIS_MODULE,
794 .create = hci_sock_create,
795};
796
797static struct notifier_block hci_sock_nblock = {
798 .notifier_call = hci_sock_dev_event
799};
800
801int __init hci_sock_init(void)
802{
803 int err;
804
805 err = proto_register(&hci_sk_proto, 0);
806 if (err < 0)
807 return err;
808
809 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
810 if (err < 0)
811 goto error;
812
813 hci_register_notifier(&hci_sock_nblock);
814
815 BT_INFO("HCI socket layer initialized");
816
817 return 0;
818
819error:
820 BT_ERR("HCI socket registration failed");
821 proto_unregister(&hci_sk_proto);
822 return err;
823}
824
Tobias Klauser04005dd2008-03-05 18:47:03 -0800825void __exit hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 if (bt_sock_unregister(BTPROTO_HCI) < 0)
828 BT_ERR("HCI socket unregistration failed");
829
830 hci_unregister_notifier(&hci_sock_nblock);
831
832 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833}