summaryrefslogtreecommitdiff
path: root/net/bluetooth/hci_sock.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2016-08-30 06:00:39 +0300
committerMarcel Holtmann <marcel@holtmann.org>2016-09-19 21:19:34 +0300
commitf81f5b2db8692ff1d2d5f4db1fde58e67aa976a3 (patch)
treef5ef557afd1ec1600ebf3b72aa3275f368c97630 /net/bluetooth/hci_sock.c
parentd0bef1d26fb6fdad818f3d15a178d51e2a8478ae (diff)
downloadlinux-f81f5b2db8692ff1d2d5f4db1fde58e67aa976a3.tar.xz
Bluetooth: Send control open and close messages for HCI raw sockets
When opening and closing HCI raw sockets their main usage is for legacy userspace. To track interaction with the modern mgmt interface, send open and close monitoring messages for these action. The HCI raw sockets is special since it supports unbound ioctl operation and for that special case delay the notification message until at least one ioctl has been executed. The difference between a bound and unbound socket will be detailed by the fact the HCI index is present or not. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/hci_sock.c')
-rw-r--r--net/bluetooth/hci_sock.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index b22efe272f7e..c7772436f508 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -488,6 +488,11 @@ static struct sk_buff *create_monitor_ctrl_open(struct sock *sk)
return NULL;
switch (hci_pi(sk)->channel) {
+ case HCI_CHANNEL_RAW:
+ format = 0x0000;
+ ver[0] = BT_SUBSYS_VERSION;
+ put_unaligned_le16(BT_SUBSYS_REVISION, ver + 1);
+ break;
case HCI_CHANNEL_CONTROL:
format = 0x0002;
mgmt_fill_version_info(ver);
@@ -533,6 +538,7 @@ static struct sk_buff *create_monitor_ctrl_close(struct sock *sk)
return NULL;
switch (hci_pi(sk)->channel) {
+ case HCI_CHANNEL_RAW:
case HCI_CHANNEL_CONTROL:
break;
default:
@@ -820,6 +826,7 @@ static int hci_sock_release(struct socket *sock)
case HCI_CHANNEL_MONITOR:
atomic_dec(&monitor_promisc);
break;
+ case HCI_CHANNEL_RAW:
case HCI_CHANNEL_CONTROL:
/* Send event to monitor */
skb = create_monitor_ctrl_close(sk);
@@ -958,6 +965,27 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
goto done;
}
+ /* When calling an ioctl on an unbound raw socket, then ensure
+ * that the monitor gets informed. Ensure that the resulting event
+ * is only send once by checking if the cookie exists or not. The
+ * socket cookie will be only ever generated once for the lifetime
+ * of a given socket.
+ */
+ if (hci_sock_gen_cookie(sk)) {
+ struct sk_buff *skb;
+
+ if (capable(CAP_NET_ADMIN))
+ hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
+
+ /* Send event to monitor */
+ skb = create_monitor_ctrl_open(sk);
+ if (skb) {
+ hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
+ HCI_SOCK_TRUSTED, NULL);
+ kfree_skb(skb);
+ }
+ }
+
release_sock(sk);
switch (cmd) {
@@ -1061,6 +1089,26 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
hci_pi(sk)->channel = haddr.hci_channel;
hci_pi(sk)->hdev = hdev;
+
+ /* Only send the event to monitor when a new cookie has
+ * been generated. An existing cookie means that an unbound
+ * socket has seen an ioctl and that triggered the cookie
+ * generation and sending of the monitor event.
+ */
+ if (hci_sock_gen_cookie(sk)) {
+ struct sk_buff *skb;
+
+ if (capable(CAP_NET_ADMIN))
+ hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
+
+ /* Send event to monitor */
+ skb = create_monitor_ctrl_open(sk);
+ if (skb) {
+ hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
+ HCI_SOCK_TRUSTED, NULL);
+ kfree_skb(skb);
+ }
+ }
break;
case HCI_CHANNEL_USER: