blob: 00469456b64522728146cad24ea4a3f3b87fa298 [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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003 Copyright (c) 2000-2001, 2011, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700183struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
Johan Hedbergf0358562010-05-18 13:20:32 +0200184{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700185 struct list_head *p;
Johan Hedbergf0358562010-05-18 13:20:32 +0200186
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187 list_for_each(p, &hdev->blacklist) {
188 struct bdaddr_list *b;
Johan Hedbergf0358562010-05-18 13:20:32 +0200189
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700190 b = list_entry(p, struct bdaddr_list, list);
191
192 if (bacmp(bdaddr, &b->bdaddr) == 0)
193 return b;
194 }
195
196 return NULL;
Johan Hedbergf0358562010-05-18 13:20:32 +0200197}
198
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700199static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
Johan Hedbergf0358562010-05-18 13:20:32 +0200200{
201 bdaddr_t bdaddr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202 struct bdaddr_list *entry;
Johan Hedbergf0358562010-05-18 13:20:32 +0200203
204 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
205 return -EFAULT;
206
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 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
219 list_add(&entry->list, &hdev->blacklist);
220
221 return 0;
222}
223
224int hci_blacklist_clear(struct hci_dev *hdev)
225{
226 struct list_head *p, *n;
227
228 list_for_each_safe(p, n, &hdev->blacklist) {
229 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;
Johan Hedbergf0358562010-05-18 13:20:32 +0200259}
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;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 return hci_blacklist_add(hdev, (void __user *) arg);
Johan Hedbergf0358562010-05-18 13:20:32 +0200294
295 case HCIUNBLOCKADDR:
296 if (!capable(CAP_NET_ADMIN))
297 return -EACCES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298 return hci_blacklist_del(hdev, (void __user *) arg);
299
300 case HCISETAUTHINFO:
301 return hci_set_auth_info(hdev, (void __user *) arg);
Johan Hedbergf0358562010-05-18 13:20:32 +0200302
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 default:
304 if (hdev->ioctl)
305 return hdev->ioctl(hdev, cmd, arg);
306 return -EINVAL;
307 }
308}
309
310static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
311{
312 struct sock *sk = sock->sk;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200313 void __user *argp = (void __user *) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 int err;
315
316 BT_DBG("cmd %x arg %lx", cmd, arg);
317
318 switch (cmd) {
319 case HCIGETDEVLIST:
320 return hci_get_dev_list(argp);
321
322 case HCIGETDEVINFO:
323 return hci_get_dev_info(argp);
324
325 case HCIGETCONNLIST:
326 return hci_get_conn_list(argp);
327
328 case HCIDEVUP:
329 if (!capable(CAP_NET_ADMIN))
330 return -EACCES;
331 return hci_dev_open(arg);
332
333 case HCIDEVDOWN:
334 if (!capable(CAP_NET_ADMIN))
335 return -EACCES;
336 return hci_dev_close(arg);
337
338 case HCIDEVRESET:
339 if (!capable(CAP_NET_ADMIN))
340 return -EACCES;
341 return hci_dev_reset(arg);
342
343 case HCIDEVRESTAT:
344 if (!capable(CAP_NET_ADMIN))
345 return -EACCES;
346 return hci_dev_reset_stat(arg);
347
348 case HCISETSCAN:
349 case HCISETAUTH:
350 case HCISETENCRYPT:
351 case HCISETPTYPE:
352 case HCISETLINKPOL:
353 case HCISETLINKMODE:
354 case HCISETACLMTU:
355 case HCISETSCOMTU:
356 if (!capable(CAP_NET_ADMIN))
357 return -EACCES;
358 return hci_dev_cmd(cmd, argp);
359
360 case HCIINQUIRY:
361 return hci_inquiry(argp);
362
363 default:
364 lock_sock(sk);
365 err = hci_sock_bound_ioctl(sk, cmd, arg);
366 release_sock(sk);
367 return err;
368 }
369}
370
371static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
372{
Johan Hedberg03811012010-12-08 00:21:06 +0200373 struct sockaddr_hci haddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 struct sock *sk = sock->sk;
375 struct hci_dev *hdev = NULL;
Johan Hedberg03811012010-12-08 00:21:06 +0200376 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
378 BT_DBG("sock %p sk %p", sock, sk);
379
Johan Hedberg03811012010-12-08 00:21:06 +0200380 if (!addr)
381 return -EINVAL;
382
383 memset(&haddr, 0, sizeof(haddr));
384 len = min_t(unsigned int, sizeof(haddr), addr_len);
385 memcpy(&haddr, addr, len);
386
387 if (haddr.hci_family != AF_BLUETOOTH)
388 return -EINVAL;
389
Gustavo F. Padovan17f9cc32010-12-22 23:00:34 -0200390 if (haddr.hci_channel > HCI_CHANNEL_CONTROL)
391 return -EINVAL;
392
393 if (haddr.hci_channel == HCI_CHANNEL_CONTROL && !enable_mgmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return -EINVAL;
395
396 lock_sock(sk);
397
Johan Hedberg03811012010-12-08 00:21:06 +0200398 if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 err = -EALREADY;
400 goto done;
401 }
402
Johan Hedberg03811012010-12-08 00:21:06 +0200403 if (haddr.hci_dev != HCI_DEV_NONE) {
404 hdev = hci_dev_get(haddr.hci_dev);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200405 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 err = -ENODEV;
407 goto done;
408 }
409
410 atomic_inc(&hdev->promisc);
411 }
412
Johan Hedberg03811012010-12-08 00:21:06 +0200413 hci_pi(sk)->channel = haddr.hci_channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 hci_pi(sk)->hdev = hdev;
415 sk->sk_state = BT_BOUND;
416
417done:
418 release_sock(sk);
419 return err;
420}
421
422static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
423{
424 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
425 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100426 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
428 BT_DBG("sock %p sk %p", sock, sk);
429
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100430 if (!hdev)
431 return -EBADFD;
432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 lock_sock(sk);
434
435 *addr_len = sizeof(*haddr);
436 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100437 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
439 release_sock(sk);
440 return 0;
441}
442
443static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
444{
445 __u32 mask = hci_pi(sk)->cmsg_mask;
446
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700447 if (mask & HCI_CMSG_DIR) {
448 int incoming = bt_cb(skb)->incoming;
449 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700452 if (mask & HCI_CMSG_TSTAMP) {
Johann Felix Sodenf6e623a2010-02-15 22:23:48 +0100453#ifdef CONFIG_COMPAT
454 struct compat_timeval ctv;
455#endif
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700456 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200457 void *data;
458 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700459
460 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200461
David S. Miller1da97f82007-09-12 14:10:58 +0200462 data = &tv;
463 len = sizeof(tv);
464#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200465 if (msg->msg_flags & MSG_CMSG_COMPAT) {
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200466 ctv.tv_sec = tv.tv_sec;
467 ctv.tv_usec = tv.tv_usec;
468 data = &ctv;
469 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200470 }
David S. Miller1da97f82007-09-12 14:10:58 +0200471#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200472
473 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900476
477static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 struct msghdr *msg, size_t len, int flags)
479{
480 int noblock = flags & MSG_DONTWAIT;
481 struct sock *sk = sock->sk;
482 struct sk_buff *skb;
483 int copied, err;
484
485 BT_DBG("sock %p, sk %p", sock, sk);
486
487 if (flags & (MSG_OOB))
488 return -EOPNOTSUPP;
489
490 if (sk->sk_state == BT_CLOSED)
491 return 0;
492
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200493 skb = skb_recv_datagram(sk, flags, noblock, &err);
494 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 return err;
496
497 msg->msg_namelen = 0;
498
499 copied = skb->len;
500 if (len < copied) {
501 msg->msg_flags |= MSG_TRUNC;
502 copied = len;
503 }
504
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300505 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
507
508 hci_sock_cmsg(sk, msg, skb);
509
510 skb_free_datagram(sk, skb);
511
512 return err ? : copied;
513}
514
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900515static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 struct msghdr *msg, size_t len)
517{
518 struct sock *sk = sock->sk;
519 struct hci_dev *hdev;
520 struct sk_buff *skb;
521 int err;
522
523 BT_DBG("sock %p sk %p", sock, sk);
524
525 if (msg->msg_flags & MSG_OOB)
526 return -EOPNOTSUPP;
527
528 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
529 return -EINVAL;
530
531 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
532 return -EINVAL;
533
534 lock_sock(sk);
535
Johan Hedberg03811012010-12-08 00:21:06 +0200536 switch (hci_pi(sk)->channel) {
537 case HCI_CHANNEL_RAW:
538 break;
539 case HCI_CHANNEL_CONTROL:
540 err = mgmt_control(sk, msg, len);
541 goto done;
542 default:
543 err = -EINVAL;
544 goto done;
545 }
546
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200547 hdev = hci_pi(sk)->hdev;
548 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 err = -EBADFD;
550 goto done;
551 }
552
Marcel Holtmann7e21add2009-11-18 01:05:00 +0100553 if (!test_bit(HCI_UP, &hdev->flags)) {
554 err = -ENETDOWN;
555 goto done;
556 }
557
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200558 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
559 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 goto done;
561
562 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
563 err = -EFAULT;
564 goto drop;
565 }
566
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700567 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 skb_pull(skb, 1);
569 skb->dev = (void *) hdev;
570
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700571 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700572 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 u16 ogf = hci_opcode_ogf(opcode);
574 u16 ocf = hci_opcode_ocf(opcode);
575
576 if (((ogf > HCI_SFLT_MAX_OGF) ||
577 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
578 !capable(CAP_NET_RAW)) {
579 err = -EPERM;
580 goto drop;
581 }
582
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200583 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100585 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 } else {
587 skb_queue_tail(&hdev->cmd_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100588 tasklet_schedule(&hdev->cmd_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 }
590 } else {
591 if (!capable(CAP_NET_RAW)) {
592 err = -EPERM;
593 goto drop;
594 }
595
596 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100597 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 }
599
600 err = len;
601
602done:
603 release_sock(sk);
604 return err;
605
606drop:
607 kfree_skb(skb);
608 goto done;
609}
610
David S. Millerb7058842009-09-30 16:12:20 -0700611static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
613 struct hci_ufilter uf = { .opcode = 0 };
614 struct sock *sk = sock->sk;
615 int err = 0, opt = 0;
616
617 BT_DBG("sk %p, opt %d", sk, optname);
618
619 lock_sock(sk);
620
621 switch (optname) {
622 case HCI_DATA_DIR:
623 if (get_user(opt, (int __user *)optval)) {
624 err = -EFAULT;
625 break;
626 }
627
628 if (opt)
629 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
630 else
631 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
632 break;
633
634 case HCI_TIME_STAMP:
635 if (get_user(opt, (int __user *)optval)) {
636 err = -EFAULT;
637 break;
638 }
639
640 if (opt)
641 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
642 else
643 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
644 break;
645
646 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200647 {
648 struct hci_filter *f = &hci_pi(sk)->filter;
649
650 uf.type_mask = f->type_mask;
651 uf.opcode = f->opcode;
652 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
653 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
654 }
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 len = min_t(unsigned int, len, sizeof(uf));
657 if (copy_from_user(&uf, optval, len)) {
658 err = -EFAULT;
659 break;
660 }
661
662 if (!capable(CAP_NET_RAW)) {
663 uf.type_mask &= hci_sec_filter.type_mask;
664 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
665 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
666 }
667
668 {
669 struct hci_filter *f = &hci_pi(sk)->filter;
670
671 f->type_mask = uf.type_mask;
672 f->opcode = uf.opcode;
673 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
674 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
675 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900676 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 default:
679 err = -ENOPROTOOPT;
680 break;
681 }
682
683 release_sock(sk);
684 return err;
685}
686
687static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
688{
689 struct hci_ufilter uf;
690 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900691 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 if (get_user(len, optlen))
694 return -EFAULT;
695
696 switch (optname) {
697 case HCI_DATA_DIR:
698 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
699 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900700 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 opt = 0;
702
703 if (put_user(opt, optval))
704 return -EFAULT;
705 break;
706
707 case HCI_TIME_STAMP:
708 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
709 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900710 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 opt = 0;
712
713 if (put_user(opt, optval))
714 return -EFAULT;
715 break;
716
717 case HCI_FILTER:
718 {
719 struct hci_filter *f = &hci_pi(sk)->filter;
720
721 uf.type_mask = f->type_mask;
722 uf.opcode = f->opcode;
723 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
724 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
725 }
726
727 len = min_t(unsigned int, len, sizeof(uf));
728 if (copy_to_user(optval, &uf, len))
729 return -EFAULT;
730 break;
731
732 default:
733 return -ENOPROTOOPT;
734 break;
735 }
736
737 return 0;
738}
739
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800740static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 .family = PF_BLUETOOTH,
742 .owner = THIS_MODULE,
743 .release = hci_sock_release,
744 .bind = hci_sock_bind,
745 .getname = hci_sock_getname,
746 .sendmsg = hci_sock_sendmsg,
747 .recvmsg = hci_sock_recvmsg,
748 .ioctl = hci_sock_ioctl,
749 .poll = datagram_poll,
750 .listen = sock_no_listen,
751 .shutdown = sock_no_shutdown,
752 .setsockopt = hci_sock_setsockopt,
753 .getsockopt = hci_sock_getsockopt,
754 .connect = sock_no_connect,
755 .socketpair = sock_no_socketpair,
756 .accept = sock_no_accept,
757 .mmap = sock_no_mmap
758};
759
760static struct proto hci_sk_proto = {
761 .name = "HCI",
762 .owner = THIS_MODULE,
763 .obj_size = sizeof(struct hci_pinfo)
764};
765
Eric Paris3f378b62009-11-05 22:18:14 -0800766static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
767 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
769 struct sock *sk;
770
771 BT_DBG("sock %p", sock);
772
773 if (sock->type != SOCK_RAW)
774 return -ESOCKTNOSUPPORT;
775
776 sock->ops = &hci_sock_ops;
777
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700778 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 if (!sk)
780 return -ENOMEM;
781
782 sock_init_data(sock, sk);
783
784 sock_reset_flag(sk, SOCK_ZAPPED);
785
786 sk->sk_protocol = protocol;
787
788 sock->state = SS_UNCONNECTED;
789 sk->sk_state = BT_OPEN;
790
791 bt_sock_link(&hci_sk_list, sk);
792 return 0;
793}
794
795static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
796{
797 struct hci_dev *hdev = (struct hci_dev *) ptr;
798 struct hci_ev_si_device ev;
799
800 BT_DBG("hdev %s event %ld", hdev->name, event);
801
802 /* Send event to sockets */
803 ev.event = event;
804 ev.dev_id = hdev->id;
805 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
806
807 if (event == HCI_DEV_UNREG) {
808 struct sock *sk;
809 struct hlist_node *node;
810
811 /* Detach sockets from device */
812 read_lock(&hci_sk_list.lock);
813 sk_for_each(sk, node, &hci_sk_list.head) {
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700814 local_bh_disable();
815 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 if (hci_pi(sk)->hdev == hdev) {
817 hci_pi(sk)->hdev = NULL;
818 sk->sk_err = EPIPE;
819 sk->sk_state = BT_OPEN;
820 sk->sk_state_change(sk);
821
822 hci_dev_put(hdev);
823 }
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700824 bh_unlock_sock(sk);
825 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 }
827 read_unlock(&hci_sk_list.lock);
828 }
829
830 return NOTIFY_DONE;
831}
832
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +0000833static const struct net_proto_family hci_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 .family = PF_BLUETOOTH,
835 .owner = THIS_MODULE,
836 .create = hci_sock_create,
837};
838
839static struct notifier_block hci_sock_nblock = {
840 .notifier_call = hci_sock_dev_event
841};
842
843int __init hci_sock_init(void)
844{
845 int err;
846
847 err = proto_register(&hci_sk_proto, 0);
848 if (err < 0)
849 return err;
850
851 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
852 if (err < 0)
853 goto error;
854
855 hci_register_notifier(&hci_sock_nblock);
856
857 BT_INFO("HCI socket layer initialized");
858
859 return 0;
860
861error:
862 BT_ERR("HCI socket registration failed");
863 proto_unregister(&hci_sk_proto);
864 return err;
865}
866
Anand Gadiyarb7440a142011-02-22 12:43:09 +0530867void hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868{
869 if (bt_sock_unregister(BTPROTO_HCI) < 0)
870 BT_ERR("HCI socket unregistration failed");
871
872 hci_unregister_notifier(&hci_sock_nblock);
873
874 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875}
Johan Hedberg03811012010-12-08 00:21:06 +0200876
877module_param(enable_mgmt, bool, 0644);
878MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");