blob: 14727cb43f6339f5f948f03285aca1fd78287d8f [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
Rusty Russelleb939922011-12-19 14:08:01 +000052static bool enable_mgmt;
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 */
Marcel Holtmann470fe1b2012-02-20 14:50:30 +010088void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070089{
90 struct sock *sk;
91 struct hlist_node *node;
Marcel Holtmanne0edf372012-02-20 14:50:36 +010092 struct sk_buff *skb_copy = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94 BT_DBG("hdev %p len %d", hdev, skb->len);
95
96 read_lock(&hci_sk_list.lock);
Marcel Holtmann470fe1b2012-02-20 14:50:30 +010097
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 sk_for_each(sk, node, &hci_sk_list.head) {
99 struct hci_filter *flt;
100 struct sk_buff *nskb;
101
102 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
103 continue;
104
105 /* Don't send frame to the socket it came from */
106 if (skb->sk == sk)
107 continue;
108
Marcel Holtmann470fe1b2012-02-20 14:50:30 +0100109 if (hci_pi(sk)->channel != HCI_CHANNEL_RAW)
Johan Hedberga40c4062010-12-08 00:21:07 +0200110 continue;
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 /* Apply filter */
113 flt = &hci_pi(sk)->filter;
114
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700115 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
116 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 continue;
118
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700119 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
121
122 if (!hci_test_bit(evt, &flt->event_mask))
123 continue;
124
David S. Miller4498c802006-11-21 16:17:41 -0800125 if (flt->opcode &&
126 ((evt == HCI_EV_CMD_COMPLETE &&
127 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800128 get_unaligned((__le16 *)(skb->data + 3))) ||
David S. Miller4498c802006-11-21 16:17:41 -0800129 (evt == HCI_EV_CMD_STATUS &&
130 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800131 get_unaligned((__le16 *)(skb->data + 4)))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 continue;
133 }
134
Marcel Holtmanne0edf372012-02-20 14:50:36 +0100135 if (!skb_copy) {
136 /* Create a private copy with headroom */
137 skb_copy = __pskb_copy(skb, 1, GFP_ATOMIC);
138 if (!skb_copy)
139 continue;
140
141 /* Put type byte before the data */
142 memcpy(skb_push(skb_copy, 1), &bt_cb(skb)->pkt_type, 1);
143 }
144
145 nskb = skb_clone(skb_copy, GFP_ATOMIC);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200146 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 continue;
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 if (sock_queue_rcv_skb(sk, nskb))
150 kfree_skb(nskb);
151 }
Marcel Holtmann470fe1b2012-02-20 14:50:30 +0100152
153 read_unlock(&hci_sk_list.lock);
Marcel Holtmanne0edf372012-02-20 14:50:36 +0100154
155 kfree_skb(skb_copy);
Marcel Holtmann470fe1b2012-02-20 14:50:30 +0100156}
157
158/* Send frame to control socket */
159void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk)
160{
161 struct sock *sk;
162 struct hlist_node *node;
163
164 BT_DBG("len %d", skb->len);
165
166 read_lock(&hci_sk_list.lock);
167
168 sk_for_each(sk, node, &hci_sk_list.head) {
169 struct sk_buff *nskb;
170
171 /* Skip the original socket */
172 if (sk == skip_sk)
173 continue;
174
175 if (sk->sk_state != BT_BOUND)
176 continue;
177
178 if (hci_pi(sk)->channel != HCI_CHANNEL_CONTROL)
179 continue;
180
181 nskb = skb_clone(skb, GFP_ATOMIC);
182 if (!nskb)
183 continue;
184
185 if (sock_queue_rcv_skb(sk, nskb))
186 kfree_skb(nskb);
187 }
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 read_unlock(&hci_sk_list.lock);
190}
191
Marcel Holtmann040030e2012-02-20 14:50:37 +0100192/* Generate internal stack event */
193static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
194{
195 struct hci_event_hdr *hdr;
196 struct hci_ev_stack_internal *ev;
197 struct sk_buff *skb;
198
199 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
200 if (!skb)
201 return;
202
203 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
204 hdr->evt = HCI_EV_STACK_INTERNAL;
205 hdr->plen = sizeof(*ev) + dlen;
206
207 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
208 ev->type = type;
209 memcpy(ev->data, data, dlen);
210
211 bt_cb(skb)->incoming = 1;
212 __net_timestamp(skb);
213
214 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
215 skb->dev = (void *) hdev;
216 hci_send_to_sock(hdev, skb);
217 kfree_skb(skb);
218}
219
220void hci_sock_dev_event(struct hci_dev *hdev, int event)
221{
222 struct hci_ev_si_device ev;
223
224 BT_DBG("hdev %s event %d", hdev->name, event);
225
226 /* Send event to sockets */
227 ev.event = event;
228 ev.dev_id = hdev->id;
229 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
230
231 if (event == HCI_DEV_UNREG) {
232 struct sock *sk;
233 struct hlist_node *node;
234
235 /* Detach sockets from device */
236 read_lock(&hci_sk_list.lock);
237 sk_for_each(sk, node, &hci_sk_list.head) {
238 bh_lock_sock_nested(sk);
239 if (hci_pi(sk)->hdev == hdev) {
240 hci_pi(sk)->hdev = NULL;
241 sk->sk_err = EPIPE;
242 sk->sk_state = BT_OPEN;
243 sk->sk_state_change(sk);
244
245 hci_dev_put(hdev);
246 }
247 bh_unlock_sock(sk);
248 }
249 read_unlock(&hci_sk_list.lock);
250 }
251}
252
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253static int hci_sock_release(struct socket *sock)
254{
255 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100256 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 BT_DBG("sock %p sk %p", sock, sk);
259
260 if (!sk)
261 return 0;
262
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100263 hdev = hci_pi(sk)->hdev;
264
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 bt_sock_unlink(&hci_sk_list, sk);
266
267 if (hdev) {
268 atomic_dec(&hdev->promisc);
269 hci_dev_put(hdev);
270 }
271
272 sock_orphan(sk);
273
274 skb_queue_purge(&sk->sk_receive_queue);
275 skb_queue_purge(&sk->sk_write_queue);
276
277 sock_put(sk);
278 return 0;
279}
280
Antti Julkub2a66aa2011-06-15 12:01:14 +0300281static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
Johan Hedbergf0358562010-05-18 13:20:32 +0200282{
283 bdaddr_t bdaddr;
Antti Julku5e762442011-08-25 16:48:02 +0300284 int err;
Johan Hedbergf0358562010-05-18 13:20:32 +0200285
286 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
287 return -EFAULT;
288
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300289 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +0300290
Johan Hedberg88c1fe42012-02-09 15:56:11 +0200291 err = hci_blacklist_add(hdev, &bdaddr, 0);
Antti Julku5e762442011-08-25 16:48:02 +0300292
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300293 hci_dev_unlock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +0300294
295 return err;
Johan Hedbergf0358562010-05-18 13:20:32 +0200296}
297
Antti Julkub2a66aa2011-06-15 12:01:14 +0300298static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
Johan Hedbergf0358562010-05-18 13:20:32 +0200299{
300 bdaddr_t bdaddr;
Antti Julku5e762442011-08-25 16:48:02 +0300301 int err;
Johan Hedbergf0358562010-05-18 13:20:32 +0200302
303 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
304 return -EFAULT;
305
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300306 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +0300307
Johan Hedberg88c1fe42012-02-09 15:56:11 +0200308 err = hci_blacklist_del(hdev, &bdaddr, 0);
Antti Julku5e762442011-08-25 16:48:02 +0300309
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300310 hci_dev_unlock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +0300311
312 return err;
Johan Hedbergf0358562010-05-18 13:20:32 +0200313}
314
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900315/* Ioctls that require bound socket */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
317{
318 struct hci_dev *hdev = hci_pi(sk)->hdev;
319
320 if (!hdev)
321 return -EBADFD;
322
323 switch (cmd) {
324 case HCISETRAW:
325 if (!capable(CAP_NET_ADMIN))
326 return -EACCES;
327
328 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
329 return -EPERM;
330
331 if (arg)
332 set_bit(HCI_RAW, &hdev->flags);
333 else
334 clear_bit(HCI_RAW, &hdev->flags);
335
336 return 0;
337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 case HCIGETCONNINFO:
Marcel Holtmann40be4922008-07-14 20:13:50 +0200339 return hci_get_conn_info(hdev, (void __user *) arg);
340
341 case HCIGETAUTHINFO:
342 return hci_get_auth_info(hdev, (void __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
Johan Hedbergf0358562010-05-18 13:20:32 +0200344 case HCIBLOCKADDR:
345 if (!capable(CAP_NET_ADMIN))
346 return -EACCES;
Antti Julkub2a66aa2011-06-15 12:01:14 +0300347 return hci_sock_blacklist_add(hdev, (void __user *) arg);
Johan Hedbergf0358562010-05-18 13:20:32 +0200348
349 case HCIUNBLOCKADDR:
350 if (!capable(CAP_NET_ADMIN))
351 return -EACCES;
Antti Julkub2a66aa2011-06-15 12:01:14 +0300352 return hci_sock_blacklist_del(hdev, (void __user *) arg);
Johan Hedbergf0358562010-05-18 13:20:32 +0200353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 default:
355 if (hdev->ioctl)
356 return hdev->ioctl(hdev, cmd, arg);
357 return -EINVAL;
358 }
359}
360
361static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
362{
363 struct sock *sk = sock->sk;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200364 void __user *argp = (void __user *) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 int err;
366
367 BT_DBG("cmd %x arg %lx", cmd, arg);
368
369 switch (cmd) {
370 case HCIGETDEVLIST:
371 return hci_get_dev_list(argp);
372
373 case HCIGETDEVINFO:
374 return hci_get_dev_info(argp);
375
376 case HCIGETCONNLIST:
377 return hci_get_conn_list(argp);
378
379 case HCIDEVUP:
380 if (!capable(CAP_NET_ADMIN))
381 return -EACCES;
382 return hci_dev_open(arg);
383
384 case HCIDEVDOWN:
385 if (!capable(CAP_NET_ADMIN))
386 return -EACCES;
387 return hci_dev_close(arg);
388
389 case HCIDEVRESET:
390 if (!capable(CAP_NET_ADMIN))
391 return -EACCES;
392 return hci_dev_reset(arg);
393
394 case HCIDEVRESTAT:
395 if (!capable(CAP_NET_ADMIN))
396 return -EACCES;
397 return hci_dev_reset_stat(arg);
398
399 case HCISETSCAN:
400 case HCISETAUTH:
401 case HCISETENCRYPT:
402 case HCISETPTYPE:
403 case HCISETLINKPOL:
404 case HCISETLINKMODE:
405 case HCISETACLMTU:
406 case HCISETSCOMTU:
407 if (!capable(CAP_NET_ADMIN))
408 return -EACCES;
409 return hci_dev_cmd(cmd, argp);
410
411 case HCIINQUIRY:
412 return hci_inquiry(argp);
413
414 default:
415 lock_sock(sk);
416 err = hci_sock_bound_ioctl(sk, cmd, arg);
417 release_sock(sk);
418 return err;
419 }
420}
421
422static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
423{
Johan Hedberg03811012010-12-08 00:21:06 +0200424 struct sockaddr_hci haddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 struct sock *sk = sock->sk;
426 struct hci_dev *hdev = NULL;
Johan Hedberg03811012010-12-08 00:21:06 +0200427 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 BT_DBG("sock %p sk %p", sock, sk);
430
Johan Hedberg03811012010-12-08 00:21:06 +0200431 if (!addr)
432 return -EINVAL;
433
434 memset(&haddr, 0, sizeof(haddr));
435 len = min_t(unsigned int, sizeof(haddr), addr_len);
436 memcpy(&haddr, addr, len);
437
438 if (haddr.hci_family != AF_BLUETOOTH)
439 return -EINVAL;
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 lock_sock(sk);
442
Marcel Holtmann7cc2ade2012-02-20 14:50:35 +0100443 if (sk->sk_state == BT_BOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 err = -EALREADY;
445 goto done;
446 }
447
Marcel Holtmann7cc2ade2012-02-20 14:50:35 +0100448 switch (haddr.hci_channel) {
449 case HCI_CHANNEL_RAW:
450 if (hci_pi(sk)->hdev) {
451 err = -EALREADY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 goto done;
453 }
454
Marcel Holtmann7cc2ade2012-02-20 14:50:35 +0100455 if (haddr.hci_dev != HCI_DEV_NONE) {
456 hdev = hci_dev_get(haddr.hci_dev);
457 if (!hdev) {
458 err = -ENODEV;
459 goto done;
460 }
461
462 atomic_inc(&hdev->promisc);
463 }
464
465 hci_pi(sk)->hdev = hdev;
466 break;
467
468 case HCI_CHANNEL_CONTROL:
469 if (haddr.hci_dev != HCI_DEV_NONE || !enable_mgmt) {
470 err = -EINVAL;
471 goto done;
472 }
473
474 set_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags);
475 break;
476
477 default:
478 err = -EINVAL;
479 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 }
481
Marcel Holtmann7cc2ade2012-02-20 14:50:35 +0100482
Johan Hedberg03811012010-12-08 00:21:06 +0200483 hci_pi(sk)->channel = haddr.hci_channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 sk->sk_state = BT_BOUND;
485
486done:
487 release_sock(sk);
488 return err;
489}
490
491static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
492{
493 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
494 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100495 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 BT_DBG("sock %p sk %p", sock, sk);
498
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100499 if (!hdev)
500 return -EBADFD;
501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 lock_sock(sk);
503
504 *addr_len = sizeof(*haddr);
505 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100506 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 release_sock(sk);
509 return 0;
510}
511
512static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
513{
514 __u32 mask = hci_pi(sk)->cmsg_mask;
515
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700516 if (mask & HCI_CMSG_DIR) {
517 int incoming = bt_cb(skb)->incoming;
518 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700521 if (mask & HCI_CMSG_TSTAMP) {
Johann Felix Sodenf6e623a2010-02-15 22:23:48 +0100522#ifdef CONFIG_COMPAT
523 struct compat_timeval ctv;
524#endif
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700525 struct timeval tv;
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200526 void *data;
527 int len;
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700528
529 skb_get_timestamp(skb, &tv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200530
David S. Miller1da97f82007-09-12 14:10:58 +0200531 data = &tv;
532 len = sizeof(tv);
533#ifdef CONFIG_COMPAT
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200534 if (msg->msg_flags & MSG_CMSG_COMPAT) {
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200535 ctv.tv_sec = tv.tv_sec;
536 ctv.tv_usec = tv.tv_usec;
537 data = &ctv;
538 len = sizeof(ctv);
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200539 }
David S. Miller1da97f82007-09-12 14:10:58 +0200540#endif
Marcel Holtmann767c5eb2007-09-09 08:39:34 +0200541
542 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900545
546static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 struct msghdr *msg, size_t len, int flags)
548{
549 int noblock = flags & MSG_DONTWAIT;
550 struct sock *sk = sock->sk;
551 struct sk_buff *skb;
552 int copied, err;
553
554 BT_DBG("sock %p, sk %p", sock, sk);
555
556 if (flags & (MSG_OOB))
557 return -EOPNOTSUPP;
558
559 if (sk->sk_state == BT_CLOSED)
560 return 0;
561
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200562 skb = skb_recv_datagram(sk, flags, noblock, &err);
563 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 return err;
565
566 msg->msg_namelen = 0;
567
568 copied = skb->len;
569 if (len < copied) {
570 msg->msg_flags |= MSG_TRUNC;
571 copied = len;
572 }
573
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300574 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
576
Marcel Holtmann3a208622012-02-20 14:50:34 +0100577 switch (hci_pi(sk)->channel) {
578 case HCI_CHANNEL_RAW:
579 hci_sock_cmsg(sk, msg, skb);
580 break;
581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
583 skb_free_datagram(sk, skb);
584
585 return err ? : copied;
586}
587
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900588static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 struct msghdr *msg, size_t len)
590{
591 struct sock *sk = sock->sk;
592 struct hci_dev *hdev;
593 struct sk_buff *skb;
594 int err;
595
596 BT_DBG("sock %p sk %p", sock, sk);
597
598 if (msg->msg_flags & MSG_OOB)
599 return -EOPNOTSUPP;
600
601 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
602 return -EINVAL;
603
604 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
605 return -EINVAL;
606
607 lock_sock(sk);
608
Johan Hedberg03811012010-12-08 00:21:06 +0200609 switch (hci_pi(sk)->channel) {
610 case HCI_CHANNEL_RAW:
611 break;
612 case HCI_CHANNEL_CONTROL:
613 err = mgmt_control(sk, msg, len);
614 goto done;
615 default:
616 err = -EINVAL;
617 goto done;
618 }
619
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200620 hdev = hci_pi(sk)->hdev;
621 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 err = -EBADFD;
623 goto done;
624 }
625
Marcel Holtmann7e21add2009-11-18 01:05:00 +0100626 if (!test_bit(HCI_UP, &hdev->flags)) {
627 err = -ENETDOWN;
628 goto done;
629 }
630
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200631 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
632 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 goto done;
634
635 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
636 err = -EFAULT;
637 goto drop;
638 }
639
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700640 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 skb_pull(skb, 1);
642 skb->dev = (void *) hdev;
643
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700644 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Harvey Harrison83985312008-05-02 16:25:46 -0700645 u16 opcode = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 u16 ogf = hci_opcode_ogf(opcode);
647 u16 ocf = hci_opcode_ocf(opcode);
648
649 if (((ogf > HCI_SFLT_MAX_OGF) ||
650 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
651 !capable(CAP_NET_RAW)) {
652 err = -EPERM;
653 goto drop;
654 }
655
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200656 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 skb_queue_tail(&hdev->raw_q, skb);
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -0200658 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 } else {
660 skb_queue_tail(&hdev->cmd_q, skb);
Gustavo F. Padovanc347b762011-12-14 23:53:47 -0200661 queue_work(hdev->workqueue, &hdev->cmd_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 }
663 } else {
664 if (!capable(CAP_NET_RAW)) {
665 err = -EPERM;
666 goto drop;
667 }
668
669 skb_queue_tail(&hdev->raw_q, skb);
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -0200670 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 }
672
673 err = len;
674
675done:
676 release_sock(sk);
677 return err;
678
679drop:
680 kfree_skb(skb);
681 goto done;
682}
683
David S. Millerb7058842009-09-30 16:12:20 -0700684static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
686 struct hci_ufilter uf = { .opcode = 0 };
687 struct sock *sk = sock->sk;
688 int err = 0, opt = 0;
689
690 BT_DBG("sk %p, opt %d", sk, optname);
691
692 lock_sock(sk);
693
Marcel Holtmann2f39cdb2012-02-20 14:50:32 +0100694 if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
695 err = -EINVAL;
696 goto done;
697 }
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 switch (optname) {
700 case HCI_DATA_DIR:
701 if (get_user(opt, (int __user *)optval)) {
702 err = -EFAULT;
703 break;
704 }
705
706 if (opt)
707 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
708 else
709 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
710 break;
711
712 case HCI_TIME_STAMP:
713 if (get_user(opt, (int __user *)optval)) {
714 err = -EFAULT;
715 break;
716 }
717
718 if (opt)
719 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
720 else
721 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
722 break;
723
724 case HCI_FILTER:
Marcel Holtmann0878b662007-05-05 00:35:59 +0200725 {
726 struct hci_filter *f = &hci_pi(sk)->filter;
727
728 uf.type_mask = f->type_mask;
729 uf.opcode = f->opcode;
730 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
731 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
732 }
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 len = min_t(unsigned int, len, sizeof(uf));
735 if (copy_from_user(&uf, optval, len)) {
736 err = -EFAULT;
737 break;
738 }
739
740 if (!capable(CAP_NET_RAW)) {
741 uf.type_mask &= hci_sec_filter.type_mask;
742 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
743 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
744 }
745
746 {
747 struct hci_filter *f = &hci_pi(sk)->filter;
748
749 f->type_mask = uf.type_mask;
750 f->opcode = uf.opcode;
751 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
752 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
753 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900754 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
756 default:
757 err = -ENOPROTOOPT;
758 break;
759 }
760
Marcel Holtmann2f39cdb2012-02-20 14:50:32 +0100761done:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 release_sock(sk);
763 return err;
764}
765
766static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
767{
768 struct hci_ufilter uf;
769 struct sock *sk = sock->sk;
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100770 int len, opt, err = 0;
771
772 BT_DBG("sk %p, opt %d", sk, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 if (get_user(len, optlen))
775 return -EFAULT;
776
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100777 lock_sock(sk);
778
779 if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
780 err = -EINVAL;
781 goto done;
782 }
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 switch (optname) {
785 case HCI_DATA_DIR:
786 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
787 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900788 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 opt = 0;
790
791 if (put_user(opt, optval))
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100792 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 break;
794
795 case HCI_TIME_STAMP:
796 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
797 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900798 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 opt = 0;
800
801 if (put_user(opt, optval))
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100802 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 break;
804
805 case HCI_FILTER:
806 {
807 struct hci_filter *f = &hci_pi(sk)->filter;
808
809 uf.type_mask = f->type_mask;
810 uf.opcode = f->opcode;
811 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
812 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
813 }
814
815 len = min_t(unsigned int, len, sizeof(uf));
816 if (copy_to_user(optval, &uf, len))
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100817 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 break;
819
820 default:
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100821 err = -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 break;
823 }
824
Marcel Holtmanncedc5462012-02-20 14:50:33 +0100825done:
826 release_sock(sk);
827 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800830static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 .family = PF_BLUETOOTH,
832 .owner = THIS_MODULE,
833 .release = hci_sock_release,
834 .bind = hci_sock_bind,
835 .getname = hci_sock_getname,
836 .sendmsg = hci_sock_sendmsg,
837 .recvmsg = hci_sock_recvmsg,
838 .ioctl = hci_sock_ioctl,
839 .poll = datagram_poll,
840 .listen = sock_no_listen,
841 .shutdown = sock_no_shutdown,
842 .setsockopt = hci_sock_setsockopt,
843 .getsockopt = hci_sock_getsockopt,
844 .connect = sock_no_connect,
845 .socketpair = sock_no_socketpair,
846 .accept = sock_no_accept,
847 .mmap = sock_no_mmap
848};
849
850static struct proto hci_sk_proto = {
851 .name = "HCI",
852 .owner = THIS_MODULE,
853 .obj_size = sizeof(struct hci_pinfo)
854};
855
Eric Paris3f378b62009-11-05 22:18:14 -0800856static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
857 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858{
859 struct sock *sk;
860
861 BT_DBG("sock %p", sock);
862
863 if (sock->type != SOCK_RAW)
864 return -ESOCKTNOSUPPORT;
865
866 sock->ops = &hci_sock_ops;
867
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700868 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 if (!sk)
870 return -ENOMEM;
871
872 sock_init_data(sock, sk);
873
874 sock_reset_flag(sk, SOCK_ZAPPED);
875
876 sk->sk_protocol = protocol;
877
878 sock->state = SS_UNCONNECTED;
879 sk->sk_state = BT_OPEN;
880
881 bt_sock_link(&hci_sk_list, sk);
882 return 0;
883}
884
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +0000885static const struct net_proto_family hci_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 .family = PF_BLUETOOTH,
887 .owner = THIS_MODULE,
888 .create = hci_sock_create,
889};
890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891int __init hci_sock_init(void)
892{
893 int err;
894
895 err = proto_register(&hci_sk_proto, 0);
896 if (err < 0)
897 return err;
898
899 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
900 if (err < 0)
901 goto error;
902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 BT_INFO("HCI socket layer initialized");
904
905 return 0;
906
907error:
908 BT_ERR("HCI socket registration failed");
909 proto_unregister(&hci_sk_proto);
910 return err;
911}
912
Anand Gadiyarb7440a142011-02-22 12:43:09 +0530913void hci_sock_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914{
915 if (bt_sock_unregister(BTPROTO_HCI) < 0)
916 BT_ERR("HCI socket unregistration failed");
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 proto_unregister(&hci_sk_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919}
Johan Hedberg03811012010-12-08 00:21:06 +0200920
921module_param(enable_mgmt, bool, 0644);
922MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");