11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 31da177e4SLinus Torvalds Copyright (C) 2000-2001 Qualcomm Incorporated 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI sockets. */ 261da177e4SLinus Torvalds 278c520a59SGustavo Padovan #include <linux/export.h> 281da177e4SLinus Torvalds #include <asm/unaligned.h> 29dd31506dSMarcel Holtmann #include <generated/compile.h> 30dd31506dSMarcel Holtmann #include <generated/utsrelease.h> 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 331da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 34cd82e61cSMarcel Holtmann #include <net/bluetooth/hci_mon.h> 35fa4335d7SJohan Hedberg #include <net/bluetooth/mgmt.h> 36fa4335d7SJohan Hedberg 37fa4335d7SJohan Hedberg #include "mgmt_util.h" 381da177e4SLinus Torvalds 39801c1e8dSJohan Hedberg static LIST_HEAD(mgmt_chan_list); 40801c1e8dSJohan Hedberg static DEFINE_MUTEX(mgmt_chan_list_lock); 41801c1e8dSJohan Hedberg 42cd82e61cSMarcel Holtmann static atomic_t monitor_promisc = ATOMIC_INIT(0); 43cd82e61cSMarcel Holtmann 441da177e4SLinus Torvalds /* ----- HCI socket interface ----- */ 451da177e4SLinus Torvalds 46863def58SMarcel Holtmann /* Socket info */ 47863def58SMarcel Holtmann #define hci_pi(sk) ((struct hci_pinfo *) sk) 48863def58SMarcel Holtmann 49863def58SMarcel Holtmann struct hci_pinfo { 50863def58SMarcel Holtmann struct bt_sock bt; 51863def58SMarcel Holtmann struct hci_dev *hdev; 52863def58SMarcel Holtmann struct hci_filter filter; 53863def58SMarcel Holtmann __u32 cmsg_mask; 54863def58SMarcel Holtmann unsigned short channel; 556befc644SMarcel Holtmann unsigned long flags; 56863def58SMarcel Holtmann }; 57863def58SMarcel Holtmann 586befc644SMarcel Holtmann void hci_sock_set_flag(struct sock *sk, int nr) 596befc644SMarcel Holtmann { 606befc644SMarcel Holtmann set_bit(nr, &hci_pi(sk)->flags); 616befc644SMarcel Holtmann } 626befc644SMarcel Holtmann 636befc644SMarcel Holtmann void hci_sock_clear_flag(struct sock *sk, int nr) 646befc644SMarcel Holtmann { 656befc644SMarcel Holtmann clear_bit(nr, &hci_pi(sk)->flags); 666befc644SMarcel Holtmann } 676befc644SMarcel Holtmann 68c85be545SMarcel Holtmann int hci_sock_test_flag(struct sock *sk, int nr) 69c85be545SMarcel Holtmann { 70c85be545SMarcel Holtmann return test_bit(nr, &hci_pi(sk)->flags); 71c85be545SMarcel Holtmann } 72c85be545SMarcel Holtmann 73d0f172b1SJohan Hedberg unsigned short hci_sock_get_channel(struct sock *sk) 74d0f172b1SJohan Hedberg { 75d0f172b1SJohan Hedberg return hci_pi(sk)->channel; 76d0f172b1SJohan Hedberg } 77d0f172b1SJohan Hedberg 789391976aSJiri Slaby static inline int hci_test_bit(int nr, const void *addr) 791da177e4SLinus Torvalds { 809391976aSJiri Slaby return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds /* Security filter */ 843ad254f7SMarcel Holtmann #define HCI_SFLT_MAX_OGF 5 853ad254f7SMarcel Holtmann 863ad254f7SMarcel Holtmann struct hci_sec_filter { 873ad254f7SMarcel Holtmann __u32 type_mask; 883ad254f7SMarcel Holtmann __u32 event_mask[2]; 893ad254f7SMarcel Holtmann __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; 903ad254f7SMarcel Holtmann }; 913ad254f7SMarcel Holtmann 927e67c112SMarcel Holtmann static const struct hci_sec_filter hci_sec_filter = { 931da177e4SLinus Torvalds /* Packet types */ 941da177e4SLinus Torvalds 0x10, 951da177e4SLinus Torvalds /* Events */ 96dd7f5527SMarcel Holtmann { 0x1000d9fe, 0x0000b00c }, 971da177e4SLinus Torvalds /* Commands */ 981da177e4SLinus Torvalds { 991da177e4SLinus Torvalds { 0x0 }, 1001da177e4SLinus Torvalds /* OGF_LINK_CTL */ 1017c631a67SMarcel Holtmann { 0xbe000006, 0x00000001, 0x00000000, 0x00 }, 1021da177e4SLinus Torvalds /* OGF_LINK_POLICY */ 1037c631a67SMarcel Holtmann { 0x00005200, 0x00000000, 0x00000000, 0x00 }, 1041da177e4SLinus Torvalds /* OGF_HOST_CTL */ 1057c631a67SMarcel Holtmann { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 }, 1061da177e4SLinus Torvalds /* OGF_INFO_PARAM */ 1077c631a67SMarcel Holtmann { 0x000002be, 0x00000000, 0x00000000, 0x00 }, 1081da177e4SLinus Torvalds /* OGF_STATUS_PARAM */ 1097c631a67SMarcel Holtmann { 0x000000ea, 0x00000000, 0x00000000, 0x00 } 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds }; 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds static struct bt_sock_list hci_sk_list = { 114d5fb2962SRobert P. J. Day .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) 1151da177e4SLinus Torvalds }; 1161da177e4SLinus Torvalds 117f81fe64fSMarcel Holtmann static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb) 118f81fe64fSMarcel Holtmann { 119f81fe64fSMarcel Holtmann struct hci_filter *flt; 120f81fe64fSMarcel Holtmann int flt_type, flt_event; 121f81fe64fSMarcel Holtmann 122f81fe64fSMarcel Holtmann /* Apply filter */ 123f81fe64fSMarcel Holtmann flt = &hci_pi(sk)->filter; 124f81fe64fSMarcel Holtmann 125d79f34e3SMarcel Holtmann flt_type = hci_skb_pkt_type(skb) & HCI_FLT_TYPE_BITS; 126f81fe64fSMarcel Holtmann 127f81fe64fSMarcel Holtmann if (!test_bit(flt_type, &flt->type_mask)) 128f81fe64fSMarcel Holtmann return true; 129f81fe64fSMarcel Holtmann 130f81fe64fSMarcel Holtmann /* Extra filter for event packets only */ 131d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT) 132f81fe64fSMarcel Holtmann return false; 133f81fe64fSMarcel Holtmann 134f81fe64fSMarcel Holtmann flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); 135f81fe64fSMarcel Holtmann 136f81fe64fSMarcel Holtmann if (!hci_test_bit(flt_event, &flt->event_mask)) 137f81fe64fSMarcel Holtmann return true; 138f81fe64fSMarcel Holtmann 139f81fe64fSMarcel Holtmann /* Check filter only when opcode is set */ 140f81fe64fSMarcel Holtmann if (!flt->opcode) 141f81fe64fSMarcel Holtmann return false; 142f81fe64fSMarcel Holtmann 143f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_COMPLETE && 144f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 3))) 145f81fe64fSMarcel Holtmann return true; 146f81fe64fSMarcel Holtmann 147f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_STATUS && 148f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 4))) 149f81fe64fSMarcel Holtmann return true; 150f81fe64fSMarcel Holtmann 151f81fe64fSMarcel Holtmann return false; 152f81fe64fSMarcel Holtmann } 153f81fe64fSMarcel Holtmann 1541da177e4SLinus Torvalds /* Send frame to RAW socket */ 155470fe1b5SMarcel Holtmann void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) 1561da177e4SLinus Torvalds { 1571da177e4SLinus Torvalds struct sock *sk; 158e0edf373SMarcel Holtmann struct sk_buff *skb_copy = NULL; 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds BT_DBG("hdev %p len %d", hdev, skb->len); 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds read_lock(&hci_sk_list.lock); 163470fe1b5SMarcel Holtmann 164b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 1651da177e4SLinus Torvalds struct sk_buff *nskb; 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 1681da177e4SLinus Torvalds continue; 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /* Don't send frame to the socket it came from */ 1711da177e4SLinus Torvalds if (skb->sk == sk) 1721da177e4SLinus Torvalds continue; 1731da177e4SLinus Torvalds 17423500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { 175d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && 176d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 177d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 178d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) 179bb77543eSMarcel Holtmann continue; 180f81fe64fSMarcel Holtmann if (is_filtered_packet(sk, skb)) 1811da177e4SLinus Torvalds continue; 18223500189SMarcel Holtmann } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 18323500189SMarcel Holtmann if (!bt_cb(skb)->incoming) 18423500189SMarcel Holtmann continue; 185d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 186d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 187d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) 18823500189SMarcel Holtmann continue; 18923500189SMarcel Holtmann } else { 19023500189SMarcel Holtmann /* Don't send frame to other channel types */ 19123500189SMarcel Holtmann continue; 19223500189SMarcel Holtmann } 1931da177e4SLinus Torvalds 194e0edf373SMarcel Holtmann if (!skb_copy) { 195e0edf373SMarcel Holtmann /* Create a private copy with headroom */ 196bad93e9dSOctavian Purdila skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true); 197e0edf373SMarcel Holtmann if (!skb_copy) 1981da177e4SLinus Torvalds continue; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds /* Put type byte before the data */ 201d79f34e3SMarcel Holtmann memcpy(skb_push(skb_copy, 1), &hci_skb_pkt_type(skb), 1); 202e0edf373SMarcel Holtmann } 203e0edf373SMarcel Holtmann 204e0edf373SMarcel Holtmann nskb = skb_clone(skb_copy, GFP_ATOMIC); 205e0edf373SMarcel Holtmann if (!nskb) 206e0edf373SMarcel Holtmann continue; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds if (sock_queue_rcv_skb(sk, nskb)) 2091da177e4SLinus Torvalds kfree_skb(nskb); 2101da177e4SLinus Torvalds } 211470fe1b5SMarcel Holtmann 212470fe1b5SMarcel Holtmann read_unlock(&hci_sk_list.lock); 213e0edf373SMarcel Holtmann 214e0edf373SMarcel Holtmann kfree_skb(skb_copy); 215470fe1b5SMarcel Holtmann } 216470fe1b5SMarcel Holtmann 2177129069eSJohan Hedberg /* Send frame to sockets with specific channel */ 2187129069eSJohan Hedberg void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, 219c08b1a1dSMarcel Holtmann int flag, struct sock *skip_sk) 220470fe1b5SMarcel Holtmann { 221470fe1b5SMarcel Holtmann struct sock *sk; 222470fe1b5SMarcel Holtmann 2237129069eSJohan Hedberg BT_DBG("channel %u len %d", channel, skb->len); 224470fe1b5SMarcel Holtmann 225470fe1b5SMarcel Holtmann read_lock(&hci_sk_list.lock); 226470fe1b5SMarcel Holtmann 227b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 228470fe1b5SMarcel Holtmann struct sk_buff *nskb; 229470fe1b5SMarcel Holtmann 230c08b1a1dSMarcel Holtmann /* Ignore socket without the flag set */ 231c85be545SMarcel Holtmann if (!hci_sock_test_flag(sk, flag)) 232c08b1a1dSMarcel Holtmann continue; 233c08b1a1dSMarcel Holtmann 234470fe1b5SMarcel Holtmann /* Skip the original socket */ 235470fe1b5SMarcel Holtmann if (sk == skip_sk) 236470fe1b5SMarcel Holtmann continue; 237470fe1b5SMarcel Holtmann 238470fe1b5SMarcel Holtmann if (sk->sk_state != BT_BOUND) 239470fe1b5SMarcel Holtmann continue; 240470fe1b5SMarcel Holtmann 2417129069eSJohan Hedberg if (hci_pi(sk)->channel != channel) 242d7f72f61SMarcel Holtmann continue; 243d7f72f61SMarcel Holtmann 244d7f72f61SMarcel Holtmann nskb = skb_clone(skb, GFP_ATOMIC); 245d7f72f61SMarcel Holtmann if (!nskb) 246d7f72f61SMarcel Holtmann continue; 247d7f72f61SMarcel Holtmann 248d7f72f61SMarcel Holtmann if (sock_queue_rcv_skb(sk, nskb)) 249d7f72f61SMarcel Holtmann kfree_skb(nskb); 250d7f72f61SMarcel Holtmann } 251d7f72f61SMarcel Holtmann 252d7f72f61SMarcel Holtmann read_unlock(&hci_sk_list.lock); 253d7f72f61SMarcel Holtmann } 254d7f72f61SMarcel Holtmann 255cd82e61cSMarcel Holtmann /* Send frame to monitor socket */ 256cd82e61cSMarcel Holtmann void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) 257cd82e61cSMarcel Holtmann { 258cd82e61cSMarcel Holtmann struct sk_buff *skb_copy = NULL; 2592b531294SMarcel Holtmann struct hci_mon_hdr *hdr; 260cd82e61cSMarcel Holtmann __le16 opcode; 261cd82e61cSMarcel Holtmann 262cd82e61cSMarcel Holtmann if (!atomic_read(&monitor_promisc)) 263cd82e61cSMarcel Holtmann return; 264cd82e61cSMarcel Holtmann 265cd82e61cSMarcel Holtmann BT_DBG("hdev %p len %d", hdev, skb->len); 266cd82e61cSMarcel Holtmann 267d79f34e3SMarcel Holtmann switch (hci_skb_pkt_type(skb)) { 268cd82e61cSMarcel Holtmann case HCI_COMMAND_PKT: 269dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); 270cd82e61cSMarcel Holtmann break; 271cd82e61cSMarcel Holtmann case HCI_EVENT_PKT: 272dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_EVENT_PKT); 273cd82e61cSMarcel Holtmann break; 274cd82e61cSMarcel Holtmann case HCI_ACLDATA_PKT: 275cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 276dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); 277cd82e61cSMarcel Holtmann else 278dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); 279cd82e61cSMarcel Holtmann break; 280cd82e61cSMarcel Holtmann case HCI_SCODATA_PKT: 281cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 282dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); 283cd82e61cSMarcel Holtmann else 284dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); 285cd82e61cSMarcel Holtmann break; 286e875ff84SMarcel Holtmann case HCI_DIAG_PKT: 287e875ff84SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG); 288e875ff84SMarcel Holtmann break; 289cd82e61cSMarcel Holtmann default: 290cd82e61cSMarcel Holtmann return; 291cd82e61cSMarcel Holtmann } 292cd82e61cSMarcel Holtmann 2932b531294SMarcel Holtmann /* Create a private copy with headroom */ 2942b531294SMarcel Holtmann skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true); 2952b531294SMarcel Holtmann if (!skb_copy) 2962b531294SMarcel Holtmann return; 2972b531294SMarcel Holtmann 2982b531294SMarcel Holtmann /* Put header before the data */ 2992b531294SMarcel Holtmann hdr = (void *)skb_push(skb_copy, HCI_MON_HDR_SIZE); 3002b531294SMarcel Holtmann hdr->opcode = opcode; 3012b531294SMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 3022b531294SMarcel Holtmann hdr->len = cpu_to_le16(skb->len); 3032b531294SMarcel Holtmann 304c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, 305c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 306cd82e61cSMarcel Holtmann kfree_skb(skb_copy); 307cd82e61cSMarcel Holtmann } 308cd82e61cSMarcel Holtmann 309cd82e61cSMarcel Holtmann static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) 310cd82e61cSMarcel Holtmann { 311cd82e61cSMarcel Holtmann struct hci_mon_hdr *hdr; 312cd82e61cSMarcel Holtmann struct hci_mon_new_index *ni; 3136c566dd5SMarcel Holtmann struct hci_mon_index_info *ii; 314cd82e61cSMarcel Holtmann struct sk_buff *skb; 315cd82e61cSMarcel Holtmann __le16 opcode; 316cd82e61cSMarcel Holtmann 317cd82e61cSMarcel Holtmann switch (event) { 318cd82e61cSMarcel Holtmann case HCI_DEV_REG: 319cd82e61cSMarcel Holtmann skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC); 320cd82e61cSMarcel Holtmann if (!skb) 321cd82e61cSMarcel Holtmann return NULL; 322cd82e61cSMarcel Holtmann 323cd82e61cSMarcel Holtmann ni = (void *)skb_put(skb, HCI_MON_NEW_INDEX_SIZE); 324cd82e61cSMarcel Holtmann ni->type = hdev->dev_type; 325cd82e61cSMarcel Holtmann ni->bus = hdev->bus; 326cd82e61cSMarcel Holtmann bacpy(&ni->bdaddr, &hdev->bdaddr); 327cd82e61cSMarcel Holtmann memcpy(ni->name, hdev->name, 8); 328cd82e61cSMarcel Holtmann 329dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_NEW_INDEX); 330cd82e61cSMarcel Holtmann break; 331cd82e61cSMarcel Holtmann 332cd82e61cSMarcel Holtmann case HCI_DEV_UNREG: 333cd82e61cSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 334cd82e61cSMarcel Holtmann if (!skb) 335cd82e61cSMarcel Holtmann return NULL; 336cd82e61cSMarcel Holtmann 337dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_DEL_INDEX); 338cd82e61cSMarcel Holtmann break; 339cd82e61cSMarcel Holtmann 340e131d74aSMarcel Holtmann case HCI_DEV_SETUP: 341e131d74aSMarcel Holtmann if (hdev->manufacturer == 0xffff) 342e131d74aSMarcel Holtmann return NULL; 343e131d74aSMarcel Holtmann 344e131d74aSMarcel Holtmann /* fall through */ 345e131d74aSMarcel Holtmann 3466c566dd5SMarcel Holtmann case HCI_DEV_UP: 3476c566dd5SMarcel Holtmann skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC); 3486c566dd5SMarcel Holtmann if (!skb) 3496c566dd5SMarcel Holtmann return NULL; 3506c566dd5SMarcel Holtmann 3516c566dd5SMarcel Holtmann ii = (void *)skb_put(skb, HCI_MON_INDEX_INFO_SIZE); 3526c566dd5SMarcel Holtmann bacpy(&ii->bdaddr, &hdev->bdaddr); 3536c566dd5SMarcel Holtmann ii->manufacturer = cpu_to_le16(hdev->manufacturer); 3546c566dd5SMarcel Holtmann 3556c566dd5SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_INDEX_INFO); 3566c566dd5SMarcel Holtmann break; 3576c566dd5SMarcel Holtmann 35822db3cbcSMarcel Holtmann case HCI_DEV_OPEN: 35922db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 36022db3cbcSMarcel Holtmann if (!skb) 36122db3cbcSMarcel Holtmann return NULL; 36222db3cbcSMarcel Holtmann 36322db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_OPEN_INDEX); 36422db3cbcSMarcel Holtmann break; 36522db3cbcSMarcel Holtmann 36622db3cbcSMarcel Holtmann case HCI_DEV_CLOSE: 36722db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 36822db3cbcSMarcel Holtmann if (!skb) 36922db3cbcSMarcel Holtmann return NULL; 37022db3cbcSMarcel Holtmann 37122db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX); 37222db3cbcSMarcel Holtmann break; 37322db3cbcSMarcel Holtmann 374cd82e61cSMarcel Holtmann default: 375cd82e61cSMarcel Holtmann return NULL; 376cd82e61cSMarcel Holtmann } 377cd82e61cSMarcel Holtmann 378cd82e61cSMarcel Holtmann __net_timestamp(skb); 379cd82e61cSMarcel Holtmann 380cd82e61cSMarcel Holtmann hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE); 381cd82e61cSMarcel Holtmann hdr->opcode = opcode; 382cd82e61cSMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 383cd82e61cSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 384cd82e61cSMarcel Holtmann 385cd82e61cSMarcel Holtmann return skb; 386cd82e61cSMarcel Holtmann } 387cd82e61cSMarcel Holtmann 388dd31506dSMarcel Holtmann static void send_monitor_note(struct sock *sk, const char *text) 389dd31506dSMarcel Holtmann { 390dd31506dSMarcel Holtmann size_t len = strlen(text); 391dd31506dSMarcel Holtmann struct hci_mon_hdr *hdr; 392dd31506dSMarcel Holtmann struct sk_buff *skb; 393dd31506dSMarcel Holtmann 394dd31506dSMarcel Holtmann skb = bt_skb_alloc(len + 1, GFP_ATOMIC); 395dd31506dSMarcel Holtmann if (!skb) 396dd31506dSMarcel Holtmann return; 397dd31506dSMarcel Holtmann 398dd31506dSMarcel Holtmann strcpy(skb_put(skb, len + 1), text); 399dd31506dSMarcel Holtmann 400dd31506dSMarcel Holtmann __net_timestamp(skb); 401dd31506dSMarcel Holtmann 402dd31506dSMarcel Holtmann hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE); 403dd31506dSMarcel Holtmann hdr->opcode = cpu_to_le16(HCI_MON_SYSTEM_NOTE); 404dd31506dSMarcel Holtmann hdr->index = cpu_to_le16(HCI_DEV_NONE); 405dd31506dSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 406dd31506dSMarcel Holtmann 407dd31506dSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 408dd31506dSMarcel Holtmann kfree_skb(skb); 409dd31506dSMarcel Holtmann } 410dd31506dSMarcel Holtmann 411cd82e61cSMarcel Holtmann static void send_monitor_replay(struct sock *sk) 412cd82e61cSMarcel Holtmann { 413cd82e61cSMarcel Holtmann struct hci_dev *hdev; 414cd82e61cSMarcel Holtmann 415cd82e61cSMarcel Holtmann read_lock(&hci_dev_list_lock); 416cd82e61cSMarcel Holtmann 417cd82e61cSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 418cd82e61cSMarcel Holtmann struct sk_buff *skb; 419cd82e61cSMarcel Holtmann 420cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_REG); 421cd82e61cSMarcel Holtmann if (!skb) 422cd82e61cSMarcel Holtmann continue; 423cd82e61cSMarcel Holtmann 424cd82e61cSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 425cd82e61cSMarcel Holtmann kfree_skb(skb); 42622db3cbcSMarcel Holtmann 42722db3cbcSMarcel Holtmann if (!test_bit(HCI_RUNNING, &hdev->flags)) 42822db3cbcSMarcel Holtmann continue; 42922db3cbcSMarcel Holtmann 43022db3cbcSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_OPEN); 43122db3cbcSMarcel Holtmann if (!skb) 43222db3cbcSMarcel Holtmann continue; 43322db3cbcSMarcel Holtmann 43422db3cbcSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 43522db3cbcSMarcel Holtmann kfree_skb(skb); 4366c566dd5SMarcel Holtmann 437e131d74aSMarcel Holtmann if (test_bit(HCI_UP, &hdev->flags)) 4386c566dd5SMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_UP); 439e131d74aSMarcel Holtmann else if (hci_dev_test_flag(hdev, HCI_SETUP)) 440e131d74aSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_SETUP); 441e131d74aSMarcel Holtmann else 442e131d74aSMarcel Holtmann skb = NULL; 4436c566dd5SMarcel Holtmann 444e131d74aSMarcel Holtmann if (skb) { 4456c566dd5SMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 4466c566dd5SMarcel Holtmann kfree_skb(skb); 447cd82e61cSMarcel Holtmann } 448e131d74aSMarcel Holtmann } 449cd82e61cSMarcel Holtmann 450cd82e61cSMarcel Holtmann read_unlock(&hci_dev_list_lock); 451cd82e61cSMarcel Holtmann } 452cd82e61cSMarcel Holtmann 453040030efSMarcel Holtmann /* Generate internal stack event */ 454040030efSMarcel Holtmann static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 455040030efSMarcel Holtmann { 456040030efSMarcel Holtmann struct hci_event_hdr *hdr; 457040030efSMarcel Holtmann struct hci_ev_stack_internal *ev; 458040030efSMarcel Holtmann struct sk_buff *skb; 459040030efSMarcel Holtmann 460040030efSMarcel Holtmann skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 461040030efSMarcel Holtmann if (!skb) 462040030efSMarcel Holtmann return; 463040030efSMarcel Holtmann 464040030efSMarcel Holtmann hdr = (void *)skb_put(skb, HCI_EVENT_HDR_SIZE); 465040030efSMarcel Holtmann hdr->evt = HCI_EV_STACK_INTERNAL; 466040030efSMarcel Holtmann hdr->plen = sizeof(*ev) + dlen; 467040030efSMarcel Holtmann 468040030efSMarcel Holtmann ev = (void *)skb_put(skb, sizeof(*ev) + dlen); 469040030efSMarcel Holtmann ev->type = type; 470040030efSMarcel Holtmann memcpy(ev->data, data, dlen); 471040030efSMarcel Holtmann 472040030efSMarcel Holtmann bt_cb(skb)->incoming = 1; 473040030efSMarcel Holtmann __net_timestamp(skb); 474040030efSMarcel Holtmann 475d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_EVENT_PKT; 476040030efSMarcel Holtmann hci_send_to_sock(hdev, skb); 477040030efSMarcel Holtmann kfree_skb(skb); 478040030efSMarcel Holtmann } 479040030efSMarcel Holtmann 480040030efSMarcel Holtmann void hci_sock_dev_event(struct hci_dev *hdev, int event) 481040030efSMarcel Holtmann { 482040030efSMarcel Holtmann BT_DBG("hdev %s event %d", hdev->name, event); 483040030efSMarcel Holtmann 484cd82e61cSMarcel Holtmann if (atomic_read(&monitor_promisc)) { 485cd82e61cSMarcel Holtmann struct sk_buff *skb; 486cd82e61cSMarcel Holtmann 487ed1b28a4SMarcel Holtmann /* Send event to monitor */ 488cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, event); 489cd82e61cSMarcel Holtmann if (skb) { 490c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, 491c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 492cd82e61cSMarcel Holtmann kfree_skb(skb); 493cd82e61cSMarcel Holtmann } 494cd82e61cSMarcel Holtmann } 495cd82e61cSMarcel Holtmann 496ed1b28a4SMarcel Holtmann if (event <= HCI_DEV_DOWN) { 497ed1b28a4SMarcel Holtmann struct hci_ev_si_device ev; 498ed1b28a4SMarcel Holtmann 499040030efSMarcel Holtmann /* Send event to sockets */ 500040030efSMarcel Holtmann ev.event = event; 501040030efSMarcel Holtmann ev.dev_id = hdev->id; 502040030efSMarcel Holtmann hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); 503ed1b28a4SMarcel Holtmann } 504040030efSMarcel Holtmann 505040030efSMarcel Holtmann if (event == HCI_DEV_UNREG) { 506040030efSMarcel Holtmann struct sock *sk; 507040030efSMarcel Holtmann 508040030efSMarcel Holtmann /* Detach sockets from device */ 509040030efSMarcel Holtmann read_lock(&hci_sk_list.lock); 510b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 511040030efSMarcel Holtmann bh_lock_sock_nested(sk); 512040030efSMarcel Holtmann if (hci_pi(sk)->hdev == hdev) { 513040030efSMarcel Holtmann hci_pi(sk)->hdev = NULL; 514040030efSMarcel Holtmann sk->sk_err = EPIPE; 515040030efSMarcel Holtmann sk->sk_state = BT_OPEN; 516040030efSMarcel Holtmann sk->sk_state_change(sk); 517040030efSMarcel Holtmann 518040030efSMarcel Holtmann hci_dev_put(hdev); 519040030efSMarcel Holtmann } 520040030efSMarcel Holtmann bh_unlock_sock(sk); 521040030efSMarcel Holtmann } 522040030efSMarcel Holtmann read_unlock(&hci_sk_list.lock); 523040030efSMarcel Holtmann } 524040030efSMarcel Holtmann } 525040030efSMarcel Holtmann 526801c1e8dSJohan Hedberg static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel) 527801c1e8dSJohan Hedberg { 528801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 529801c1e8dSJohan Hedberg 530801c1e8dSJohan Hedberg list_for_each_entry(c, &mgmt_chan_list, list) { 531801c1e8dSJohan Hedberg if (c->channel == channel) 532801c1e8dSJohan Hedberg return c; 533801c1e8dSJohan Hedberg } 534801c1e8dSJohan Hedberg 535801c1e8dSJohan Hedberg return NULL; 536801c1e8dSJohan Hedberg } 537801c1e8dSJohan Hedberg 538801c1e8dSJohan Hedberg static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel) 539801c1e8dSJohan Hedberg { 540801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 541801c1e8dSJohan Hedberg 542801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 543801c1e8dSJohan Hedberg c = __hci_mgmt_chan_find(channel); 544801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 545801c1e8dSJohan Hedberg 546801c1e8dSJohan Hedberg return c; 547801c1e8dSJohan Hedberg } 548801c1e8dSJohan Hedberg 549801c1e8dSJohan Hedberg int hci_mgmt_chan_register(struct hci_mgmt_chan *c) 550801c1e8dSJohan Hedberg { 551801c1e8dSJohan Hedberg if (c->channel < HCI_CHANNEL_CONTROL) 552801c1e8dSJohan Hedberg return -EINVAL; 553801c1e8dSJohan Hedberg 554801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 555801c1e8dSJohan Hedberg if (__hci_mgmt_chan_find(c->channel)) { 556801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 557801c1e8dSJohan Hedberg return -EALREADY; 558801c1e8dSJohan Hedberg } 559801c1e8dSJohan Hedberg 560801c1e8dSJohan Hedberg list_add_tail(&c->list, &mgmt_chan_list); 561801c1e8dSJohan Hedberg 562801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 563801c1e8dSJohan Hedberg 564801c1e8dSJohan Hedberg return 0; 565801c1e8dSJohan Hedberg } 566801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_register); 567801c1e8dSJohan Hedberg 568801c1e8dSJohan Hedberg void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c) 569801c1e8dSJohan Hedberg { 570801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 571801c1e8dSJohan Hedberg list_del(&c->list); 572801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 573801c1e8dSJohan Hedberg } 574801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_unregister); 575801c1e8dSJohan Hedberg 5761da177e4SLinus Torvalds static int hci_sock_release(struct socket *sock) 5771da177e4SLinus Torvalds { 5781da177e4SLinus Torvalds struct sock *sk = sock->sk; 5797b005bd3SMarcel Holtmann struct hci_dev *hdev; 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds if (!sk) 5841da177e4SLinus Torvalds return 0; 5851da177e4SLinus Torvalds 5867b005bd3SMarcel Holtmann hdev = hci_pi(sk)->hdev; 5877b005bd3SMarcel Holtmann 588cd82e61cSMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_MONITOR) 589cd82e61cSMarcel Holtmann atomic_dec(&monitor_promisc); 590cd82e61cSMarcel Holtmann 5911da177e4SLinus Torvalds bt_sock_unlink(&hci_sk_list, sk); 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds if (hdev) { 59423500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 5956b3cc1dbSSimon Fels /* When releasing an user channel exclusive access, 5966b3cc1dbSSimon Fels * call hci_dev_do_close directly instead of calling 5976b3cc1dbSSimon Fels * hci_dev_close to ensure the exclusive access will 5986b3cc1dbSSimon Fels * be released and the controller brought back down. 5996b3cc1dbSSimon Fels * 6006b3cc1dbSSimon Fels * The checking of HCI_AUTO_OFF is not needed in this 6016b3cc1dbSSimon Fels * case since it will have been cleared already when 6026b3cc1dbSSimon Fels * opening the user channel. 6036b3cc1dbSSimon Fels */ 6046b3cc1dbSSimon Fels hci_dev_do_close(hdev); 6059380f9eaSLoic Poulain hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 6069380f9eaSLoic Poulain mgmt_index_added(hdev); 60723500189SMarcel Holtmann } 60823500189SMarcel Holtmann 6091da177e4SLinus Torvalds atomic_dec(&hdev->promisc); 6101da177e4SLinus Torvalds hci_dev_put(hdev); 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds sock_orphan(sk); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds skb_queue_purge(&sk->sk_receive_queue); 6161da177e4SLinus Torvalds skb_queue_purge(&sk->sk_write_queue); 6171da177e4SLinus Torvalds 6181da177e4SLinus Torvalds sock_put(sk); 6191da177e4SLinus Torvalds return 0; 6201da177e4SLinus Torvalds } 6211da177e4SLinus Torvalds 622b2a66aadSAntti Julku static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) 623f0358568SJohan Hedberg { 624f0358568SJohan Hedberg bdaddr_t bdaddr; 6255e762444SAntti Julku int err; 626f0358568SJohan Hedberg 627f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 628f0358568SJohan Hedberg return -EFAULT; 629f0358568SJohan Hedberg 63009fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6315e762444SAntti Julku 632dcc36c16SJohan Hedberg err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6335e762444SAntti Julku 63409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6355e762444SAntti Julku 6365e762444SAntti Julku return err; 637f0358568SJohan Hedberg } 638f0358568SJohan Hedberg 639b2a66aadSAntti Julku static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) 640f0358568SJohan Hedberg { 641f0358568SJohan Hedberg bdaddr_t bdaddr; 6425e762444SAntti Julku int err; 643f0358568SJohan Hedberg 644f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 645f0358568SJohan Hedberg return -EFAULT; 646f0358568SJohan Hedberg 64709fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6485e762444SAntti Julku 649dcc36c16SJohan Hedberg err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6505e762444SAntti Julku 65109fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6525e762444SAntti Julku 6535e762444SAntti Julku return err; 654f0358568SJohan Hedberg } 655f0358568SJohan Hedberg 6561da177e4SLinus Torvalds /* Ioctls that require bound socket */ 6576039aa73SGustavo Padovan static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, 6586039aa73SGustavo Padovan unsigned long arg) 6591da177e4SLinus Torvalds { 6601da177e4SLinus Torvalds struct hci_dev *hdev = hci_pi(sk)->hdev; 6611da177e4SLinus Torvalds 6621da177e4SLinus Torvalds if (!hdev) 6631da177e4SLinus Torvalds return -EBADFD; 6641da177e4SLinus Torvalds 665d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) 6660736cfa8SMarcel Holtmann return -EBUSY; 6670736cfa8SMarcel Holtmann 668d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 669fee746b0SMarcel Holtmann return -EOPNOTSUPP; 670fee746b0SMarcel Holtmann 6715b69bef5SMarcel Holtmann if (hdev->dev_type != HCI_BREDR) 6725b69bef5SMarcel Holtmann return -EOPNOTSUPP; 6735b69bef5SMarcel Holtmann 6741da177e4SLinus Torvalds switch (cmd) { 6751da177e4SLinus Torvalds case HCISETRAW: 6761da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 677bf5b30b8SZhao Hongjiang return -EPERM; 678db596681SMarcel Holtmann return -EOPNOTSUPP; 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds case HCIGETCONNINFO: 6811da177e4SLinus Torvalds return hci_get_conn_info(hdev, (void __user *)arg); 6821da177e4SLinus Torvalds 68340be492fSMarcel Holtmann case HCIGETAUTHINFO: 68440be492fSMarcel Holtmann return hci_get_auth_info(hdev, (void __user *)arg); 68540be492fSMarcel Holtmann 686f0358568SJohan Hedberg case HCIBLOCKADDR: 687f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 688bf5b30b8SZhao Hongjiang return -EPERM; 689b2a66aadSAntti Julku return hci_sock_blacklist_add(hdev, (void __user *)arg); 690f0358568SJohan Hedberg 691f0358568SJohan Hedberg case HCIUNBLOCKADDR: 692f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 693bf5b30b8SZhao Hongjiang return -EPERM; 694b2a66aadSAntti Julku return hci_sock_blacklist_del(hdev, (void __user *)arg); 6950736cfa8SMarcel Holtmann } 696f0358568SJohan Hedberg 697324d36edSMarcel Holtmann return -ENOIOCTLCMD; 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds 7008fc9ced3SGustavo Padovan static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, 7018fc9ced3SGustavo Padovan unsigned long arg) 7021da177e4SLinus Torvalds { 7031da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 7040736cfa8SMarcel Holtmann struct sock *sk = sock->sk; 7051da177e4SLinus Torvalds int err; 7061da177e4SLinus Torvalds 7071da177e4SLinus Torvalds BT_DBG("cmd %x arg %lx", cmd, arg); 7081da177e4SLinus Torvalds 709c1c4f956SMarcel Holtmann lock_sock(sk); 710c1c4f956SMarcel Holtmann 711c1c4f956SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 712c1c4f956SMarcel Holtmann err = -EBADFD; 713c1c4f956SMarcel Holtmann goto done; 714c1c4f956SMarcel Holtmann } 715c1c4f956SMarcel Holtmann 716c1c4f956SMarcel Holtmann release_sock(sk); 717c1c4f956SMarcel Holtmann 7181da177e4SLinus Torvalds switch (cmd) { 7191da177e4SLinus Torvalds case HCIGETDEVLIST: 7201da177e4SLinus Torvalds return hci_get_dev_list(argp); 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds case HCIGETDEVINFO: 7231da177e4SLinus Torvalds return hci_get_dev_info(argp); 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds case HCIGETCONNLIST: 7261da177e4SLinus Torvalds return hci_get_conn_list(argp); 7271da177e4SLinus Torvalds 7281da177e4SLinus Torvalds case HCIDEVUP: 7291da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 730bf5b30b8SZhao Hongjiang return -EPERM; 7311da177e4SLinus Torvalds return hci_dev_open(arg); 7321da177e4SLinus Torvalds 7331da177e4SLinus Torvalds case HCIDEVDOWN: 7341da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 735bf5b30b8SZhao Hongjiang return -EPERM; 7361da177e4SLinus Torvalds return hci_dev_close(arg); 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds case HCIDEVRESET: 7391da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 740bf5b30b8SZhao Hongjiang return -EPERM; 7411da177e4SLinus Torvalds return hci_dev_reset(arg); 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds case HCIDEVRESTAT: 7441da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 745bf5b30b8SZhao Hongjiang return -EPERM; 7461da177e4SLinus Torvalds return hci_dev_reset_stat(arg); 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds case HCISETSCAN: 7491da177e4SLinus Torvalds case HCISETAUTH: 7501da177e4SLinus Torvalds case HCISETENCRYPT: 7511da177e4SLinus Torvalds case HCISETPTYPE: 7521da177e4SLinus Torvalds case HCISETLINKPOL: 7531da177e4SLinus Torvalds case HCISETLINKMODE: 7541da177e4SLinus Torvalds case HCISETACLMTU: 7551da177e4SLinus Torvalds case HCISETSCOMTU: 7561da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 757bf5b30b8SZhao Hongjiang return -EPERM; 7581da177e4SLinus Torvalds return hci_dev_cmd(cmd, argp); 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds case HCIINQUIRY: 7611da177e4SLinus Torvalds return hci_inquiry(argp); 762c1c4f956SMarcel Holtmann } 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds lock_sock(sk); 765c1c4f956SMarcel Holtmann 7661da177e4SLinus Torvalds err = hci_sock_bound_ioctl(sk, cmd, arg); 767c1c4f956SMarcel Holtmann 768c1c4f956SMarcel Holtmann done: 7691da177e4SLinus Torvalds release_sock(sk); 7701da177e4SLinus Torvalds return err; 7711da177e4SLinus Torvalds } 7721da177e4SLinus Torvalds 7738fc9ced3SGustavo Padovan static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, 7748fc9ced3SGustavo Padovan int addr_len) 7751da177e4SLinus Torvalds { 7760381101fSJohan Hedberg struct sockaddr_hci haddr; 7771da177e4SLinus Torvalds struct sock *sk = sock->sk; 7781da177e4SLinus Torvalds struct hci_dev *hdev = NULL; 7790381101fSJohan Hedberg int len, err = 0; 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 7821da177e4SLinus Torvalds 7830381101fSJohan Hedberg if (!addr) 7840381101fSJohan Hedberg return -EINVAL; 7850381101fSJohan Hedberg 7860381101fSJohan Hedberg memset(&haddr, 0, sizeof(haddr)); 7870381101fSJohan Hedberg len = min_t(unsigned int, sizeof(haddr), addr_len); 7880381101fSJohan Hedberg memcpy(&haddr, addr, len); 7890381101fSJohan Hedberg 7900381101fSJohan Hedberg if (haddr.hci_family != AF_BLUETOOTH) 7910381101fSJohan Hedberg return -EINVAL; 7920381101fSJohan Hedberg 7931da177e4SLinus Torvalds lock_sock(sk); 7941da177e4SLinus Torvalds 7957cc2ade2SMarcel Holtmann if (sk->sk_state == BT_BOUND) { 7967cc2ade2SMarcel Holtmann err = -EALREADY; 7977cc2ade2SMarcel Holtmann goto done; 7987cc2ade2SMarcel Holtmann } 7997cc2ade2SMarcel Holtmann 8007cc2ade2SMarcel Holtmann switch (haddr.hci_channel) { 8017cc2ade2SMarcel Holtmann case HCI_CHANNEL_RAW: 8027cc2ade2SMarcel Holtmann if (hci_pi(sk)->hdev) { 8031da177e4SLinus Torvalds err = -EALREADY; 8041da177e4SLinus Torvalds goto done; 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds 8070381101fSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 8080381101fSJohan Hedberg hdev = hci_dev_get(haddr.hci_dev); 80970f23020SAndrei Emeltchenko if (!hdev) { 8101da177e4SLinus Torvalds err = -ENODEV; 8111da177e4SLinus Torvalds goto done; 8121da177e4SLinus Torvalds } 8131da177e4SLinus Torvalds 8141da177e4SLinus Torvalds atomic_inc(&hdev->promisc); 8151da177e4SLinus Torvalds } 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds hci_pi(sk)->hdev = hdev; 8187cc2ade2SMarcel Holtmann break; 8197cc2ade2SMarcel Holtmann 82023500189SMarcel Holtmann case HCI_CHANNEL_USER: 82123500189SMarcel Holtmann if (hci_pi(sk)->hdev) { 82223500189SMarcel Holtmann err = -EALREADY; 82323500189SMarcel Holtmann goto done; 82423500189SMarcel Holtmann } 82523500189SMarcel Holtmann 82623500189SMarcel Holtmann if (haddr.hci_dev == HCI_DEV_NONE) { 82723500189SMarcel Holtmann err = -EINVAL; 82823500189SMarcel Holtmann goto done; 82923500189SMarcel Holtmann } 83023500189SMarcel Holtmann 83110a8b86fSMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 83223500189SMarcel Holtmann err = -EPERM; 83323500189SMarcel Holtmann goto done; 83423500189SMarcel Holtmann } 83523500189SMarcel Holtmann 83623500189SMarcel Holtmann hdev = hci_dev_get(haddr.hci_dev); 83723500189SMarcel Holtmann if (!hdev) { 83823500189SMarcel Holtmann err = -ENODEV; 83923500189SMarcel Holtmann goto done; 84023500189SMarcel Holtmann } 84123500189SMarcel Holtmann 842781f899fSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags) || 843d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_SETUP) || 844781f899fSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG) || 845781f899fSMarcel Holtmann (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) && 846781f899fSMarcel Holtmann test_bit(HCI_UP, &hdev->flags))) { 84723500189SMarcel Holtmann err = -EBUSY; 84823500189SMarcel Holtmann hci_dev_put(hdev); 84923500189SMarcel Holtmann goto done; 85023500189SMarcel Holtmann } 85123500189SMarcel Holtmann 852238be788SMarcel Holtmann if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) { 85323500189SMarcel Holtmann err = -EUSERS; 85423500189SMarcel Holtmann hci_dev_put(hdev); 85523500189SMarcel Holtmann goto done; 85623500189SMarcel Holtmann } 85723500189SMarcel Holtmann 85823500189SMarcel Holtmann mgmt_index_removed(hdev); 85923500189SMarcel Holtmann 86023500189SMarcel Holtmann err = hci_dev_open(hdev->id); 86123500189SMarcel Holtmann if (err) { 862781f899fSMarcel Holtmann if (err == -EALREADY) { 863781f899fSMarcel Holtmann /* In case the transport is already up and 864781f899fSMarcel Holtmann * running, clear the error here. 865781f899fSMarcel Holtmann * 866781f899fSMarcel Holtmann * This can happen when opening an user 867781f899fSMarcel Holtmann * channel and HCI_AUTO_OFF grace period 868781f899fSMarcel Holtmann * is still active. 869781f899fSMarcel Holtmann */ 870781f899fSMarcel Holtmann err = 0; 871781f899fSMarcel Holtmann } else { 872a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 873c6521401SMarcel Holtmann mgmt_index_added(hdev); 87423500189SMarcel Holtmann hci_dev_put(hdev); 87523500189SMarcel Holtmann goto done; 87623500189SMarcel Holtmann } 877781f899fSMarcel Holtmann } 87823500189SMarcel Holtmann 87923500189SMarcel Holtmann atomic_inc(&hdev->promisc); 88023500189SMarcel Holtmann 88123500189SMarcel Holtmann hci_pi(sk)->hdev = hdev; 88223500189SMarcel Holtmann break; 88323500189SMarcel Holtmann 884cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 885cd82e61cSMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 886cd82e61cSMarcel Holtmann err = -EINVAL; 887cd82e61cSMarcel Holtmann goto done; 888cd82e61cSMarcel Holtmann } 889cd82e61cSMarcel Holtmann 890cd82e61cSMarcel Holtmann if (!capable(CAP_NET_RAW)) { 891cd82e61cSMarcel Holtmann err = -EPERM; 892cd82e61cSMarcel Holtmann goto done; 893cd82e61cSMarcel Holtmann } 894cd82e61cSMarcel Holtmann 89550ebc055SMarcel Holtmann /* The monitor interface is restricted to CAP_NET_RAW 89650ebc055SMarcel Holtmann * capabilities and with that implicitly trusted. 89750ebc055SMarcel Holtmann */ 89850ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 89950ebc055SMarcel Holtmann 900dd31506dSMarcel Holtmann send_monitor_note(sk, "Linux version " UTS_RELEASE 901dd31506dSMarcel Holtmann " (" UTS_MACHINE ")"); 902dd31506dSMarcel Holtmann send_monitor_note(sk, "Bluetooth subsystem version " 903dd31506dSMarcel Holtmann BT_SUBSYS_VERSION); 904cd82e61cSMarcel Holtmann send_monitor_replay(sk); 905cd82e61cSMarcel Holtmann 906cd82e61cSMarcel Holtmann atomic_inc(&monitor_promisc); 907cd82e61cSMarcel Holtmann break; 908cd82e61cSMarcel Holtmann 909*ac714949SMarcel Holtmann case HCI_CHANNEL_LOGGING: 910*ac714949SMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 911*ac714949SMarcel Holtmann err = -EINVAL; 912*ac714949SMarcel Holtmann goto done; 913*ac714949SMarcel Holtmann } 914*ac714949SMarcel Holtmann 915*ac714949SMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 916*ac714949SMarcel Holtmann err = -EPERM; 917*ac714949SMarcel Holtmann goto done; 918*ac714949SMarcel Holtmann } 919*ac714949SMarcel Holtmann break; 920*ac714949SMarcel Holtmann 9217cc2ade2SMarcel Holtmann default: 922801c1e8dSJohan Hedberg if (!hci_mgmt_chan_find(haddr.hci_channel)) { 9237cc2ade2SMarcel Holtmann err = -EINVAL; 9247cc2ade2SMarcel Holtmann goto done; 9257cc2ade2SMarcel Holtmann } 9267cc2ade2SMarcel Holtmann 927801c1e8dSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 928801c1e8dSJohan Hedberg err = -EINVAL; 929801c1e8dSJohan Hedberg goto done; 930801c1e8dSJohan Hedberg } 931801c1e8dSJohan Hedberg 9321195fbb8SMarcel Holtmann /* Users with CAP_NET_ADMIN capabilities are allowed 9331195fbb8SMarcel Holtmann * access to all management commands and events. For 9341195fbb8SMarcel Holtmann * untrusted users the interface is restricted and 9351195fbb8SMarcel Holtmann * also only untrusted events are sent. 93650ebc055SMarcel Holtmann */ 9371195fbb8SMarcel Holtmann if (capable(CAP_NET_ADMIN)) 93850ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 93950ebc055SMarcel Holtmann 940f9207338SMarcel Holtmann /* At the moment the index and unconfigured index events 941f9207338SMarcel Holtmann * are enabled unconditionally. Setting them on each 942f9207338SMarcel Holtmann * socket when binding keeps this functionality. They 943f9207338SMarcel Holtmann * however might be cleared later and then sending of these 944f9207338SMarcel Holtmann * events will be disabled, but that is then intentional. 945f6b7712eSMarcel Holtmann * 946f6b7712eSMarcel Holtmann * This also enables generic events that are safe to be 947f6b7712eSMarcel Holtmann * received by untrusted users. Example for such events 948f6b7712eSMarcel Holtmann * are changes to settings, class of device, name etc. 949f9207338SMarcel Holtmann */ 950f9207338SMarcel Holtmann if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { 951f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); 952f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); 953f6b7712eSMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS); 954f9207338SMarcel Holtmann } 955801c1e8dSJohan Hedberg break; 956801c1e8dSJohan Hedberg } 957801c1e8dSJohan Hedberg 9587cc2ade2SMarcel Holtmann 9597cc2ade2SMarcel Holtmann hci_pi(sk)->channel = haddr.hci_channel; 9601da177e4SLinus Torvalds sk->sk_state = BT_BOUND; 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds done: 9631da177e4SLinus Torvalds release_sock(sk); 9641da177e4SLinus Torvalds return err; 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9678fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, 9688fc9ced3SGustavo Padovan int *addr_len, int peer) 9691da177e4SLinus Torvalds { 9701da177e4SLinus Torvalds struct sockaddr_hci *haddr = (struct sockaddr_hci *)addr; 9711da177e4SLinus Torvalds struct sock *sk = sock->sk; 9729d4b68b2SMarcel Holtmann struct hci_dev *hdev; 9739d4b68b2SMarcel Holtmann int err = 0; 9741da177e4SLinus Torvalds 9751da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 9761da177e4SLinus Torvalds 97706f43cbcSMarcel Holtmann if (peer) 97806f43cbcSMarcel Holtmann return -EOPNOTSUPP; 97906f43cbcSMarcel Holtmann 9801da177e4SLinus Torvalds lock_sock(sk); 9811da177e4SLinus Torvalds 9829d4b68b2SMarcel Holtmann hdev = hci_pi(sk)->hdev; 9839d4b68b2SMarcel Holtmann if (!hdev) { 9849d4b68b2SMarcel Holtmann err = -EBADFD; 9859d4b68b2SMarcel Holtmann goto done; 9869d4b68b2SMarcel Holtmann } 9879d4b68b2SMarcel Holtmann 9881da177e4SLinus Torvalds *addr_len = sizeof(*haddr); 9891da177e4SLinus Torvalds haddr->hci_family = AF_BLUETOOTH; 9907b005bd3SMarcel Holtmann haddr->hci_dev = hdev->id; 9919d4b68b2SMarcel Holtmann haddr->hci_channel= hci_pi(sk)->channel; 9921da177e4SLinus Torvalds 9939d4b68b2SMarcel Holtmann done: 9941da177e4SLinus Torvalds release_sock(sk); 9959d4b68b2SMarcel Holtmann return err; 9961da177e4SLinus Torvalds } 9971da177e4SLinus Torvalds 9986039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, 9996039aa73SGustavo Padovan struct sk_buff *skb) 10001da177e4SLinus Torvalds { 10011da177e4SLinus Torvalds __u32 mask = hci_pi(sk)->cmsg_mask; 10021da177e4SLinus Torvalds 10030d48d939SMarcel Holtmann if (mask & HCI_CMSG_DIR) { 10040d48d939SMarcel Holtmann int incoming = bt_cb(skb)->incoming; 10058fc9ced3SGustavo Padovan put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), 10068fc9ced3SGustavo Padovan &incoming); 10070d48d939SMarcel Holtmann } 10081da177e4SLinus Torvalds 1009a61bbcf2SPatrick McHardy if (mask & HCI_CMSG_TSTAMP) { 1010f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT 1011f6e623a6SJohann Felix Soden struct compat_timeval ctv; 1012f6e623a6SJohann Felix Soden #endif 1013a61bbcf2SPatrick McHardy struct timeval tv; 1014767c5eb5SMarcel Holtmann void *data; 1015767c5eb5SMarcel Holtmann int len; 1016a61bbcf2SPatrick McHardy 1017a61bbcf2SPatrick McHardy skb_get_timestamp(skb, &tv); 1018767c5eb5SMarcel Holtmann 10191da97f83SDavid S. Miller data = &tv; 10201da97f83SDavid S. Miller len = sizeof(tv); 10211da97f83SDavid S. Miller #ifdef CONFIG_COMPAT 1022da88cea1SH. J. Lu if (!COMPAT_USE_64BIT_TIME && 1023da88cea1SH. J. Lu (msg->msg_flags & MSG_CMSG_COMPAT)) { 1024767c5eb5SMarcel Holtmann ctv.tv_sec = tv.tv_sec; 1025767c5eb5SMarcel Holtmann ctv.tv_usec = tv.tv_usec; 1026767c5eb5SMarcel Holtmann data = &ctv; 1027767c5eb5SMarcel Holtmann len = sizeof(ctv); 1028767c5eb5SMarcel Holtmann } 10291da97f83SDavid S. Miller #endif 1030767c5eb5SMarcel Holtmann 1031767c5eb5SMarcel Holtmann put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 1032a61bbcf2SPatrick McHardy } 10331da177e4SLinus Torvalds } 10341da177e4SLinus Torvalds 10358528d3f7SMarcel Holtmann static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, 10368528d3f7SMarcel Holtmann size_t len, int flags) 10371da177e4SLinus Torvalds { 10381da177e4SLinus Torvalds int noblock = flags & MSG_DONTWAIT; 10391da177e4SLinus Torvalds struct sock *sk = sock->sk; 10401da177e4SLinus Torvalds struct sk_buff *skb; 10411da177e4SLinus Torvalds int copied, err; 10421da177e4SLinus Torvalds 10431da177e4SLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 10441da177e4SLinus Torvalds 1045d94a6104SMarcel Holtmann if (flags & MSG_OOB) 10461da177e4SLinus Torvalds return -EOPNOTSUPP; 10471da177e4SLinus Torvalds 1048*ac714949SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_LOGGING) 1049*ac714949SMarcel Holtmann return -EOPNOTSUPP; 1050*ac714949SMarcel Holtmann 10511da177e4SLinus Torvalds if (sk->sk_state == BT_CLOSED) 10521da177e4SLinus Torvalds return 0; 10531da177e4SLinus Torvalds 105470f23020SAndrei Emeltchenko skb = skb_recv_datagram(sk, flags, noblock, &err); 105570f23020SAndrei Emeltchenko if (!skb) 10561da177e4SLinus Torvalds return err; 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds copied = skb->len; 10591da177e4SLinus Torvalds if (len < copied) { 10601da177e4SLinus Torvalds msg->msg_flags |= MSG_TRUNC; 10611da177e4SLinus Torvalds copied = len; 10621da177e4SLinus Torvalds } 10631da177e4SLinus Torvalds 1064badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb); 106551f3d02bSDavid S. Miller err = skb_copy_datagram_msg(skb, 0, msg, copied); 10661da177e4SLinus Torvalds 10673a208627SMarcel Holtmann switch (hci_pi(sk)->channel) { 10683a208627SMarcel Holtmann case HCI_CHANNEL_RAW: 10691da177e4SLinus Torvalds hci_sock_cmsg(sk, msg, skb); 10703a208627SMarcel Holtmann break; 107123500189SMarcel Holtmann case HCI_CHANNEL_USER: 1072cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1073cd82e61cSMarcel Holtmann sock_recv_timestamp(msg, sk, skb); 1074cd82e61cSMarcel Holtmann break; 1075801c1e8dSJohan Hedberg default: 1076801c1e8dSJohan Hedberg if (hci_mgmt_chan_find(hci_pi(sk)->channel)) 1077801c1e8dSJohan Hedberg sock_recv_timestamp(msg, sk, skb); 1078801c1e8dSJohan Hedberg break; 10793a208627SMarcel Holtmann } 10801da177e4SLinus Torvalds 10811da177e4SLinus Torvalds skb_free_datagram(sk, skb); 10821da177e4SLinus Torvalds 10831da177e4SLinus Torvalds return err ? : copied; 10841da177e4SLinus Torvalds } 10851da177e4SLinus Torvalds 1086fa4335d7SJohan Hedberg static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, 1087fa4335d7SJohan Hedberg struct msghdr *msg, size_t msglen) 1088fa4335d7SJohan Hedberg { 1089fa4335d7SJohan Hedberg void *buf; 1090fa4335d7SJohan Hedberg u8 *cp; 1091fa4335d7SJohan Hedberg struct mgmt_hdr *hdr; 1092fa4335d7SJohan Hedberg u16 opcode, index, len; 1093fa4335d7SJohan Hedberg struct hci_dev *hdev = NULL; 1094fa4335d7SJohan Hedberg const struct hci_mgmt_handler *handler; 1095fa4335d7SJohan Hedberg bool var_len, no_hdev; 1096fa4335d7SJohan Hedberg int err; 1097fa4335d7SJohan Hedberg 1098fa4335d7SJohan Hedberg BT_DBG("got %zu bytes", msglen); 1099fa4335d7SJohan Hedberg 1100fa4335d7SJohan Hedberg if (msglen < sizeof(*hdr)) 1101fa4335d7SJohan Hedberg return -EINVAL; 1102fa4335d7SJohan Hedberg 1103fa4335d7SJohan Hedberg buf = kmalloc(msglen, GFP_KERNEL); 1104fa4335d7SJohan Hedberg if (!buf) 1105fa4335d7SJohan Hedberg return -ENOMEM; 1106fa4335d7SJohan Hedberg 1107fa4335d7SJohan Hedberg if (memcpy_from_msg(buf, msg, msglen)) { 1108fa4335d7SJohan Hedberg err = -EFAULT; 1109fa4335d7SJohan Hedberg goto done; 1110fa4335d7SJohan Hedberg } 1111fa4335d7SJohan Hedberg 1112fa4335d7SJohan Hedberg hdr = buf; 1113fa4335d7SJohan Hedberg opcode = __le16_to_cpu(hdr->opcode); 1114fa4335d7SJohan Hedberg index = __le16_to_cpu(hdr->index); 1115fa4335d7SJohan Hedberg len = __le16_to_cpu(hdr->len); 1116fa4335d7SJohan Hedberg 1117fa4335d7SJohan Hedberg if (len != msglen - sizeof(*hdr)) { 1118fa4335d7SJohan Hedberg err = -EINVAL; 1119fa4335d7SJohan Hedberg goto done; 1120fa4335d7SJohan Hedberg } 1121fa4335d7SJohan Hedberg 1122fa4335d7SJohan Hedberg if (opcode >= chan->handler_count || 1123fa4335d7SJohan Hedberg chan->handlers[opcode].func == NULL) { 1124fa4335d7SJohan Hedberg BT_DBG("Unknown op %u", opcode); 1125fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1126fa4335d7SJohan Hedberg MGMT_STATUS_UNKNOWN_COMMAND); 1127fa4335d7SJohan Hedberg goto done; 1128fa4335d7SJohan Hedberg } 1129fa4335d7SJohan Hedberg 1130fa4335d7SJohan Hedberg handler = &chan->handlers[opcode]; 1131fa4335d7SJohan Hedberg 1132fa4335d7SJohan Hedberg if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && 1133fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNTRUSTED)) { 1134fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1135fa4335d7SJohan Hedberg MGMT_STATUS_PERMISSION_DENIED); 1136fa4335d7SJohan Hedberg goto done; 1137fa4335d7SJohan Hedberg } 1138fa4335d7SJohan Hedberg 1139fa4335d7SJohan Hedberg if (index != MGMT_INDEX_NONE) { 1140fa4335d7SJohan Hedberg hdev = hci_dev_get(index); 1141fa4335d7SJohan Hedberg if (!hdev) { 1142fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1143fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1144fa4335d7SJohan Hedberg goto done; 1145fa4335d7SJohan Hedberg } 1146fa4335d7SJohan Hedberg 1147fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_SETUP) || 1148fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_CONFIG) || 1149fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 1150fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1151fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1152fa4335d7SJohan Hedberg goto done; 1153fa4335d7SJohan Hedberg } 1154fa4335d7SJohan Hedberg 1155fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 1156fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNCONFIGURED)) { 1157fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1158fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1159fa4335d7SJohan Hedberg goto done; 1160fa4335d7SJohan Hedberg } 1161fa4335d7SJohan Hedberg } 1162fa4335d7SJohan Hedberg 1163fa4335d7SJohan Hedberg no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); 1164fa4335d7SJohan Hedberg if (no_hdev != !hdev) { 1165fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1166fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1167fa4335d7SJohan Hedberg goto done; 1168fa4335d7SJohan Hedberg } 1169fa4335d7SJohan Hedberg 1170fa4335d7SJohan Hedberg var_len = (handler->flags & HCI_MGMT_VAR_LEN); 1171fa4335d7SJohan Hedberg if ((var_len && len < handler->data_len) || 1172fa4335d7SJohan Hedberg (!var_len && len != handler->data_len)) { 1173fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1174fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_PARAMS); 1175fa4335d7SJohan Hedberg goto done; 1176fa4335d7SJohan Hedberg } 1177fa4335d7SJohan Hedberg 1178fa4335d7SJohan Hedberg if (hdev && chan->hdev_init) 1179fa4335d7SJohan Hedberg chan->hdev_init(sk, hdev); 1180fa4335d7SJohan Hedberg 1181fa4335d7SJohan Hedberg cp = buf + sizeof(*hdr); 1182fa4335d7SJohan Hedberg 1183fa4335d7SJohan Hedberg err = handler->func(sk, hdev, cp, len); 1184fa4335d7SJohan Hedberg if (err < 0) 1185fa4335d7SJohan Hedberg goto done; 1186fa4335d7SJohan Hedberg 1187fa4335d7SJohan Hedberg err = msglen; 1188fa4335d7SJohan Hedberg 1189fa4335d7SJohan Hedberg done: 1190fa4335d7SJohan Hedberg if (hdev) 1191fa4335d7SJohan Hedberg hci_dev_put(hdev); 1192fa4335d7SJohan Hedberg 1193fa4335d7SJohan Hedberg kfree(buf); 1194fa4335d7SJohan Hedberg return err; 1195fa4335d7SJohan Hedberg } 1196fa4335d7SJohan Hedberg 1197*ac714949SMarcel Holtmann static int hci_logging_frame(struct sock *sk, struct msghdr *msg, int len) 1198*ac714949SMarcel Holtmann { 1199*ac714949SMarcel Holtmann struct hci_mon_hdr *hdr; 1200*ac714949SMarcel Holtmann struct sk_buff *skb; 1201*ac714949SMarcel Holtmann struct hci_dev *hdev; 1202*ac714949SMarcel Holtmann u16 index; 1203*ac714949SMarcel Holtmann int err; 1204*ac714949SMarcel Holtmann 1205*ac714949SMarcel Holtmann /* The logging frame consists at minimum of the standard header, 1206*ac714949SMarcel Holtmann * the priority byte, the ident length byte and at least one string 1207*ac714949SMarcel Holtmann * terminator NUL byte. Anything shorter are invalid packets. 1208*ac714949SMarcel Holtmann */ 1209*ac714949SMarcel Holtmann if (len < sizeof(*hdr) + 3) 1210*ac714949SMarcel Holtmann return -EINVAL; 1211*ac714949SMarcel Holtmann 1212*ac714949SMarcel Holtmann skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 1213*ac714949SMarcel Holtmann if (!skb) 1214*ac714949SMarcel Holtmann return err; 1215*ac714949SMarcel Holtmann 1216*ac714949SMarcel Holtmann if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 1217*ac714949SMarcel Holtmann err = -EFAULT; 1218*ac714949SMarcel Holtmann goto drop; 1219*ac714949SMarcel Holtmann } 1220*ac714949SMarcel Holtmann 1221*ac714949SMarcel Holtmann hdr = (void *)skb->data; 1222*ac714949SMarcel Holtmann 1223*ac714949SMarcel Holtmann if (__le16_to_cpu(hdr->len) != len - sizeof(*hdr)) { 1224*ac714949SMarcel Holtmann err = -EINVAL; 1225*ac714949SMarcel Holtmann goto drop; 1226*ac714949SMarcel Holtmann } 1227*ac714949SMarcel Holtmann 1228*ac714949SMarcel Holtmann if (__le16_to_cpu(hdr->opcode) == 0x0000) { 1229*ac714949SMarcel Holtmann __u8 priority = skb->data[sizeof(*hdr)]; 1230*ac714949SMarcel Holtmann __u8 ident_len = skb->data[sizeof(*hdr) + 1]; 1231*ac714949SMarcel Holtmann 1232*ac714949SMarcel Holtmann /* Only the priorities 0-7 are valid and with that any other 1233*ac714949SMarcel Holtmann * value results in an invalid packet. 1234*ac714949SMarcel Holtmann * 1235*ac714949SMarcel Holtmann * The priority byte is followed by an ident length byte and 1236*ac714949SMarcel Holtmann * the NUL terminated ident string. Check that the ident 1237*ac714949SMarcel Holtmann * length is not overflowing the packet and also that the 1238*ac714949SMarcel Holtmann * ident string itself is NUL terminated. In case the ident 1239*ac714949SMarcel Holtmann * length is zero, the length value actually doubles as NUL 1240*ac714949SMarcel Holtmann * terminator identifier. 1241*ac714949SMarcel Holtmann * 1242*ac714949SMarcel Holtmann * The message follows the ident string (if present) and 1243*ac714949SMarcel Holtmann * must be NUL terminated. Otherwise it is not a valid packet. 1244*ac714949SMarcel Holtmann */ 1245*ac714949SMarcel Holtmann if (priority > 7 || skb->data[len - 1] != 0x00 || 1246*ac714949SMarcel Holtmann ident_len > len - sizeof(*hdr) - 3 || 1247*ac714949SMarcel Holtmann skb->data[sizeof(*hdr) + ident_len + 1] != 0x00) { 1248*ac714949SMarcel Holtmann err = -EINVAL; 1249*ac714949SMarcel Holtmann goto drop; 1250*ac714949SMarcel Holtmann } 1251*ac714949SMarcel Holtmann } else { 1252*ac714949SMarcel Holtmann err = -EINVAL; 1253*ac714949SMarcel Holtmann goto drop; 1254*ac714949SMarcel Holtmann } 1255*ac714949SMarcel Holtmann 1256*ac714949SMarcel Holtmann index = __le16_to_cpu(hdr->index); 1257*ac714949SMarcel Holtmann 1258*ac714949SMarcel Holtmann if (index != MGMT_INDEX_NONE) { 1259*ac714949SMarcel Holtmann hdev = hci_dev_get(index); 1260*ac714949SMarcel Holtmann if (!hdev) { 1261*ac714949SMarcel Holtmann err = -ENODEV; 1262*ac714949SMarcel Holtmann goto drop; 1263*ac714949SMarcel Holtmann } 1264*ac714949SMarcel Holtmann } else { 1265*ac714949SMarcel Holtmann hdev = NULL; 1266*ac714949SMarcel Holtmann } 1267*ac714949SMarcel Holtmann 1268*ac714949SMarcel Holtmann hdr->opcode = cpu_to_le16(HCI_MON_USER_LOGGING); 1269*ac714949SMarcel Holtmann 1270*ac714949SMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, HCI_SOCK_TRUSTED, NULL); 1271*ac714949SMarcel Holtmann err = len; 1272*ac714949SMarcel Holtmann 1273*ac714949SMarcel Holtmann if (hdev) 1274*ac714949SMarcel Holtmann hci_dev_put(hdev); 1275*ac714949SMarcel Holtmann 1276*ac714949SMarcel Holtmann drop: 1277*ac714949SMarcel Holtmann kfree_skb(skb); 1278*ac714949SMarcel Holtmann return err; 1279*ac714949SMarcel Holtmann } 1280*ac714949SMarcel Holtmann 12811b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, 12821b784140SYing Xue size_t len) 12831da177e4SLinus Torvalds { 12841da177e4SLinus Torvalds struct sock *sk = sock->sk; 1285801c1e8dSJohan Hedberg struct hci_mgmt_chan *chan; 12861da177e4SLinus Torvalds struct hci_dev *hdev; 12871da177e4SLinus Torvalds struct sk_buff *skb; 12881da177e4SLinus Torvalds int err; 12891da177e4SLinus Torvalds 12901da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 12911da177e4SLinus Torvalds 12921da177e4SLinus Torvalds if (msg->msg_flags & MSG_OOB) 12931da177e4SLinus Torvalds return -EOPNOTSUPP; 12941da177e4SLinus Torvalds 12951da177e4SLinus Torvalds if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 12961da177e4SLinus Torvalds return -EINVAL; 12971da177e4SLinus Torvalds 12981da177e4SLinus Torvalds if (len < 4 || len > HCI_MAX_FRAME_SIZE) 12991da177e4SLinus Torvalds return -EINVAL; 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds lock_sock(sk); 13021da177e4SLinus Torvalds 13030381101fSJohan Hedberg switch (hci_pi(sk)->channel) { 13040381101fSJohan Hedberg case HCI_CHANNEL_RAW: 130523500189SMarcel Holtmann case HCI_CHANNEL_USER: 13060381101fSJohan Hedberg break; 1307cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1308cd82e61cSMarcel Holtmann err = -EOPNOTSUPP; 1309cd82e61cSMarcel Holtmann goto done; 1310*ac714949SMarcel Holtmann case HCI_CHANNEL_LOGGING: 1311*ac714949SMarcel Holtmann err = hci_logging_frame(sk, msg, len); 1312*ac714949SMarcel Holtmann goto done; 13130381101fSJohan Hedberg default: 1314801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 1315801c1e8dSJohan Hedberg chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); 1316801c1e8dSJohan Hedberg if (chan) 1317fa4335d7SJohan Hedberg err = hci_mgmt_cmd(chan, sk, msg, len); 1318801c1e8dSJohan Hedberg else 13190381101fSJohan Hedberg err = -EINVAL; 1320801c1e8dSJohan Hedberg 1321801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 13220381101fSJohan Hedberg goto done; 13230381101fSJohan Hedberg } 13240381101fSJohan Hedberg 132570f23020SAndrei Emeltchenko hdev = hci_pi(sk)->hdev; 132670f23020SAndrei Emeltchenko if (!hdev) { 13271da177e4SLinus Torvalds err = -EBADFD; 13281da177e4SLinus Torvalds goto done; 13291da177e4SLinus Torvalds } 13301da177e4SLinus Torvalds 13317e21addcSMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) { 13327e21addcSMarcel Holtmann err = -ENETDOWN; 13337e21addcSMarcel Holtmann goto done; 13347e21addcSMarcel Holtmann } 13357e21addcSMarcel Holtmann 133670f23020SAndrei Emeltchenko skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 133770f23020SAndrei Emeltchenko if (!skb) 13381da177e4SLinus Torvalds goto done; 13391da177e4SLinus Torvalds 13406ce8e9ceSAl Viro if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 13411da177e4SLinus Torvalds err = -EFAULT; 13421da177e4SLinus Torvalds goto drop; 13431da177e4SLinus Torvalds } 13441da177e4SLinus Torvalds 13458528d3f7SMarcel Holtmann hci_skb_pkt_type(skb) = skb->data[0]; 13461da177e4SLinus Torvalds skb_pull(skb, 1); 13471da177e4SLinus Torvalds 13481bc5ad16SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 13491bc5ad16SMarcel Holtmann /* No permission check is needed for user channel 13501bc5ad16SMarcel Holtmann * since that gets enforced when binding the socket. 13511bc5ad16SMarcel Holtmann * 13521bc5ad16SMarcel Holtmann * However check that the packet type is valid. 13531bc5ad16SMarcel Holtmann */ 1354d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && 1355d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 1356d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { 13571bc5ad16SMarcel Holtmann err = -EINVAL; 13581bc5ad16SMarcel Holtmann goto drop; 13591bc5ad16SMarcel Holtmann } 13601bc5ad16SMarcel Holtmann 13611bc5ad16SMarcel Holtmann skb_queue_tail(&hdev->raw_q, skb); 13621bc5ad16SMarcel Holtmann queue_work(hdev->workqueue, &hdev->tx_work); 1363d79f34e3SMarcel Holtmann } else if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) { 136483985319SHarvey Harrison u16 opcode = get_unaligned_le16(skb->data); 13651da177e4SLinus Torvalds u16 ogf = hci_opcode_ogf(opcode); 13661da177e4SLinus Torvalds u16 ocf = hci_opcode_ocf(opcode); 13671da177e4SLinus Torvalds 13681da177e4SLinus Torvalds if (((ogf > HCI_SFLT_MAX_OGF) || 13693bb3c755SGustavo Padovan !hci_test_bit(ocf & HCI_FLT_OCF_BITS, 13703bb3c755SGustavo Padovan &hci_sec_filter.ocf_mask[ogf])) && 13711da177e4SLinus Torvalds !capable(CAP_NET_RAW)) { 13721da177e4SLinus Torvalds err = -EPERM; 13731da177e4SLinus Torvalds goto drop; 13741da177e4SLinus Torvalds } 13751da177e4SLinus Torvalds 13761982162bSMarcel Holtmann /* Since the opcode has already been extracted here, store 13771982162bSMarcel Holtmann * a copy of the value for later use by the drivers. 13781982162bSMarcel Holtmann */ 13791982162bSMarcel Holtmann hci_skb_opcode(skb) = opcode; 13801982162bSMarcel Holtmann 1381fee746b0SMarcel Holtmann if (ogf == 0x3f) { 13821da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 13833eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 13841da177e4SLinus Torvalds } else { 138549c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as 138611714b3dSJohan Hedberg * single-command requests. 138711714b3dSJohan Hedberg */ 138844d27137SJohan Hedberg bt_cb(skb)->hci.req_flags |= HCI_REQ_START; 138911714b3dSJohan Hedberg 13901da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb); 1391c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 13921da177e4SLinus Torvalds } 13931da177e4SLinus Torvalds } else { 13941da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 13951da177e4SLinus Torvalds err = -EPERM; 13961da177e4SLinus Torvalds goto drop; 13971da177e4SLinus Torvalds } 13981da177e4SLinus Torvalds 1399d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 1400d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { 1401bb77543eSMarcel Holtmann err = -EINVAL; 1402bb77543eSMarcel Holtmann goto drop; 1403bb77543eSMarcel Holtmann } 1404bb77543eSMarcel Holtmann 14051da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 14063eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 14071da177e4SLinus Torvalds } 14081da177e4SLinus Torvalds 14091da177e4SLinus Torvalds err = len; 14101da177e4SLinus Torvalds 14111da177e4SLinus Torvalds done: 14121da177e4SLinus Torvalds release_sock(sk); 14131da177e4SLinus Torvalds return err; 14141da177e4SLinus Torvalds 14151da177e4SLinus Torvalds drop: 14161da177e4SLinus Torvalds kfree_skb(skb); 14171da177e4SLinus Torvalds goto done; 14181da177e4SLinus Torvalds } 14191da177e4SLinus Torvalds 14208fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname, 14218fc9ced3SGustavo Padovan char __user *optval, unsigned int len) 14221da177e4SLinus Torvalds { 14231da177e4SLinus Torvalds struct hci_ufilter uf = { .opcode = 0 }; 14241da177e4SLinus Torvalds struct sock *sk = sock->sk; 14251da177e4SLinus Torvalds int err = 0, opt = 0; 14261da177e4SLinus Torvalds 14271da177e4SLinus Torvalds BT_DBG("sk %p, opt %d", sk, optname); 14281da177e4SLinus Torvalds 14291da177e4SLinus Torvalds lock_sock(sk); 14301da177e4SLinus Torvalds 14312f39cdb7SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1432c2371e80SMarcel Holtmann err = -EBADFD; 14332f39cdb7SMarcel Holtmann goto done; 14342f39cdb7SMarcel Holtmann } 14352f39cdb7SMarcel Holtmann 14361da177e4SLinus Torvalds switch (optname) { 14371da177e4SLinus Torvalds case HCI_DATA_DIR: 14381da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 14391da177e4SLinus Torvalds err = -EFAULT; 14401da177e4SLinus Torvalds break; 14411da177e4SLinus Torvalds } 14421da177e4SLinus Torvalds 14431da177e4SLinus Torvalds if (opt) 14441da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 14451da177e4SLinus Torvalds else 14461da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 14471da177e4SLinus Torvalds break; 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds case HCI_TIME_STAMP: 14501da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 14511da177e4SLinus Torvalds err = -EFAULT; 14521da177e4SLinus Torvalds break; 14531da177e4SLinus Torvalds } 14541da177e4SLinus Torvalds 14551da177e4SLinus Torvalds if (opt) 14561da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 14571da177e4SLinus Torvalds else 14581da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 14591da177e4SLinus Torvalds break; 14601da177e4SLinus Torvalds 14611da177e4SLinus Torvalds case HCI_FILTER: 14620878b666SMarcel Holtmann { 14630878b666SMarcel Holtmann struct hci_filter *f = &hci_pi(sk)->filter; 14640878b666SMarcel Holtmann 14650878b666SMarcel Holtmann uf.type_mask = f->type_mask; 14660878b666SMarcel Holtmann uf.opcode = f->opcode; 14670878b666SMarcel Holtmann uf.event_mask[0] = *((u32 *) f->event_mask + 0); 14680878b666SMarcel Holtmann uf.event_mask[1] = *((u32 *) f->event_mask + 1); 14690878b666SMarcel Holtmann } 14700878b666SMarcel Holtmann 14711da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 14721da177e4SLinus Torvalds if (copy_from_user(&uf, optval, len)) { 14731da177e4SLinus Torvalds err = -EFAULT; 14741da177e4SLinus Torvalds break; 14751da177e4SLinus Torvalds } 14761da177e4SLinus Torvalds 14771da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 14781da177e4SLinus Torvalds uf.type_mask &= hci_sec_filter.type_mask; 14791da177e4SLinus Torvalds uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 14801da177e4SLinus Torvalds uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 14811da177e4SLinus Torvalds } 14821da177e4SLinus Torvalds 14831da177e4SLinus Torvalds { 14841da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds f->type_mask = uf.type_mask; 14871da177e4SLinus Torvalds f->opcode = uf.opcode; 14881da177e4SLinus Torvalds *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 14891da177e4SLinus Torvalds *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 14901da177e4SLinus Torvalds } 14911da177e4SLinus Torvalds break; 14921da177e4SLinus Torvalds 14931da177e4SLinus Torvalds default: 14941da177e4SLinus Torvalds err = -ENOPROTOOPT; 14951da177e4SLinus Torvalds break; 14961da177e4SLinus Torvalds } 14971da177e4SLinus Torvalds 14982f39cdb7SMarcel Holtmann done: 14991da177e4SLinus Torvalds release_sock(sk); 15001da177e4SLinus Torvalds return err; 15011da177e4SLinus Torvalds } 15021da177e4SLinus Torvalds 15038fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname, 15048fc9ced3SGustavo Padovan char __user *optval, int __user *optlen) 15051da177e4SLinus Torvalds { 15061da177e4SLinus Torvalds struct hci_ufilter uf; 15071da177e4SLinus Torvalds struct sock *sk = sock->sk; 1508cedc5469SMarcel Holtmann int len, opt, err = 0; 1509cedc5469SMarcel Holtmann 1510cedc5469SMarcel Holtmann BT_DBG("sk %p, opt %d", sk, optname); 15111da177e4SLinus Torvalds 15121da177e4SLinus Torvalds if (get_user(len, optlen)) 15131da177e4SLinus Torvalds return -EFAULT; 15141da177e4SLinus Torvalds 1515cedc5469SMarcel Holtmann lock_sock(sk); 1516cedc5469SMarcel Holtmann 1517cedc5469SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1518c2371e80SMarcel Holtmann err = -EBADFD; 1519cedc5469SMarcel Holtmann goto done; 1520cedc5469SMarcel Holtmann } 1521cedc5469SMarcel Holtmann 15221da177e4SLinus Torvalds switch (optname) { 15231da177e4SLinus Torvalds case HCI_DATA_DIR: 15241da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 15251da177e4SLinus Torvalds opt = 1; 15261da177e4SLinus Torvalds else 15271da177e4SLinus Torvalds opt = 0; 15281da177e4SLinus Torvalds 15291da177e4SLinus Torvalds if (put_user(opt, optval)) 1530cedc5469SMarcel Holtmann err = -EFAULT; 15311da177e4SLinus Torvalds break; 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds case HCI_TIME_STAMP: 15341da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 15351da177e4SLinus Torvalds opt = 1; 15361da177e4SLinus Torvalds else 15371da177e4SLinus Torvalds opt = 0; 15381da177e4SLinus Torvalds 15391da177e4SLinus Torvalds if (put_user(opt, optval)) 1540cedc5469SMarcel Holtmann err = -EFAULT; 15411da177e4SLinus Torvalds break; 15421da177e4SLinus Torvalds 15431da177e4SLinus Torvalds case HCI_FILTER: 15441da177e4SLinus Torvalds { 15451da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 15461da177e4SLinus Torvalds 1547e15ca9a0SMathias Krause memset(&uf, 0, sizeof(uf)); 15481da177e4SLinus Torvalds uf.type_mask = f->type_mask; 15491da177e4SLinus Torvalds uf.opcode = f->opcode; 15501da177e4SLinus Torvalds uf.event_mask[0] = *((u32 *) f->event_mask + 0); 15511da177e4SLinus Torvalds uf.event_mask[1] = *((u32 *) f->event_mask + 1); 15521da177e4SLinus Torvalds } 15531da177e4SLinus Torvalds 15541da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 15551da177e4SLinus Torvalds if (copy_to_user(optval, &uf, len)) 1556cedc5469SMarcel Holtmann err = -EFAULT; 15571da177e4SLinus Torvalds break; 15581da177e4SLinus Torvalds 15591da177e4SLinus Torvalds default: 1560cedc5469SMarcel Holtmann err = -ENOPROTOOPT; 15611da177e4SLinus Torvalds break; 15621da177e4SLinus Torvalds } 15631da177e4SLinus Torvalds 1564cedc5469SMarcel Holtmann done: 1565cedc5469SMarcel Holtmann release_sock(sk); 1566cedc5469SMarcel Holtmann return err; 15671da177e4SLinus Torvalds } 15681da177e4SLinus Torvalds 156990ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = { 15701da177e4SLinus Torvalds .family = PF_BLUETOOTH, 15711da177e4SLinus Torvalds .owner = THIS_MODULE, 15721da177e4SLinus Torvalds .release = hci_sock_release, 15731da177e4SLinus Torvalds .bind = hci_sock_bind, 15741da177e4SLinus Torvalds .getname = hci_sock_getname, 15751da177e4SLinus Torvalds .sendmsg = hci_sock_sendmsg, 15761da177e4SLinus Torvalds .recvmsg = hci_sock_recvmsg, 15771da177e4SLinus Torvalds .ioctl = hci_sock_ioctl, 15781da177e4SLinus Torvalds .poll = datagram_poll, 15791da177e4SLinus Torvalds .listen = sock_no_listen, 15801da177e4SLinus Torvalds .shutdown = sock_no_shutdown, 15811da177e4SLinus Torvalds .setsockopt = hci_sock_setsockopt, 15821da177e4SLinus Torvalds .getsockopt = hci_sock_getsockopt, 15831da177e4SLinus Torvalds .connect = sock_no_connect, 15841da177e4SLinus Torvalds .socketpair = sock_no_socketpair, 15851da177e4SLinus Torvalds .accept = sock_no_accept, 15861da177e4SLinus Torvalds .mmap = sock_no_mmap 15871da177e4SLinus Torvalds }; 15881da177e4SLinus Torvalds 15891da177e4SLinus Torvalds static struct proto hci_sk_proto = { 15901da177e4SLinus Torvalds .name = "HCI", 15911da177e4SLinus Torvalds .owner = THIS_MODULE, 15921da177e4SLinus Torvalds .obj_size = sizeof(struct hci_pinfo) 15931da177e4SLinus Torvalds }; 15941da177e4SLinus Torvalds 15953f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 15963f378b68SEric Paris int kern) 15971da177e4SLinus Torvalds { 15981da177e4SLinus Torvalds struct sock *sk; 15991da177e4SLinus Torvalds 16001da177e4SLinus Torvalds BT_DBG("sock %p", sock); 16011da177e4SLinus Torvalds 16021da177e4SLinus Torvalds if (sock->type != SOCK_RAW) 16031da177e4SLinus Torvalds return -ESOCKTNOSUPPORT; 16041da177e4SLinus Torvalds 16051da177e4SLinus Torvalds sock->ops = &hci_sock_ops; 16061da177e4SLinus Torvalds 160711aa9c28SEric W. Biederman sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern); 16081da177e4SLinus Torvalds if (!sk) 16091da177e4SLinus Torvalds return -ENOMEM; 16101da177e4SLinus Torvalds 16111da177e4SLinus Torvalds sock_init_data(sock, sk); 16121da177e4SLinus Torvalds 16131da177e4SLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 16141da177e4SLinus Torvalds 16151da177e4SLinus Torvalds sk->sk_protocol = protocol; 16161da177e4SLinus Torvalds 16171da177e4SLinus Torvalds sock->state = SS_UNCONNECTED; 16181da177e4SLinus Torvalds sk->sk_state = BT_OPEN; 16191da177e4SLinus Torvalds 16201da177e4SLinus Torvalds bt_sock_link(&hci_sk_list, sk); 16211da177e4SLinus Torvalds return 0; 16221da177e4SLinus Torvalds } 16231da177e4SLinus Torvalds 1624ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = { 16251da177e4SLinus Torvalds .family = PF_BLUETOOTH, 16261da177e4SLinus Torvalds .owner = THIS_MODULE, 16271da177e4SLinus Torvalds .create = hci_sock_create, 16281da177e4SLinus Torvalds }; 16291da177e4SLinus Torvalds 16301da177e4SLinus Torvalds int __init hci_sock_init(void) 16311da177e4SLinus Torvalds { 16321da177e4SLinus Torvalds int err; 16331da177e4SLinus Torvalds 1634b0a8e282SMarcel Holtmann BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr)); 1635b0a8e282SMarcel Holtmann 16361da177e4SLinus Torvalds err = proto_register(&hci_sk_proto, 0); 16371da177e4SLinus Torvalds if (err < 0) 16381da177e4SLinus Torvalds return err; 16391da177e4SLinus Torvalds 16401da177e4SLinus Torvalds err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 1641f7c86637SMasatake YAMATO if (err < 0) { 1642f7c86637SMasatake YAMATO BT_ERR("HCI socket registration failed"); 16431da177e4SLinus Torvalds goto error; 1644f7c86637SMasatake YAMATO } 1645f7c86637SMasatake YAMATO 1646b0316615SAl Viro err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL); 1647f7c86637SMasatake YAMATO if (err < 0) { 1648f7c86637SMasatake YAMATO BT_ERR("Failed to create HCI proc file"); 1649f7c86637SMasatake YAMATO bt_sock_unregister(BTPROTO_HCI); 1650f7c86637SMasatake YAMATO goto error; 1651f7c86637SMasatake YAMATO } 16521da177e4SLinus Torvalds 16531da177e4SLinus Torvalds BT_INFO("HCI socket layer initialized"); 16541da177e4SLinus Torvalds 16551da177e4SLinus Torvalds return 0; 16561da177e4SLinus Torvalds 16571da177e4SLinus Torvalds error: 16581da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 16591da177e4SLinus Torvalds return err; 16601da177e4SLinus Torvalds } 16611da177e4SLinus Torvalds 1662b7440a14SAnand Gadiyar void hci_sock_cleanup(void) 16631da177e4SLinus Torvalds { 1664f7c86637SMasatake YAMATO bt_procfs_cleanup(&init_net, "hci"); 16655e9d7f86SDavid Herrmann bt_sock_unregister(BTPROTO_HCI); 16661da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 16671da177e4SLinus Torvalds } 1668