blob: 295e4a88fff8ccea7e197560d47f90bc6584b7df [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 */
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020088void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
89 struct sock *skip_sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
91 struct sock *sk;
92 struct hlist_node *node;
93
94 BT_DBG("hdev %p len %d", hdev, skb->len);
95
96 read_lock(&hci_sk_list.lock);
97 sk_for_each(sk, node, &hci_sk_list.head) {
98 struct hci_filter *flt;
99 struct sk_buff *nskb;
100
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200101 if (sk == skip_sk)
102 continue;
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
105 continue;
106
107 /* Don't send frame to the socket it came from */
108 if (skb->sk == sk)
109 continue;
110
Johan Hedberga40c4062010-12-08 00:21:07 +0200111 if (bt_cb(skb)->channel != hci_pi(sk)->channel)
112 continue;
113
114 if (bt_cb(skb)->channel == HCI_CHANNEL_CONTROL)
115 goto clone;
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 /* Apply filter */
118 flt = &hci_pi(sk)->filter;
119
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700120 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
121 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 continue;
123
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700124 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
126
127 if (!hci_test_bit(evt, &flt->event_mask))
128 continue;
129
David S. Miller4498c802006-11-21 16:17:41 -0800130 if (flt->opcode &&
131 ((evt == HCI_EV_CMD_COMPLETE &&
132 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800133 get_unaligned((__le16 *)(skb->data + 3))) ||
David S. Miller4498c802006-11-21 16:17:41 -0800134 (evt == HCI_EV_CMD_STATUS &&
135 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800136 get_unaligned((__le16 *)(skb->data + 4)))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 continue;
138 }
139
Johan Hedberga40c4062010-12-08 00:21:07 +0200140clone:
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200141 nskb = skb_clone(skb, GFP_ATOMIC);
142 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 continue;
144
145 /* Put type byte before the data */
Johan Hedberga40c4062010-12-08 00:21:07 +0200146 if (bt_cb(skb)->channel == HCI_CHANNEL_RAW)
147 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 if (sock_queue_rcv_skb(sk, nskb))
150 kfree_skb(nskb);
151 }
152 read_unlock(&hci_sk_list.lock);
153}
154
155static int hci_sock_release(struct socket *sock)
156{
157 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100158 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 BT_DBG("sock %p sk %p", sock, sk);
161
162 if (!sk)
163 return 0;
164
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100165 hdev = hci_pi(sk)->hdev;
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 bt_sock_unlink(&hci_sk_list, sk);
168
169 if (hdev) {
170 atomic_dec(&hdev->promisc);
171 hci_dev_put(hdev);
172 }
173
174 sock_orphan(sk);
175
176 skb_queue_purge(&sk->sk_receive_queue);
177 skb_queue_purge(&sk->sk_write_queue);
178
179 sock_put(sk);
180 return 0;
181}
182
Johan Hedbergf0358562010-05-18 13:20:32 +0200183struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
184{
185 struct list_head *p;
Johan Hedbergf0358562010-05-18 13:20:32 +0200186
David Millerea4bd8b2010-07-30 21:54:49 -0700187 list_for_each(p, &hdev->blacklist) {
Johan Hedbergf0358562010-05-18 13:20:32 +0200188 struct bdaddr_list *b;
189
190 b = list_entry(p, struct bdaddr_list, list);
191
192 if (bacmp(bdaddr, &b->bdaddr) == 0)
193 return b;
194 }
195
196 return NULL;
197}
198
199static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
200{
201 bdaddr_t bdaddr;
202 struct bdaddr_list *entry;
203
204 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
205 return -EFAULT;
206
207 if (bacmp(&bdaddr, BDADDR_ANY) == 0)
208 return -EBADF;
209
210 if (hci_blacklist_lookup(hdev, &bdaddr))
211 return -EEXIST;
212
213 entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
214 if (!entry)
215 return -ENOMEM;
216
217 bacpy(&entry->bdaddr, &bdaddr);
218
David Millerea4bd8b2010-07-30 21:54:49 -0700219 list_add(&entry->list, &hdev->blacklist);
Johan Hedbergf0358562010-05-18 13:20:32 +0200220
221 return 0;
222}
223
224int hci_blacklist_clear(struct hci_dev *hdev)
225{
226 struct list_head *p, *n;
Johan Hedbergf0358562010-05-18 13:20:32 +0200227
David Millerea4bd8b2010-07-30 21:54:49 -0700228 list_for_each_safe(p, n, &hdev->blacklist) {
Johan Hedbergf0358562010-05-18 13:20:32 +0200229 struct bdaddr_list *b;
230
231 b = list_entry(p, struct bdaddr_list, list);
232
233 list_del(p);
234 kfree(b);
235 }
236
237 return 0;
238}
239
240static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
241{
242 bdaddr_t bdaddr;
243 struct bdaddr_list *entry;
244
245 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
246 return -EFAULT;
247
248 if (bacmp(&bdaddr, BDADDR_ANY) == 0)
249 return hci_blacklist_clear(hdev);
250
251 entry = hci_blacklist_lookup(hdev, &bdaddr);
252 if (!entry)
253 return -ENOENT;
254
255 list_del(&entry->list);
256 kfree(entry);
257
258 return 0;
259}
260
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900261/* Ioctls that require bound socket */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
263{
264 struct hci_dev *hdev = hci_pi(sk)->hdev;
265
266 if (!hdev)
267 return -EBADFD;
268
269 switch (cmd) {
270 case HCISETRAW:
271 if (!capable(CAP_NET_ADMIN))
272 return -EACCES;
273
274 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
275 return -EPERM;
276
277 if (arg)
278 set_bit(HCI_RAW, &hdev->flags);
279 else
280 clear_bit(HCI_RAW, &hdev->flags);
281
282 return 0;
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 case HCIGETCONNINFO:
Marcel Holtmann40be4922008-07-14 20:13:50 +0200285 return hci_get_conn_info(hdev, (void __user *) arg);
286
287 case HCIGETAUTHINFO:
288 return hci_get_auth_info(hdev, (void __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Johan Hedbergf0358562010-05-18 13:20:32 +0200290 case HCIBLOCKADDR:
291 if (!capable(CAP_NET_ADMIN))
292 return -EACCES;
293 return hci_blacklist_add(hdev, (void __user *) arg);
294
295 case HCIUNBLOCKADDR:
296 if (!capable(CAP_NET_ADMIN))
297 return -EACCES;
298 return hci_blacklist_del(hdev, (void __user *) arg);
299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 default:
301 if (hdev->ioctl)
302 return hdev->ioctl(hdev, cmd, arg);
303 return -EINVAL;
304 }
305}
306
307static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
308{
309 struct sock *sk = sock->sk;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200310 void __user *argp = (void __user *) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 int err;
312
313 BT_DBG("cmd %x arg %lx", cmd, arg);
314
315 switch (cmd) {
316 case HCIGETDEVLIST:
317 return hci_get_dev_list(argp);
318
319 case HCIGETDEVINFO:
320 return hci_get_dev_info(argp);
321
322 case HCIGETCONNLIST:
323 return hci_get_conn_list(argp);
324
325 case HCIDEVUP:
326 if (!capable(CAP_NET_ADMIN))
327 return -EACCES;
328 return hci_dev_open(arg);
329
330 case HCIDEVDOWN:
331 if (!capable(CAP_NET_ADMIN))
332 return -EACCES;
333 return hci_dev_close(arg);
334
335 case HCIDEVRESET:
336 if (!capable(CAP_NET_ADMIN))
337 return -EACCES;
338 return hci_dev_reset(arg);
339
340 case HCIDEVRESTAT:
341 if (!capable(CAP_NET_ADMIN))
342 return -EACCES;
343 return hci_dev_reset_stat(arg);
344
345 case HCISETSCAN:
346 case HCISETAUTH:
347 case HCISETENCRYPT:
348 case HCISETPTYPE:
349 case HCISETLINKPOL:
350 case HCISETLINKMODE:
351 case HCISETACLMTU:
352 case HCISETSCOMTU:
353 if (!capable(CAP_NET_ADMIN))
354 return -EACCES;
355 return hci_dev_cmd(cmd, argp);
356
357 case HCIINQUIRY:
358 return hci_inquiry(argp);
359
360 default:
361 lock_sock(sk);
362 err = hci_sock_bound_ioctl(sk, cmd, arg);
363 release_sock(sk);
364 return err;
365 }
366}
367
368static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
369{
Johan Hedberg03811012010-12-08 00:21:06 +0200370 struct sockaddr_hci haddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 struct sock *sk = sock->sk;
372 struct hci_dev *hdev = NULL;
Johan Hedberg03811012010-12-08 00:21:06 +0200373 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
375 BT_DBG("sock %p sk %p", sock, sk);
376
Johan Hedberg03811012010-12-08 00:21:06 +0200377 if (!addr)
378 return -EINVAL;
379
380 memset(&haddr, 0, sizeof(haddr));
381 len = min_t(unsigned int, sizeof(haddr), addr_len);
382 memcpy(&haddr, addr, len);
383
384 if (haddr.hci_family != AF_BLUETOOTH)
385 return -EINVAL;
386
Gustavo F. Padovan17f9cc32010-12-22 23:00:34 -0200387 if (haddr.hci_channel > HCI_CHANNEL_CONTROL)
388 return -EINVAL;
389
390 if (haddr.hci_channel == HCI_CHANNEL_CONTROL && !enable_mgmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 return -EINVAL;
392
393 lock_sock(sk);
394
Johan Hedberg03811012010-12-08 00:21:06 +0200395 if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 err = -EALREADY;
397 goto done;
398 }
399
Johan Hedberg03811012010-12-08 00:21:06 +0200400 if (haddr.hci_dev != HCI_DEV_NONE) {
401 hdev = hci_dev_get(haddr.hci_dev);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200402 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 err = -ENODEV;
404 goto done;
405 }
406
407 atomic_inc(&hdev->promisc);
408 }
409
Johan Hedberg03811012010-12-08 00:21:06 +0200410 hci_pi(sk)->channel = haddr.hci_channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 hci_pi(sk)->hdev = hdev;
412 sk->sk_state = BT_BOUND;
413
414done:
415 release_sock(sk);
416 return err;
417}
418
419static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
420{
421 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
422 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100423 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
425 BT_DBG("sock %p sk %p", sock, sk);
426
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100427 if (!hdev)
428 return -EBADFD;
429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 lock_sock(sk);
431
432 *addr_len = sizeof(*haddr);
433 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100434 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 release_sock(sk);
437 return 0;
438}
439
440static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
441{
442 __u32 mask = hci_pi(sk)->cmsg_mask;
443
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700444 if (mask & HCI_CMSG_DIR) {
445 int incoming = bt_cb(skb)->incoming;
446 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700449 if (mask & HCI_CMSG_TSTAMP) {
Johann Felix Sodenf6e623a2010-02-15 22:23:48 +0100450#ifdef CONFIG_COMPAT
451 struct compat_timeval ctv;
452#endif
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700453 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200454 void *data;
455 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700456
457 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200458
David S. Miller1da97f82007-09-12 14:10:58 +0200459 data = &tv;
460 len = sizeof(tv);
461#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200462 if (msg->msg_flags & MSG_CMSG_COMPAT) {
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200463 ctv.tv_sec = tv.tv_sec;
464 ctv.tv_usec = tv.tv_usec;
465 data = &ctv;
466 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200467 }
David S. Miller1da97f82007-09-12 14:10:58 +0200468#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200469
470 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900473
474static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 struct msghdr *msg, size_t len, int flags)
476{
477 int noblock = flags & MSG_DONTWAIT;
478 struct sock *sk = sock->sk;
479 struct sk_buff *skb;
480 int copied, err;
481
482 BT_DBG("sock %p, sk %p", sock, sk);
483
484 if (flags & (MSG_OOB))
485 return -EOPNOTSUPP;
486
487 if (sk->sk_state == BT_CLOSED)
488 return 0;
489
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200490 skb = skb_recv_datagram(sk, flags, noblock, &err);
491 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 return err;
493
494 msg->msg_namelen = 0;
495
496 copied = skb->len;
497 if (len < copied) {
498 msg->msg_flags |= MSG_TRUNC;
499 copied = len;
500 }
501
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300502 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
504
505 hci_sock_cmsg(sk, msg, skb);
506
507 skb_free_datagram(sk, skb);
508
509 return err ? : copied;
510}
511
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900512static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 struct msghdr *msg, size_t len)
514{
515 struct sock *sk = sock->sk;
516 struct hci_dev *hdev;
517 struct sk_buff *skb;
518 int err;
519
520 BT_DBG("sock %p sk %p", sock, sk);
521
522 if (msg->msg_flags & MSG_OOB)
523 return -EOPNOTSUPP;
524
525 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
526 return -EINVAL;
527
528 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
529 return -EINVAL;
530
531 lock_sock(sk);
532
Johan Hedberg03811012010-12-08 00:21:06 +0200533 switch (hci_pi(sk)->channel) {
534 case HCI_CHANNEL_RAW:
535 break;
536 case HCI_CHANNEL_CONTROL:
537 err = mgmt_control(sk, msg, len);
538 goto done;
539 default:
540 err = -EINVAL;
541 goto done;
542 }
543
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200544 hdev = hci_pi(sk)->hdev;
545 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 err = -EBADFD;
547 goto done;
548 }
549
Marcel Holtmann7e21add2009-11-18 01:05:00 +0100550 if (!test_bit(HCI_UP, &hdev->flags)) {
551 err = -ENETDOWN;
552 goto done;
553 }
554
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200555 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
556 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 goto done;
558
559 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
560 err = -EFAULT;
561 goto drop;
562 }
563
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700564 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 skb_pull(skb, 1);
566 skb->dev = (void *) hdev;
567
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700568 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700569 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 u16 ogf = hci_opcode_ogf(opcode);
571 u16 ocf = hci_opcode_ocf(opcode);
572
573 if (((ogf > HCI_SFLT_MAX_OGF) ||
574 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
575 !capable(CAP_NET_RAW)) {
576 err = -EPERM;
577 goto drop;
578 }
579
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200580 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100582 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 } else {
584 skb_queue_tail(&hdev->cmd_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100585 tasklet_schedule(&hdev->cmd_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 }
587 } else {
588 if (!capable(CAP_NET_RAW)) {
589 err = -EPERM;
590 goto drop;
591 }
592
593 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100594 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 }
596
597 err = len;
598
599done:
600 release_sock(sk);
601 return err;
602
603drop:
604 kfree_skb(skb);
605 goto done;
606}
607
David S. Millerb7058842009-09-30 16:12:20 -0700608static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
610 struct hci_ufilter uf = { .opcode = 0 };
611 struct sock *sk = sock->sk;
612 int err = 0, opt = 0;
613
614 BT_DBG("sk %p, opt %d", sk, optname);
615
616 lock_sock(sk);
617
618 switch (optname) {
619 case HCI_DATA_DIR:
620 if (get_user(opt, (int __user *)optval)) {
621 err = -EFAULT;
622 break;
623 }
624
625 if (opt)
626 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
627 else
628 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
629 break;
630
631 case HCI_TIME_STAMP:
632 if (get_user(opt, (int __user *)optval)) {
633 err = -EFAULT;
634 break;
635 }
636
637 if (opt)
638 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
639 else
640 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
641 break;
642
643 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200644 {
645 struct hci_filter *f = &hci_pi(sk)->filter;
646
647 uf.type_mask = f->type_mask;
648 uf.opcode = f->opcode;
649 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
650 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
651 }
652
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 len = min_t(unsigned int, len, sizeof(uf));
654 if (copy_from_user(&uf, optval, len)) {
655 err = -EFAULT;
656 break;
657 }
658
659 if (!capable(CAP_NET_RAW)) {
660 uf.type_mask &= hci_sec_filter.type_mask;
661 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
662 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
663 }
664
665 {
666 struct hci_filter *f = &hci_pi(sk)->filter;
667
668 f->type_mask = uf.type_mask;
669 f->opcode = uf.opcode;
670 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
671 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
672 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900673 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
675 default:
676 err = -ENOPROTOOPT;
677 break;
678 }
679
680 release_sock(sk);
681 return err;
682}
683
684static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
685{
686 struct hci_ufilter uf;
687 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900688 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
690 if (get_user(len, optlen))
691 return -EFAULT;
692
693 switch (optname) {
694 case HCI_DATA_DIR:
695 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
696 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900697 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 opt = 0;
699
700 if (put_user(opt, optval))
701 return -EFAULT;
702 break;
703
704 case HCI_TIME_STAMP:
705 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
706 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900707 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 opt = 0;
709
710 if (put_user(opt, optval))
711 return -EFAULT;
712 break;
713
714 case HCI_FILTER:
715 {
716 struct hci_filter *f = &hci_pi(sk)->filter;
717
718 uf.type_mask = f->type_mask;
719 uf.opcode = f->opcode;
720 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
721 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
722 }
723
724 len = min_t(unsigned int, len, sizeof(uf));
725 if (copy_to_user(optval, &uf, len))
726 return -EFAULT;
727 break;
728
729 default:
730 return -ENOPROTOOPT;
731 break;
732 }
733
734 return 0;
735}
736
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800737static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 .family = PF_BLUETOOTH,
739 .owner = THIS_MODULE,
740 .release = hci_sock_release,
741 .bind = hci_sock_bind,
742 .getname = hci_sock_getname,
743 .sendmsg = hci_sock_sendmsg,
744 .recvmsg = hci_sock_recvmsg,
745 .ioctl = hci_sock_ioctl,
746 .poll = datagram_poll,
747 .listen = sock_no_listen,
748 .shutdown = sock_no_shutdown,
749 .setsockopt = hci_sock_setsockopt,
750 .getsockopt = hci_sock_getsockopt,
751 .connect = sock_no_connect,
752 .socketpair = sock_no_socketpair,
753 .accept = sock_no_accept,
754 .mmap = sock_no_mmap
755};
756
757static struct proto hci_sk_proto = {
758 .name = "HCI",
759 .owner = THIS_MODULE,
760 .obj_size = sizeof(struct hci_pinfo)
761};
762
Eric Paris3f378b62009-11-05 22:18:14 -0800763static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
764 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
766 struct sock *sk;
767
768 BT_DBG("sock %p", sock);
769
770 if (sock->type != SOCK_RAW)
771 return -ESOCKTNOSUPPORT;
772
773 sock->ops = &hci_sock_ops;
774
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700775 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 if (!sk)
777 return -ENOMEM;
778
779 sock_init_data(sock, sk);
780
781 sock_reset_flag(sk, SOCK_ZAPPED);
782
783 sk->sk_protocol = protocol;
784
785 sock->state = SS_UNCONNECTED;
786 sk->sk_state = BT_OPEN;
787
788 bt_sock_link(&hci_sk_list, sk);
789 return 0;
790}
791
792static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
793{
794 struct hci_dev *hdev = (struct hci_dev *) ptr;
795 struct hci_ev_si_device ev;
796
797 BT_DBG("hdev %s event %ld", hdev->name, event);
798
799 /* Send event to sockets */
800 ev.event = event;
801 ev.dev_id = hdev->id;
802 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
803
804 if (event == HCI_DEV_UNREG) {
805 struct sock *sk;
806 struct hlist_node *node;
807
808 /* Detach sockets from device */
809 read_lock(&hci_sk_list.lock);
810 sk_for_each(sk, node, &hci_sk_list.head) {
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700811 local_bh_disable();
812 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (hci_pi(sk)->hdev == hdev) {
814 hci_pi(sk)->hdev = NULL;
815 sk->sk_err = EPIPE;
816 sk->sk_state = BT_OPEN;
817 sk->sk_state_change(sk);
818
819 hci_dev_put(hdev);
820 }
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700821 bh_unlock_sock(sk);
822 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 }
824 read_unlock(&hci_sk_list.lock);
825 }
826
827 return NOTIFY_DONE;
828}
829
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +0000830static const struct net_proto_family hci_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 .family = PF_BLUETOOTH,
832 .owner = THIS_MODULE,
833 .create = hci_sock_create,
834};
835
836static struct notifier_block hci_sock_nblock = {
837 .notifier_call = hci_sock_dev_event
838};
839
840int __init hci_sock_init(void)
841{
842 int err;
843
844 err = proto_register(&hci_sk_proto, 0);
845 if (err < 0)
846 return err;
847
848 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
849 if (err < 0)
850 goto error;
851
852 hci_register_notifier(&hci_sock_nblock);
853
854 BT_INFO("HCI socket layer initialized");
855
856 return 0;
857
858error:
859 BT_ERR("HCI socket registration failed");
860 proto_unregister(&hci_sk_proto);
861 return err;
862}
863
Anand Gadiyarb7440a142011-02-22 12:43:09 +0530864void hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865{
866 if (bt_sock_unregister(BTPROTO_HCI) < 0)
867 BT_ERR("HCI socket unregistration failed");
868
869 hci_unregister_notifier(&hci_sock_nblock);
870
871 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872}
Johan Hedberg03811012010-12-08 00:21:06 +0200873
874module_param(enable_mgmt, bool, 0644);
875MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");