blob: f928d2b2a17dac5c81a7660108e895b5640a1263 [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>
40#include <linux/socket.h>
41#include <linux/ioctl.h>
42#include <net/sock.h>
43
44#include <asm/system.h>
45#include <asm/uaccess.h>
46#include <asm/unaligned.h>
47
48#include <net/bluetooth/bluetooth.h>
49#include <net/bluetooth/hci_core.h>
50
51#ifndef CONFIG_BT_HCI_SOCK_DEBUG
52#undef BT_DBG
53#define BT_DBG(D...)
54#endif
55
56/* ----- HCI socket interface ----- */
57
58static inline int hci_test_bit(int nr, void *addr)
59{
60 return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
61}
62
63/* Security filter */
64static struct hci_sec_filter hci_sec_filter = {
65 /* Packet types */
66 0x10,
67 /* Events */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020068 { 0x1000d9fe, 0x0000b00c },
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 /* Commands */
70 {
71 { 0x0 },
72 /* OGF_LINK_CTL */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020073 { 0xbe000006, 0x00000001, 0x000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 /* OGF_LINK_POLICY */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020075 { 0x00005200, 0x00000000, 0x000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 /* OGF_HOST_CTL */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020077 { 0xaab00200, 0x2b402aaa, 0x020154, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 /* OGF_INFO_PARAM */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020079 { 0x000002be, 0x00000000, 0x000000, 0x00 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 /* OGF_STATUS_PARAM */
Marcel Holtmanndd7f5522005-10-28 19:20:53 +020081 { 0x000000ea, 0x00000000, 0x000000, 0x00 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 }
83};
84
85static struct bt_sock_list hci_sk_list = {
86 .lock = RW_LOCK_UNLOCKED
87};
88
89/* Send frame to RAW socket */
90void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
91{
92 struct sock *sk;
93 struct hlist_node *node;
94
95 BT_DBG("hdev %p len %d", hdev, skb->len);
96
97 read_lock(&hci_sk_list.lock);
98 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
109 /* Apply filter */
110 flt = &hci_pi(sk)->filter;
111
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700112 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
113 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 continue;
115
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700116 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
118
119 if (!hci_test_bit(evt, &flt->event_mask))
120 continue;
121
David S. Miller4498c802006-11-21 16:17:41 -0800122 if (flt->opcode &&
123 ((evt == HCI_EV_CMD_COMPLETE &&
124 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800125 get_unaligned((__le16 *)(skb->data + 3))) ||
David S. Miller4498c802006-11-21 16:17:41 -0800126 (evt == HCI_EV_CMD_STATUS &&
127 flt->opcode !=
Al Viro905f3ed2006-12-13 00:35:01 -0800128 get_unaligned((__le16 *)(skb->data + 4)))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 continue;
130 }
131
132 if (!(nskb = skb_clone(skb, GFP_ATOMIC)))
133 continue;
134
135 /* Put type byte before the data */
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700136 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138 if (sock_queue_rcv_skb(sk, nskb))
139 kfree_skb(nskb);
140 }
141 read_unlock(&hci_sk_list.lock);
142}
143
144static int hci_sock_release(struct socket *sock)
145{
146 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100147 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 BT_DBG("sock %p sk %p", sock, sk);
150
151 if (!sk)
152 return 0;
153
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100154 hdev = hci_pi(sk)->hdev;
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 bt_sock_unlink(&hci_sk_list, sk);
157
158 if (hdev) {
159 atomic_dec(&hdev->promisc);
160 hci_dev_put(hdev);
161 }
162
163 sock_orphan(sk);
164
165 skb_queue_purge(&sk->sk_receive_queue);
166 skb_queue_purge(&sk->sk_write_queue);
167
168 sock_put(sk);
169 return 0;
170}
171
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900172/* Ioctls that require bound socket */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
174{
175 struct hci_dev *hdev = hci_pi(sk)->hdev;
176
177 if (!hdev)
178 return -EBADFD;
179
180 switch (cmd) {
181 case HCISETRAW:
182 if (!capable(CAP_NET_ADMIN))
183 return -EACCES;
184
185 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
186 return -EPERM;
187
188 if (arg)
189 set_bit(HCI_RAW, &hdev->flags);
190 else
191 clear_bit(HCI_RAW, &hdev->flags);
192
193 return 0;
194
195 case HCISETSECMGR:
196 if (!capable(CAP_NET_ADMIN))
197 return -EACCES;
198
199 if (arg)
200 set_bit(HCI_SECMGR, &hdev->flags);
201 else
202 clear_bit(HCI_SECMGR, &hdev->flags);
203
204 return 0;
205
206 case HCIGETCONNINFO:
207 return hci_get_conn_info(hdev, (void __user *)arg);
208
209 default:
210 if (hdev->ioctl)
211 return hdev->ioctl(hdev, cmd, arg);
212 return -EINVAL;
213 }
214}
215
216static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
217{
218 struct sock *sk = sock->sk;
219 void __user *argp = (void __user *)arg;
220 int err;
221
222 BT_DBG("cmd %x arg %lx", cmd, arg);
223
224 switch (cmd) {
225 case HCIGETDEVLIST:
226 return hci_get_dev_list(argp);
227
228 case HCIGETDEVINFO:
229 return hci_get_dev_info(argp);
230
231 case HCIGETCONNLIST:
232 return hci_get_conn_list(argp);
233
234 case HCIDEVUP:
235 if (!capable(CAP_NET_ADMIN))
236 return -EACCES;
237 return hci_dev_open(arg);
238
239 case HCIDEVDOWN:
240 if (!capable(CAP_NET_ADMIN))
241 return -EACCES;
242 return hci_dev_close(arg);
243
244 case HCIDEVRESET:
245 if (!capable(CAP_NET_ADMIN))
246 return -EACCES;
247 return hci_dev_reset(arg);
248
249 case HCIDEVRESTAT:
250 if (!capable(CAP_NET_ADMIN))
251 return -EACCES;
252 return hci_dev_reset_stat(arg);
253
254 case HCISETSCAN:
255 case HCISETAUTH:
256 case HCISETENCRYPT:
257 case HCISETPTYPE:
258 case HCISETLINKPOL:
259 case HCISETLINKMODE:
260 case HCISETACLMTU:
261 case HCISETSCOMTU:
262 if (!capable(CAP_NET_ADMIN))
263 return -EACCES;
264 return hci_dev_cmd(cmd, argp);
265
266 case HCIINQUIRY:
267 return hci_inquiry(argp);
268
269 default:
270 lock_sock(sk);
271 err = hci_sock_bound_ioctl(sk, cmd, arg);
272 release_sock(sk);
273 return err;
274 }
275}
276
277static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
278{
279 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
280 struct sock *sk = sock->sk;
281 struct hci_dev *hdev = NULL;
282 int err = 0;
283
284 BT_DBG("sock %p sk %p", sock, sk);
285
286 if (!haddr || haddr->hci_family != AF_BLUETOOTH)
287 return -EINVAL;
288
289 lock_sock(sk);
290
291 if (hci_pi(sk)->hdev) {
292 err = -EALREADY;
293 goto done;
294 }
295
296 if (haddr->hci_dev != HCI_DEV_NONE) {
297 if (!(hdev = hci_dev_get(haddr->hci_dev))) {
298 err = -ENODEV;
299 goto done;
300 }
301
302 atomic_inc(&hdev->promisc);
303 }
304
305 hci_pi(sk)->hdev = hdev;
306 sk->sk_state = BT_BOUND;
307
308done:
309 release_sock(sk);
310 return err;
311}
312
313static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
314{
315 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
316 struct sock *sk = sock->sk;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100317 struct hci_dev *hdev = hci_pi(sk)->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
319 BT_DBG("sock %p sk %p", sock, sk);
320
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100321 if (!hdev)
322 return -EBADFD;
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 lock_sock(sk);
325
326 *addr_len = sizeof(*haddr);
327 haddr->hci_family = AF_BLUETOOTH;
Marcel Holtmann7b005bd2006-02-13 11:40:03 +0100328 haddr->hci_dev = hdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 release_sock(sk);
331 return 0;
332}
333
334static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
335{
336 __u32 mask = hci_pi(sk)->cmsg_mask;
337
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700338 if (mask & HCI_CMSG_DIR) {
339 int incoming = bt_cb(skb)->incoming;
340 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Patrick McHardya61bbcf2005-08-14 17:24:31 -0700343 if (mask & HCI_CMSG_TSTAMP) {
344 struct timeval tv;
345
346 skb_get_timestamp(skb, &tv);
347 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(tv), &tv);
348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349}
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900350
351static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 struct msghdr *msg, size_t len, int flags)
353{
354 int noblock = flags & MSG_DONTWAIT;
355 struct sock *sk = sock->sk;
356 struct sk_buff *skb;
357 int copied, err;
358
359 BT_DBG("sock %p, sk %p", sock, sk);
360
361 if (flags & (MSG_OOB))
362 return -EOPNOTSUPP;
363
364 if (sk->sk_state == BT_CLOSED)
365 return 0;
366
367 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err)))
368 return err;
369
370 msg->msg_namelen = 0;
371
372 copied = skb->len;
373 if (len < copied) {
374 msg->msg_flags |= MSG_TRUNC;
375 copied = len;
376 }
377
378 skb->h.raw = skb->data;
379 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
380
381 hci_sock_cmsg(sk, msg, skb);
382
383 skb_free_datagram(sk, skb);
384
385 return err ? : copied;
386}
387
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900388static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 struct msghdr *msg, size_t len)
390{
391 struct sock *sk = sock->sk;
392 struct hci_dev *hdev;
393 struct sk_buff *skb;
394 int err;
395
396 BT_DBG("sock %p sk %p", sock, sk);
397
398 if (msg->msg_flags & MSG_OOB)
399 return -EOPNOTSUPP;
400
401 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
402 return -EINVAL;
403
404 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
405 return -EINVAL;
406
407 lock_sock(sk);
408
409 if (!(hdev = hci_pi(sk)->hdev)) {
410 err = -EBADFD;
411 goto done;
412 }
413
414 if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
415 goto done;
416
417 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
418 err = -EFAULT;
419 goto drop;
420 }
421
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700422 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 skb_pull(skb, 1);
424 skb->dev = (void *) hdev;
425
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700426 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
Marcel Holtmann1ebb9252005-11-08 09:57:21 -0800427 u16 opcode = __le16_to_cpu(get_unaligned((__le16 *) skb->data));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 u16 ogf = hci_opcode_ogf(opcode);
429 u16 ocf = hci_opcode_ocf(opcode);
430
431 if (((ogf > HCI_SFLT_MAX_OGF) ||
432 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
433 !capable(CAP_NET_RAW)) {
434 err = -EPERM;
435 goto drop;
436 }
437
438 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == OGF_VENDOR_CMD)) {
439 skb_queue_tail(&hdev->raw_q, skb);
440 hci_sched_tx(hdev);
441 } else {
442 skb_queue_tail(&hdev->cmd_q, skb);
443 hci_sched_cmd(hdev);
444 }
445 } else {
446 if (!capable(CAP_NET_RAW)) {
447 err = -EPERM;
448 goto drop;
449 }
450
451 skb_queue_tail(&hdev->raw_q, skb);
452 hci_sched_tx(hdev);
453 }
454
455 err = len;
456
457done:
458 release_sock(sk);
459 return err;
460
461drop:
462 kfree_skb(skb);
463 goto done;
464}
465
466static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
467{
468 struct hci_ufilter uf = { .opcode = 0 };
469 struct sock *sk = sock->sk;
470 int err = 0, opt = 0;
471
472 BT_DBG("sk %p, opt %d", sk, optname);
473
474 lock_sock(sk);
475
476 switch (optname) {
477 case HCI_DATA_DIR:
478 if (get_user(opt, (int __user *)optval)) {
479 err = -EFAULT;
480 break;
481 }
482
483 if (opt)
484 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
485 else
486 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
487 break;
488
489 case HCI_TIME_STAMP:
490 if (get_user(opt, (int __user *)optval)) {
491 err = -EFAULT;
492 break;
493 }
494
495 if (opt)
496 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
497 else
498 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
499 break;
500
501 case HCI_FILTER:
502 len = min_t(unsigned int, len, sizeof(uf));
503 if (copy_from_user(&uf, optval, len)) {
504 err = -EFAULT;
505 break;
506 }
507
508 if (!capable(CAP_NET_RAW)) {
509 uf.type_mask &= hci_sec_filter.type_mask;
510 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
511 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
512 }
513
514 {
515 struct hci_filter *f = &hci_pi(sk)->filter;
516
517 f->type_mask = uf.type_mask;
518 f->opcode = uf.opcode;
519 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
520 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
521 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900522 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
524 default:
525 err = -ENOPROTOOPT;
526 break;
527 }
528
529 release_sock(sk);
530 return err;
531}
532
533static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
534{
535 struct hci_ufilter uf;
536 struct sock *sk = sock->sk;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900537 int len, opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539 if (get_user(len, optlen))
540 return -EFAULT;
541
542 switch (optname) {
543 case HCI_DATA_DIR:
544 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
545 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900546 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 opt = 0;
548
549 if (put_user(opt, optval))
550 return -EFAULT;
551 break;
552
553 case HCI_TIME_STAMP:
554 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
555 opt = 1;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900556 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 opt = 0;
558
559 if (put_user(opt, optval))
560 return -EFAULT;
561 break;
562
563 case HCI_FILTER:
564 {
565 struct hci_filter *f = &hci_pi(sk)->filter;
566
567 uf.type_mask = f->type_mask;
568 uf.opcode = f->opcode;
569 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
570 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
571 }
572
573 len = min_t(unsigned int, len, sizeof(uf));
574 if (copy_to_user(optval, &uf, len))
575 return -EFAULT;
576 break;
577
578 default:
579 return -ENOPROTOOPT;
580 break;
581 }
582
583 return 0;
584}
585
Eric Dumazet90ddc4f2005-12-22 12:49:22 -0800586static const struct proto_ops hci_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 .family = PF_BLUETOOTH,
588 .owner = THIS_MODULE,
589 .release = hci_sock_release,
590 .bind = hci_sock_bind,
591 .getname = hci_sock_getname,
592 .sendmsg = hci_sock_sendmsg,
593 .recvmsg = hci_sock_recvmsg,
594 .ioctl = hci_sock_ioctl,
595 .poll = datagram_poll,
596 .listen = sock_no_listen,
597 .shutdown = sock_no_shutdown,
598 .setsockopt = hci_sock_setsockopt,
599 .getsockopt = hci_sock_getsockopt,
600 .connect = sock_no_connect,
601 .socketpair = sock_no_socketpair,
602 .accept = sock_no_accept,
603 .mmap = sock_no_mmap
604};
605
606static struct proto hci_sk_proto = {
607 .name = "HCI",
608 .owner = THIS_MODULE,
609 .obj_size = sizeof(struct hci_pinfo)
610};
611
612static int hci_sock_create(struct socket *sock, int protocol)
613{
614 struct sock *sk;
615
616 BT_DBG("sock %p", sock);
617
618 if (sock->type != SOCK_RAW)
619 return -ESOCKTNOSUPPORT;
620
621 sock->ops = &hci_sock_ops;
622
Marcel Holtmann74da6262006-10-15 17:31:14 +0200623 sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 if (!sk)
625 return -ENOMEM;
626
627 sock_init_data(sock, sk);
628
629 sock_reset_flag(sk, SOCK_ZAPPED);
630
631 sk->sk_protocol = protocol;
632
633 sock->state = SS_UNCONNECTED;
634 sk->sk_state = BT_OPEN;
635
636 bt_sock_link(&hci_sk_list, sk);
637 return 0;
638}
639
640static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
641{
642 struct hci_dev *hdev = (struct hci_dev *) ptr;
643 struct hci_ev_si_device ev;
644
645 BT_DBG("hdev %s event %ld", hdev->name, event);
646
647 /* Send event to sockets */
648 ev.event = event;
649 ev.dev_id = hdev->id;
650 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
651
652 if (event == HCI_DEV_UNREG) {
653 struct sock *sk;
654 struct hlist_node *node;
655
656 /* Detach sockets from device */
657 read_lock(&hci_sk_list.lock);
658 sk_for_each(sk, node, &hci_sk_list.head) {
659 bh_lock_sock(sk);
660 if (hci_pi(sk)->hdev == hdev) {
661 hci_pi(sk)->hdev = NULL;
662 sk->sk_err = EPIPE;
663 sk->sk_state = BT_OPEN;
664 sk->sk_state_change(sk);
665
666 hci_dev_put(hdev);
667 }
668 bh_unlock_sock(sk);
669 }
670 read_unlock(&hci_sk_list.lock);
671 }
672
673 return NOTIFY_DONE;
674}
675
676static struct net_proto_family hci_sock_family_ops = {
677 .family = PF_BLUETOOTH,
678 .owner = THIS_MODULE,
679 .create = hci_sock_create,
680};
681
682static struct notifier_block hci_sock_nblock = {
683 .notifier_call = hci_sock_dev_event
684};
685
686int __init hci_sock_init(void)
687{
688 int err;
689
690 err = proto_register(&hci_sk_proto, 0);
691 if (err < 0)
692 return err;
693
694 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
695 if (err < 0)
696 goto error;
697
698 hci_register_notifier(&hci_sock_nblock);
699
700 BT_INFO("HCI socket layer initialized");
701
702 return 0;
703
704error:
705 BT_ERR("HCI socket registration failed");
706 proto_unregister(&hci_sk_proto);
707 return err;
708}
709
710int __exit hci_sock_cleanup(void)
711{
712 if (bt_sock_unregister(BTPROTO_HCI) < 0)
713 BT_ERR("HCI socket unregistration failed");
714
715 hci_unregister_notifier(&hci_sock_nblock);
716
717 proto_unregister(&hci_sk_proto);
718
719 return 0;
720}