blob: 207be7abda9fb283bb18711169be5b73c81c5e2e [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
Johan Hedberg03811012010-12-08 00:21:06 +020052static int enable_mgmt;
53
Linus Torvalds1da177e2005-04-16 15:20:36 -070054/* ----- HCI socket interface ----- */
55
56static inline int hci_test_bit(int nr, void *addr)
57{
58 return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
59}
60
61/* Security filter */
62static struct hci_sec_filter hci_sec_filter = {
63 /* Packet types */
64 0x10,
65 /* Events */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020066 { 0x1000d9fe, 0x0000b00c },
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 /* Commands */
68 {
69 { 0x0 },
70 /* OGF_LINK_CTL */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020071 { 0xbe000006, 0x00000001, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 /* OGF_LINK_POLICY */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020073 { 0x00005200, 0x00000000, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 /* OGF_HOST_CTL */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020075 { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 /* OGF_INFO_PARAM */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020077 { 0x000002be, 0x00000000, 0x00000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 /* OGF_STATUS_PARAM */
Marcel Holtmann7c631a62007-09-09 08:39:43 +020079 { 0x000000ea, 0x00000000, 0x00000000, 0x00 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 }
81};
82
83static struct bt_sock_list hci_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070084 .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085};
86
87/* Send frame to RAW socket */
88void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
89{
90 struct sock *sk;
91 struct hlist_node *node;
92
93 BT_DBG("hdev %p len %d", hdev, skb->len);
94
95 read_lock(&hci_sk_list.lock);
96 sk_for_each(sk, node, &hci_sk_list.head) {
97 struct hci_filter *flt;
98 struct sk_buff *nskb;
99
100 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
101 continue;
102
103 /* Don't send frame to the socket it came from */
104 if (skb->sk == sk)
105 continue;
106
107 /* Apply filter */
108 flt = &hci_pi(sk)->filter;
109
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700110 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
111 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 continue;
113
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700114 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
116
117 if (!hci_test_bit(evt, &flt->event_mask))
118 continue;
119
David S. Miller4498c802006-11-21 16:17:41 -0800120 if (flt->opcode &&
121 ((evt == HCI_EV_CMD_COMPLETE &&
122 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800123 get_unaligned((__le16 *)(skb->data + 3))) ||
David S. Miller4498c802006-11-21 16:17:41 -0800124 (evt == HCI_EV_CMD_STATUS &&
125 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800126 get_unaligned((__le16 *)(skb->data + 4)))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 continue;
128 }
129
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200130 nskb = skb_clone(skb, GFP_ATOMIC);
131 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 continue;
133
134 /* Put type byte before the data */
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700135 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137 if (sock_queue_rcv_skb(sk, nskb))
138 kfree_skb(nskb);
139 }
140 read_unlock(&hci_sk_list.lock);
141}
142
143static int hci_sock_release(struct socket *sock)
144{
145 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100146 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
148 BT_DBG("sock %p sk %p", sock, sk);
149
150 if (!sk)
151 return 0;
152
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100153 hdev = hci_pi(sk)->hdev;
154
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 bt_sock_unlink(&hci_sk_list, sk);
156
157 if (hdev) {
158 atomic_dec(&hdev->promisc);
159 hci_dev_put(hdev);
160 }
161
162 sock_orphan(sk);
163
164 skb_queue_purge(&sk->sk_receive_queue);
165 skb_queue_purge(&sk->sk_write_queue);
166
167 sock_put(sk);
168 return 0;
169}
170
Johan Hedbergf0358562010-05-18 13:20:32 +0200171struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
172{
173 struct list_head *p;
Johan Hedbergf0358562010-05-18 13:20:32 +0200174
David Millerea4bd8b2010-07-30 21:54:49 -0700175 list_for_each(p, &hdev->blacklist) {
Johan Hedbergf0358562010-05-18 13:20:32 +0200176 struct bdaddr_list *b;
177
178 b = list_entry(p, struct bdaddr_list, list);
179
180 if (bacmp(bdaddr, &b->bdaddr) == 0)
181 return b;
182 }
183
184 return NULL;
185}
186
187static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
188{
189 bdaddr_t bdaddr;
190 struct bdaddr_list *entry;
191
192 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
193 return -EFAULT;
194
195 if (bacmp(&bdaddr, BDADDR_ANY) == 0)
196 return -EBADF;
197
198 if (hci_blacklist_lookup(hdev, &bdaddr))
199 return -EEXIST;
200
201 entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
202 if (!entry)
203 return -ENOMEM;
204
205 bacpy(&entry->bdaddr, &bdaddr);
206
David Millerea4bd8b2010-07-30 21:54:49 -0700207 list_add(&entry->list, &hdev->blacklist);
Johan Hedbergf0358562010-05-18 13:20:32 +0200208
209 return 0;
210}
211
212int hci_blacklist_clear(struct hci_dev *hdev)
213{
214 struct list_head *p, *n;
Johan Hedbergf0358562010-05-18 13:20:32 +0200215
David Millerea4bd8b2010-07-30 21:54:49 -0700216 list_for_each_safe(p, n, &hdev->blacklist) {
Johan Hedbergf0358562010-05-18 13:20:32 +0200217 struct bdaddr_list *b;
218
219 b = list_entry(p, struct bdaddr_list, list);
220
221 list_del(p);
222 kfree(b);
223 }
224
225 return 0;
226}
227
228static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
229{
230 bdaddr_t bdaddr;
231 struct bdaddr_list *entry;
232
233 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
234 return -EFAULT;
235
236 if (bacmp(&bdaddr, BDADDR_ANY) == 0)
237 return hci_blacklist_clear(hdev);
238
239 entry = hci_blacklist_lookup(hdev, &bdaddr);
240 if (!entry)
241 return -ENOENT;
242
243 list_del(&entry->list);
244 kfree(entry);
245
246 return 0;
247}
248
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900249/* Ioctls that require bound socket */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
251{
252 struct hci_dev *hdev = hci_pi(sk)->hdev;
253
254 if (!hdev)
255 return -EBADFD;
256
257 switch (cmd) {
258 case HCISETRAW:
259 if (!capable(CAP_NET_ADMIN))
260 return -EACCES;
261
262 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
263 return -EPERM;
264
265 if (arg)
266 set_bit(HCI_RAW, &hdev->flags);
267 else
268 clear_bit(HCI_RAW, &hdev->flags);
269
270 return 0;
271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 case HCIGETCONNINFO:
Marcel Holtmann40be4922008-07-14 20:13:50 +0200273 return hci_get_conn_info(hdev, (void __user *) arg);
274
275 case HCIGETAUTHINFO:
276 return hci_get_auth_info(hdev, (void __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
Johan Hedbergf0358562010-05-18 13:20:32 +0200278 case HCIBLOCKADDR:
279 if (!capable(CAP_NET_ADMIN))
280 return -EACCES;
281 return hci_blacklist_add(hdev, (void __user *) arg);
282
283 case HCIUNBLOCKADDR:
284 if (!capable(CAP_NET_ADMIN))
285 return -EACCES;
286 return hci_blacklist_del(hdev, (void __user *) arg);
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 default:
289 if (hdev->ioctl)
290 return hdev->ioctl(hdev, cmd, arg);
291 return -EINVAL;
292 }
293}
294
295static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
296{
297 struct sock *sk = sock->sk;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200298 void __user *argp = (void __user *) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 int err;
300
301 BT_DBG("cmd %x arg %lx", cmd, arg);
302
303 switch (cmd) {
304 case HCIGETDEVLIST:
305 return hci_get_dev_list(argp);
306
307 case HCIGETDEVINFO:
308 return hci_get_dev_info(argp);
309
310 case HCIGETCONNLIST:
311 return hci_get_conn_list(argp);
312
313 case HCIDEVUP:
314 if (!capable(CAP_NET_ADMIN))
315 return -EACCES;
316 return hci_dev_open(arg);
317
318 case HCIDEVDOWN:
319 if (!capable(CAP_NET_ADMIN))
320 return -EACCES;
321 return hci_dev_close(arg);
322
323 case HCIDEVRESET:
324 if (!capable(CAP_NET_ADMIN))
325 return -EACCES;
326 return hci_dev_reset(arg);
327
328 case HCIDEVRESTAT:
329 if (!capable(CAP_NET_ADMIN))
330 return -EACCES;
331 return hci_dev_reset_stat(arg);
332
333 case HCISETSCAN:
334 case HCISETAUTH:
335 case HCISETENCRYPT:
336 case HCISETPTYPE:
337 case HCISETLINKPOL:
338 case HCISETLINKMODE:
339 case HCISETACLMTU:
340 case HCISETSCOMTU:
341 if (!capable(CAP_NET_ADMIN))
342 return -EACCES;
343 return hci_dev_cmd(cmd, argp);
344
345 case HCIINQUIRY:
346 return hci_inquiry(argp);
347
348 default:
349 lock_sock(sk);
350 err = hci_sock_bound_ioctl(sk, cmd, arg);
351 release_sock(sk);
352 return err;
353 }
354}
355
356static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
357{
Johan Hedberg03811012010-12-08 00:21:06 +0200358 struct sockaddr_hci haddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 struct sock *sk = sock->sk;
360 struct hci_dev *hdev = NULL;
Johan Hedberg03811012010-12-08 00:21:06 +0200361 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 BT_DBG("sock %p sk %p", sock, sk);
364
Johan Hedberg03811012010-12-08 00:21:06 +0200365 if (!addr)
366 return -EINVAL;
367
368 memset(&haddr, 0, sizeof(haddr));
369 len = min_t(unsigned int, sizeof(haddr), addr_len);
370 memcpy(&haddr, addr, len);
371
372 if (haddr.hci_family != AF_BLUETOOTH)
373 return -EINVAL;
374
375 if (haddr.hci_channel != HCI_CHANNEL_RAW && !enable_mgmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 return -EINVAL;
377
378 lock_sock(sk);
379
Johan Hedberg03811012010-12-08 00:21:06 +0200380 if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 err = -EALREADY;
382 goto done;
383 }
384
Johan Hedberg03811012010-12-08 00:21:06 +0200385 if (haddr.hci_dev != HCI_DEV_NONE) {
386 hdev = hci_dev_get(haddr.hci_dev);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200387 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 err = -ENODEV;
389 goto done;
390 }
391
392 atomic_inc(&hdev->promisc);
393 }
394
Johan Hedberg03811012010-12-08 00:21:06 +0200395 hci_pi(sk)->channel = haddr.hci_channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 hci_pi(sk)->hdev = hdev;
397 sk->sk_state = BT_BOUND;
398
399done:
400 release_sock(sk);
401 return err;
402}
403
404static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
405{
406 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
407 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100408 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
410 BT_DBG("sock %p sk %p", sock, sk);
411
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100412 if (!hdev)
413 return -EBADFD;
414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 lock_sock(sk);
416
417 *addr_len = sizeof(*haddr);
418 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100419 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421 release_sock(sk);
422 return 0;
423}
424
425static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
426{
427 __u32 mask = hci_pi(sk)->cmsg_mask;
428
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700429 if (mask & HCI_CMSG_DIR) {
430 int incoming = bt_cb(skb)->incoming;
431 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700434 if (mask & HCI_CMSG_TSTAMP) {
Johann Felix Sodenf6e623a2010-02-15 22:23:48 +0100435#ifdef CONFIG_COMPAT
436 struct compat_timeval ctv;
437#endif
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700438 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200439 void *data;
440 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700441
442 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200443
David S. Miller1da97f82007-09-12 14:10:58 +0200444 data = &tv;
445 len = sizeof(tv);
446#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200447 if (msg->msg_flags & MSG_CMSG_COMPAT) {
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200448 ctv.tv_sec = tv.tv_sec;
449 ctv.tv_usec = tv.tv_usec;
450 data = &ctv;
451 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200452 }
David S. Miller1da97f82007-09-12 14:10:58 +0200453#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200454
455 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700456 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900458
459static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 struct msghdr *msg, size_t len, int flags)
461{
462 int noblock = flags & MSG_DONTWAIT;
463 struct sock *sk = sock->sk;
464 struct sk_buff *skb;
465 int copied, err;
466
467 BT_DBG("sock %p, sk %p", sock, sk);
468
469 if (flags & (MSG_OOB))
470 return -EOPNOTSUPP;
471
472 if (sk->sk_state == BT_CLOSED)
473 return 0;
474
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200475 skb = skb_recv_datagram(sk, flags, noblock, &err);
476 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 return err;
478
479 msg->msg_namelen = 0;
480
481 copied = skb->len;
482 if (len < copied) {
483 msg->msg_flags |= MSG_TRUNC;
484 copied = len;
485 }
486
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300487 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
489
490 hci_sock_cmsg(sk, msg, skb);
491
492 skb_free_datagram(sk, skb);
493
494 return err ? : copied;
495}
496
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900497static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 struct msghdr *msg, size_t len)
499{
500 struct sock *sk = sock->sk;
501 struct hci_dev *hdev;
502 struct sk_buff *skb;
503 int err;
504
505 BT_DBG("sock %p sk %p", sock, sk);
506
507 if (msg->msg_flags & MSG_OOB)
508 return -EOPNOTSUPP;
509
510 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
511 return -EINVAL;
512
513 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
514 return -EINVAL;
515
516 lock_sock(sk);
517
Johan Hedberg03811012010-12-08 00:21:06 +0200518 switch (hci_pi(sk)->channel) {
519 case HCI_CHANNEL_RAW:
520 break;
521 case HCI_CHANNEL_CONTROL:
522 err = mgmt_control(sk, msg, len);
523 goto done;
524 default:
525 err = -EINVAL;
526 goto done;
527 }
528
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200529 hdev = hci_pi(sk)->hdev;
530 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 err = -EBADFD;
532 goto done;
533 }
534
Marcel Holtmann7e21add2009-11-18 01:05:00 +0100535 if (!test_bit(HCI_UP, &hdev->flags)) {
536 err = -ENETDOWN;
537 goto done;
538 }
539
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200540 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
541 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 goto done;
543
544 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
545 err = -EFAULT;
546 goto drop;
547 }
548
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700549 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 skb_pull(skb, 1);
551 skb->dev = (void *) hdev;
552
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700553 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700554 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 u16 ogf = hci_opcode_ogf(opcode);
556 u16 ocf = hci_opcode_ocf(opcode);
557
558 if (((ogf > HCI_SFLT_MAX_OGF) ||
559 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
560 !capable(CAP_NET_RAW)) {
561 err = -EPERM;
562 goto drop;
563 }
564
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200565 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100567 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 } else {
569 skb_queue_tail(&hdev->cmd_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100570 tasklet_schedule(&hdev->cmd_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 }
572 } else {
573 if (!capable(CAP_NET_RAW)) {
574 err = -EPERM;
575 goto drop;
576 }
577
578 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100579 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 }
581
582 err = len;
583
584done:
585 release_sock(sk);
586 return err;
587
588drop:
589 kfree_skb(skb);
590 goto done;
591}
592
David S. Millerb7058842009-09-30 16:12:20 -0700593static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594{
595 struct hci_ufilter uf = { .opcode = 0 };
596 struct sock *sk = sock->sk;
597 int err = 0, opt = 0;
598
599 BT_DBG("sk %p, opt %d", sk, optname);
600
601 lock_sock(sk);
602
603 switch (optname) {
604 case HCI_DATA_DIR:
605 if (get_user(opt, (int __user *)optval)) {
606 err = -EFAULT;
607 break;
608 }
609
610 if (opt)
611 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
612 else
613 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
614 break;
615
616 case HCI_TIME_STAMP:
617 if (get_user(opt, (int __user *)optval)) {
618 err = -EFAULT;
619 break;
620 }
621
622 if (opt)
623 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
624 else
625 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
626 break;
627
628 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200629 {
630 struct hci_filter *f = &hci_pi(sk)->filter;
631
632 uf.type_mask = f->type_mask;
633 uf.opcode = f->opcode;
634 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
635 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
636 }
637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 len = min_t(unsigned int, len, sizeof(uf));
639 if (copy_from_user(&uf, optval, len)) {
640 err = -EFAULT;
641 break;
642 }
643
644 if (!capable(CAP_NET_RAW)) {
645 uf.type_mask &= hci_sec_filter.type_mask;
646 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
647 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
648 }
649
650 {
651 struct hci_filter *f = &hci_pi(sk)->filter;
652
653 f->type_mask = uf.type_mask;
654 f->opcode = uf.opcode;
655 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
656 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
657 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900658 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 default:
661 err = -ENOPROTOOPT;
662 break;
663 }
664
665 release_sock(sk);
666 return err;
667}
668
669static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
670{
671 struct hci_ufilter uf;
672 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900673 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
675 if (get_user(len, optlen))
676 return -EFAULT;
677
678 switch (optname) {
679 case HCI_DATA_DIR:
680 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
681 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900682 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 opt = 0;
684
685 if (put_user(opt, optval))
686 return -EFAULT;
687 break;
688
689 case HCI_TIME_STAMP:
690 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
691 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900692 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 opt = 0;
694
695 if (put_user(opt, optval))
696 return -EFAULT;
697 break;
698
699 case HCI_FILTER:
700 {
701 struct hci_filter *f = &hci_pi(sk)->filter;
702
703 uf.type_mask = f->type_mask;
704 uf.opcode = f->opcode;
705 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
706 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
707 }
708
709 len = min_t(unsigned int, len, sizeof(uf));
710 if (copy_to_user(optval, &uf, len))
711 return -EFAULT;
712 break;
713
714 default:
715 return -ENOPROTOOPT;
716 break;
717 }
718
719 return 0;
720}
721
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800722static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 .family = PF_BLUETOOTH,
724 .owner = THIS_MODULE,
725 .release = hci_sock_release,
726 .bind = hci_sock_bind,
727 .getname = hci_sock_getname,
728 .sendmsg = hci_sock_sendmsg,
729 .recvmsg = hci_sock_recvmsg,
730 .ioctl = hci_sock_ioctl,
731 .poll = datagram_poll,
732 .listen = sock_no_listen,
733 .shutdown = sock_no_shutdown,
734 .setsockopt = hci_sock_setsockopt,
735 .getsockopt = hci_sock_getsockopt,
736 .connect = sock_no_connect,
737 .socketpair = sock_no_socketpair,
738 .accept = sock_no_accept,
739 .mmap = sock_no_mmap
740};
741
742static struct proto hci_sk_proto = {
743 .name = "HCI",
744 .owner = THIS_MODULE,
745 .obj_size = sizeof(struct hci_pinfo)
746};
747
Eric Paris3f378b62009-11-05 22:18:14 -0800748static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
749 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
751 struct sock *sk;
752
753 BT_DBG("sock %p", sock);
754
755 if (sock->type != SOCK_RAW)
756 return -ESOCKTNOSUPPORT;
757
758 sock->ops = &hci_sock_ops;
759
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700760 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 if (!sk)
762 return -ENOMEM;
763
764 sock_init_data(sock, sk);
765
766 sock_reset_flag(sk, SOCK_ZAPPED);
767
768 sk->sk_protocol = protocol;
769
770 sock->state = SS_UNCONNECTED;
771 sk->sk_state = BT_OPEN;
772
773 bt_sock_link(&hci_sk_list, sk);
774 return 0;
775}
776
777static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
778{
779 struct hci_dev *hdev = (struct hci_dev *) ptr;
780 struct hci_ev_si_device ev;
781
782 BT_DBG("hdev %s event %ld", hdev->name, event);
783
784 /* Send event to sockets */
785 ev.event = event;
786 ev.dev_id = hdev->id;
787 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
788
789 if (event == HCI_DEV_UNREG) {
790 struct sock *sk;
791 struct hlist_node *node;
792
793 /* Detach sockets from device */
794 read_lock(&hci_sk_list.lock);
795 sk_for_each(sk, node, &hci_sk_list.head) {
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700796 local_bh_disable();
797 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 if (hci_pi(sk)->hdev == hdev) {
799 hci_pi(sk)->hdev = NULL;
800 sk->sk_err = EPIPE;
801 sk->sk_state = BT_OPEN;
802 sk->sk_state_change(sk);
803
804 hci_dev_put(hdev);
805 }
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700806 bh_unlock_sock(sk);
807 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 }
809 read_unlock(&hci_sk_list.lock);
810 }
811
812 return NOTIFY_DONE;
813}
814
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +0000815static const struct net_proto_family hci_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 .family = PF_BLUETOOTH,
817 .owner = THIS_MODULE,
818 .create = hci_sock_create,
819};
820
821static struct notifier_block hci_sock_nblock = {
822 .notifier_call = hci_sock_dev_event
823};
824
825int __init hci_sock_init(void)
826{
827 int err;
828
829 err = proto_register(&hci_sk_proto, 0);
830 if (err < 0)
831 return err;
832
833 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
834 if (err < 0)
835 goto error;
836
837 hci_register_notifier(&hci_sock_nblock);
838
839 BT_INFO("HCI socket layer initialized");
840
841 return 0;
842
843error:
844 BT_ERR("HCI socket registration failed");
845 proto_unregister(&hci_sk_proto);
846 return err;
847}
848
Tobias Klauser04005dd2008-03-05 18:47:03 -0800849void __exit hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850{
851 if (bt_sock_unregister(BTPROTO_HCI) < 0)
852 BT_ERR("HCI socket unregistration failed");
853
854 hci_unregister_notifier(&hci_sock_nblock);
855
856 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
Johan Hedberg03811012010-12-08 00:21:06 +0200858
859module_param(enable_mgmt, bool, 0644);
860MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");