aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/hci_sock.c')
-rw-r--r--net/bluetooth/hci_sock.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index b3753bad2a55..29827c77f6ce 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -49,6 +49,8 @@
49#include <net/bluetooth/bluetooth.h> 49#include <net/bluetooth/bluetooth.h>
50#include <net/bluetooth/hci_core.h> 50#include <net/bluetooth/hci_core.h>
51 51
52static int enable_mgmt;
53
52/* ----- HCI socket interface ----- */ 54/* ----- HCI socket interface ----- */
53 55
54static inline int hci_test_bit(int nr, void *addr) 56static inline int hci_test_bit(int nr, void *addr)
@@ -102,6 +104,12 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
102 if (skb->sk == sk) 104 if (skb->sk == sk)
103 continue; 105 continue;
104 106
107 if (bt_cb(skb)->channel != hci_pi(sk)->channel)
108 continue;
109
110 if (bt_cb(skb)->channel == HCI_CHANNEL_CONTROL)
111 goto clone;
112
105 /* Apply filter */ 113 /* Apply filter */
106 flt = &hci_pi(sk)->filter; 114 flt = &hci_pi(sk)->filter;
107 115
@@ -125,12 +133,14 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
125 continue; 133 continue;
126 } 134 }
127 135
136clone:
128 nskb = skb_clone(skb, GFP_ATOMIC); 137 nskb = skb_clone(skb, GFP_ATOMIC);
129 if (!nskb) 138 if (!nskb)
130 continue; 139 continue;
131 140
132 /* Put type byte before the data */ 141 /* Put type byte before the data */
133 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1); 142 if (bt_cb(skb)->channel == HCI_CHANNEL_RAW)
143 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
134 144
135 if (sock_queue_rcv_skb(sk, nskb)) 145 if (sock_queue_rcv_skb(sk, nskb))
136 kfree_skb(nskb); 146 kfree_skb(nskb);
@@ -353,25 +363,38 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a
353 363
354static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) 364static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
355{ 365{
356 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 366 struct sockaddr_hci haddr;
357 struct sock *sk = sock->sk; 367 struct sock *sk = sock->sk;
358 struct hci_dev *hdev = NULL; 368 struct hci_dev *hdev = NULL;
359 int err = 0; 369 int len, err = 0;
360 370
361 BT_DBG("sock %p sk %p", sock, sk); 371 BT_DBG("sock %p sk %p", sock, sk);
362 372
363 if (!haddr || haddr->hci_family != AF_BLUETOOTH) 373 if (!addr)
374 return -EINVAL;
375
376 memset(&haddr, 0, sizeof(haddr));
377 len = min_t(unsigned int, sizeof(haddr), addr_len);
378 memcpy(&haddr, addr, len);
379
380 if (haddr.hci_family != AF_BLUETOOTH)
381 return -EINVAL;
382
383 if (haddr.hci_channel > HCI_CHANNEL_CONTROL)
384 return -EINVAL;
385
386 if (haddr.hci_channel == HCI_CHANNEL_CONTROL && !enable_mgmt)
364 return -EINVAL; 387 return -EINVAL;
365 388
366 lock_sock(sk); 389 lock_sock(sk);
367 390
368 if (hci_pi(sk)->hdev) { 391 if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {
369 err = -EALREADY; 392 err = -EALREADY;
370 goto done; 393 goto done;
371 } 394 }
372 395
373 if (haddr->hci_dev != HCI_DEV_NONE) { 396 if (haddr.hci_dev != HCI_DEV_NONE) {
374 hdev = hci_dev_get(haddr->hci_dev); 397 hdev = hci_dev_get(haddr.hci_dev);
375 if (!hdev) { 398 if (!hdev) {
376 err = -ENODEV; 399 err = -ENODEV;
377 goto done; 400 goto done;
@@ -380,6 +403,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
380 atomic_inc(&hdev->promisc); 403 atomic_inc(&hdev->promisc);
381 } 404 }
382 405
406 hci_pi(sk)->channel = haddr.hci_channel;
383 hci_pi(sk)->hdev = hdev; 407 hci_pi(sk)->hdev = hdev;
384 sk->sk_state = BT_BOUND; 408 sk->sk_state = BT_BOUND;
385 409
@@ -502,6 +526,17 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
502 526
503 lock_sock(sk); 527 lock_sock(sk);
504 528
529 switch (hci_pi(sk)->channel) {
530 case HCI_CHANNEL_RAW:
531 break;
532 case HCI_CHANNEL_CONTROL:
533 err = mgmt_control(sk, msg, len);
534 goto done;
535 default:
536 err = -EINVAL;
537 goto done;
538 }
539
505 hdev = hci_pi(sk)->hdev; 540 hdev = hci_pi(sk)->hdev;
506 if (!hdev) { 541 if (!hdev) {
507 err = -EBADFD; 542 err = -EBADFD;
@@ -831,3 +866,6 @@ void __exit hci_sock_cleanup(void)
831 866
832 proto_unregister(&hci_sk_proto); 867 proto_unregister(&hci_sk_proto);
833} 868}
869
870module_param(enable_mgmt, bool, 0644);
871MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");