blob: 92d72b7fc13445f5464a1104dceb310b5fd24f7d [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
Brian Gixa68668b2011-08-11 15:49:36 -070052static int enable_mgmt = 1;
Johan Hedberg03811012010-12-08 00:21:06 +020053
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;
Brian Gixcfb536b2011-09-02 08:45:22 -0700331
332 err = hci_dev_open(arg);
333 if (!err || err == -EALREADY)
334 return 0;
335 else
336 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
338 case HCIDEVDOWN:
339 if (!capable(CAP_NET_ADMIN))
340 return -EACCES;
341 return hci_dev_close(arg);
342
343 case HCIDEVRESET:
344 if (!capable(CAP_NET_ADMIN))
345 return -EACCES;
346 return hci_dev_reset(arg);
347
348 case HCIDEVRESTAT:
349 if (!capable(CAP_NET_ADMIN))
350 return -EACCES;
351 return hci_dev_reset_stat(arg);
352
353 case HCISETSCAN:
354 case HCISETAUTH:
355 case HCISETENCRYPT:
356 case HCISETPTYPE:
357 case HCISETLINKPOL:
358 case HCISETLINKMODE:
359 case HCISETACLMTU:
360 case HCISETSCOMTU:
361 if (!capable(CAP_NET_ADMIN))
362 return -EACCES;
363 return hci_dev_cmd(cmd, argp);
364
365 case HCIINQUIRY:
366 return hci_inquiry(argp);
367
368 default:
369 lock_sock(sk);
370 err = hci_sock_bound_ioctl(sk, cmd, arg);
371 release_sock(sk);
372 return err;
373 }
374}
375
376static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
377{
Johan Hedberg03811012010-12-08 00:21:06 +0200378 struct sockaddr_hci haddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 struct sock *sk = sock->sk;
380 struct hci_dev *hdev = NULL;
Johan Hedberg03811012010-12-08 00:21:06 +0200381 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 BT_DBG("sock %p sk %p", sock, sk);
384
Johan Hedberg03811012010-12-08 00:21:06 +0200385 if (!addr)
386 return -EINVAL;
387
388 memset(&haddr, 0, sizeof(haddr));
389 len = min_t(unsigned int, sizeof(haddr), addr_len);
390 memcpy(&haddr, addr, len);
391
392 if (haddr.hci_family != AF_BLUETOOTH)
393 return -EINVAL;
394
Gustavo F. Padovan17f9cc32010-12-22 23:00:34 -0200395 if (haddr.hci_channel > HCI_CHANNEL_CONTROL)
396 return -EINVAL;
397
398 if (haddr.hci_channel == HCI_CHANNEL_CONTROL && !enable_mgmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 return -EINVAL;
400
401 lock_sock(sk);
402
Johan Hedberg03811012010-12-08 00:21:06 +0200403 if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 err = -EALREADY;
405 goto done;
406 }
407
Johan Hedberg03811012010-12-08 00:21:06 +0200408 if (haddr.hci_dev != HCI_DEV_NONE) {
409 hdev = hci_dev_get(haddr.hci_dev);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200410 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 err = -ENODEV;
412 goto done;
413 }
414
415 atomic_inc(&hdev->promisc);
416 }
417
Johan Hedberg03811012010-12-08 00:21:06 +0200418 hci_pi(sk)->channel = haddr.hci_channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 hci_pi(sk)->hdev = hdev;
420 sk->sk_state = BT_BOUND;
421
422done:
423 release_sock(sk);
424 return err;
425}
426
427static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
428{
429 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
430 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100431 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
433 BT_DBG("sock %p sk %p", sock, sk);
434
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100435 if (!hdev)
436 return -EBADFD;
437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 lock_sock(sk);
439
440 *addr_len = sizeof(*haddr);
441 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100442 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444 release_sock(sk);
445 return 0;
446}
447
448static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
449{
450 __u32 mask = hci_pi(sk)->cmsg_mask;
451
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700452 if (mask & HCI_CMSG_DIR) {
453 int incoming = bt_cb(skb)->incoming;
454 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700457 if (mask & HCI_CMSG_TSTAMP) {
Johann Felix Sodenf6e623a2010-02-15 22:23:48 +0100458#ifdef CONFIG_COMPAT
459 struct compat_timeval ctv;
460#endif
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700461 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200462 void *data;
463 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700464
465 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200466
David S. Miller1da97f82007-09-12 14:10:58 +0200467 data = &tv;
468 len = sizeof(tv);
469#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200470 if (msg->msg_flags & MSG_CMSG_COMPAT) {
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200471 ctv.tv_sec = tv.tv_sec;
472 ctv.tv_usec = tv.tv_usec;
473 data = &ctv;
474 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200475 }
David S. Miller1da97f82007-09-12 14:10:58 +0200476#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200477
478 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900481
482static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 struct msghdr *msg, size_t len, int flags)
484{
485 int noblock = flags & MSG_DONTWAIT;
486 struct sock *sk = sock->sk;
487 struct sk_buff *skb;
488 int copied, err;
489
490 BT_DBG("sock %p, sk %p", sock, sk);
491
492 if (flags & (MSG_OOB))
493 return -EOPNOTSUPP;
494
495 if (sk->sk_state == BT_CLOSED)
496 return 0;
497
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200498 skb = skb_recv_datagram(sk, flags, noblock, &err);
499 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 return err;
501
502 msg->msg_namelen = 0;
503
504 copied = skb->len;
505 if (len < copied) {
506 msg->msg_flags |= MSG_TRUNC;
507 copied = len;
508 }
509
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300510 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
512
513 hci_sock_cmsg(sk, msg, skb);
514
515 skb_free_datagram(sk, skb);
516
517 return err ? : copied;
518}
519
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900520static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 struct msghdr *msg, size_t len)
522{
523 struct sock *sk = sock->sk;
524 struct hci_dev *hdev;
525 struct sk_buff *skb;
526 int err;
527
528 BT_DBG("sock %p sk %p", sock, sk);
529
530 if (msg->msg_flags & MSG_OOB)
531 return -EOPNOTSUPP;
532
533 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
534 return -EINVAL;
535
536 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
537 return -EINVAL;
538
539 lock_sock(sk);
540
Johan Hedberg03811012010-12-08 00:21:06 +0200541 switch (hci_pi(sk)->channel) {
542 case HCI_CHANNEL_RAW:
543 break;
544 case HCI_CHANNEL_CONTROL:
545 err = mgmt_control(sk, msg, len);
546 goto done;
547 default:
548 err = -EINVAL;
549 goto done;
550 }
551
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200552 hdev = hci_pi(sk)->hdev;
553 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 err = -EBADFD;
555 goto done;
556 }
557
Marcel Holtmann7e21add2009-11-18 01:05:00 +0100558 if (!test_bit(HCI_UP, &hdev->flags)) {
559 err = -ENETDOWN;
560 goto done;
561 }
562
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200563 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
564 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 goto done;
566
567 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
568 err = -EFAULT;
569 goto drop;
570 }
571
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700572 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 skb_pull(skb, 1);
574 skb->dev = (void *) hdev;
575
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700576 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700577 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 u16 ogf = hci_opcode_ogf(opcode);
579 u16 ocf = hci_opcode_ocf(opcode);
580
581 if (((ogf > HCI_SFLT_MAX_OGF) ||
582 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
583 !capable(CAP_NET_RAW)) {
584 err = -EPERM;
585 goto drop;
586 }
587
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200588 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100590 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 } else {
592 skb_queue_tail(&hdev->cmd_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100593 tasklet_schedule(&hdev->cmd_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 }
595 } else {
596 if (!capable(CAP_NET_RAW)) {
597 err = -EPERM;
598 goto drop;
599 }
600
601 skb_queue_tail(&hdev->raw_q, skb);
Marcel Holtmannc78ae282009-11-18 01:02:54 +0100602 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 }
604
605 err = len;
606
607done:
608 release_sock(sk);
609 return err;
610
611drop:
612 kfree_skb(skb);
613 goto done;
614}
615
David S. Millerb7058842009-09-30 16:12:20 -0700616static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617{
618 struct hci_ufilter uf = { .opcode = 0 };
619 struct sock *sk = sock->sk;
620 int err = 0, opt = 0;
621
622 BT_DBG("sk %p, opt %d", sk, optname);
623
624 lock_sock(sk);
625
626 switch (optname) {
627 case HCI_DATA_DIR:
628 if (get_user(opt, (int __user *)optval)) {
629 err = -EFAULT;
630 break;
631 }
632
633 if (opt)
634 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
635 else
636 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
637 break;
638
639 case HCI_TIME_STAMP:
640 if (get_user(opt, (int __user *)optval)) {
641 err = -EFAULT;
642 break;
643 }
644
645 if (opt)
646 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
647 else
648 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
649 break;
650
651 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200652 {
653 struct hci_filter *f = &hci_pi(sk)->filter;
654
655 uf.type_mask = f->type_mask;
656 uf.opcode = f->opcode;
657 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
658 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
659 }
660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 len = min_t(unsigned int, len, sizeof(uf));
662 if (copy_from_user(&uf, optval, len)) {
663 err = -EFAULT;
664 break;
665 }
666
667 if (!capable(CAP_NET_RAW)) {
668 uf.type_mask &= hci_sec_filter.type_mask;
669 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
670 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
671 }
672
673 {
674 struct hci_filter *f = &hci_pi(sk)->filter;
675
676 f->type_mask = uf.type_mask;
677 f->opcode = uf.opcode;
678 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
679 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
680 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900681 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 default:
684 err = -ENOPROTOOPT;
685 break;
686 }
687
688 release_sock(sk);
689 return err;
690}
691
692static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
693{
694 struct hci_ufilter uf;
695 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900696 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
698 if (get_user(len, optlen))
699 return -EFAULT;
700
701 switch (optname) {
702 case HCI_DATA_DIR:
703 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
704 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900705 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 opt = 0;
707
708 if (put_user(opt, optval))
709 return -EFAULT;
710 break;
711
712 case HCI_TIME_STAMP:
713 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
714 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900715 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 opt = 0;
717
718 if (put_user(opt, optval))
719 return -EFAULT;
720 break;
721
722 case HCI_FILTER:
723 {
724 struct hci_filter *f = &hci_pi(sk)->filter;
725
726 uf.type_mask = f->type_mask;
727 uf.opcode = f->opcode;
728 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
729 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
730 }
731
732 len = min_t(unsigned int, len, sizeof(uf));
733 if (copy_to_user(optval, &uf, len))
734 return -EFAULT;
735 break;
736
737 default:
738 return -ENOPROTOOPT;
739 break;
740 }
741
742 return 0;
743}
744
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800745static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 .family = PF_BLUETOOTH,
747 .owner = THIS_MODULE,
748 .release = hci_sock_release,
749 .bind = hci_sock_bind,
750 .getname = hci_sock_getname,
751 .sendmsg = hci_sock_sendmsg,
752 .recvmsg = hci_sock_recvmsg,
753 .ioctl = hci_sock_ioctl,
754 .poll = datagram_poll,
755 .listen = sock_no_listen,
756 .shutdown = sock_no_shutdown,
757 .setsockopt = hci_sock_setsockopt,
758 .getsockopt = hci_sock_getsockopt,
759 .connect = sock_no_connect,
760 .socketpair = sock_no_socketpair,
761 .accept = sock_no_accept,
762 .mmap = sock_no_mmap
763};
764
765static struct proto hci_sk_proto = {
766 .name = "HCI",
767 .owner = THIS_MODULE,
768 .obj_size = sizeof(struct hci_pinfo)
769};
770
Eric Paris3f378b62009-11-05 22:18:14 -0800771static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
772 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773{
774 struct sock *sk;
775
776 BT_DBG("sock %p", sock);
777
778 if (sock->type != SOCK_RAW)
779 return -ESOCKTNOSUPPORT;
780
781 sock->ops = &hci_sock_ops;
782
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700783 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 if (!sk)
785 return -ENOMEM;
786
787 sock_init_data(sock, sk);
788
789 sock_reset_flag(sk, SOCK_ZAPPED);
790
791 sk->sk_protocol = protocol;
792
793 sock->state = SS_UNCONNECTED;
794 sk->sk_state = BT_OPEN;
795
796 bt_sock_link(&hci_sk_list, sk);
797 return 0;
798}
799
800static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
801{
802 struct hci_dev *hdev = (struct hci_dev *) ptr;
803 struct hci_ev_si_device ev;
804
805 BT_DBG("hdev %s event %ld", hdev->name, event);
806
807 /* Send event to sockets */
808 ev.event = event;
809 ev.dev_id = hdev->id;
810 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
811
812 if (event == HCI_DEV_UNREG) {
813 struct sock *sk;
814 struct hlist_node *node;
815
816 /* Detach sockets from device */
817 read_lock(&hci_sk_list.lock);
818 sk_for_each(sk, node, &hci_sk_list.head) {
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700819 local_bh_disable();
820 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 if (hci_pi(sk)->hdev == hdev) {
822 hci_pi(sk)->hdev = NULL;
823 sk->sk_err = EPIPE;
824 sk->sk_state = BT_OPEN;
825 sk->sk_state_change(sk);
826
827 hci_dev_put(hdev);
828 }
Satyam Sharma4ce61d12007-05-16 23:50:16 -0700829 bh_unlock_sock(sk);
830 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 }
832 read_unlock(&hci_sk_list.lock);
833 }
834
835 return NOTIFY_DONE;
836}
837
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +0000838static const struct net_proto_family hci_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 .family = PF_BLUETOOTH,
840 .owner = THIS_MODULE,
841 .create = hci_sock_create,
842};
843
844static struct notifier_block hci_sock_nblock = {
845 .notifier_call = hci_sock_dev_event
846};
847
848int __init hci_sock_init(void)
849{
850 int err;
851
852 err = proto_register(&hci_sk_proto, 0);
853 if (err < 0)
854 return err;
855
856 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
857 if (err < 0)
858 goto error;
859
860 hci_register_notifier(&hci_sock_nblock);
861
862 BT_INFO("HCI socket layer initialized");
863
864 return 0;
865
866error:
867 BT_ERR("HCI socket registration failed");
868 proto_unregister(&hci_sk_proto);
869 return err;
870}
871
Anand Gadiyarb7440a142011-02-22 12:43:09 +0530872void hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873{
874 if (bt_sock_unregister(BTPROTO_HCI) < 0)
875 BT_ERR("HCI socket unregistration failed");
876
877 hci_unregister_notifier(&hci_sock_nblock);
878
879 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880}
Johan Hedberg03811012010-12-08 00:21:06 +0200881
882module_param(enable_mgmt, bool, 0644);
883MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");