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> 28787b306cSJohannes Berg #include <linux/utsname.h> 291da177e4SLinus Torvalds #include <asm/unaligned.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 321da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 33cd82e61cSMarcel Holtmann #include <net/bluetooth/hci_mon.h> 34fa4335d7SJohan Hedberg #include <net/bluetooth/mgmt.h> 35fa4335d7SJohan Hedberg 36fa4335d7SJohan Hedberg #include "mgmt_util.h" 371da177e4SLinus Torvalds 38801c1e8dSJohan Hedberg static LIST_HEAD(mgmt_chan_list); 39801c1e8dSJohan Hedberg static DEFINE_MUTEX(mgmt_chan_list_lock); 40801c1e8dSJohan Hedberg 41cd82e61cSMarcel Holtmann static atomic_t monitor_promisc = ATOMIC_INIT(0); 42cd82e61cSMarcel Holtmann 431da177e4SLinus Torvalds /* ----- HCI socket interface ----- */ 441da177e4SLinus Torvalds 45863def58SMarcel Holtmann /* Socket info */ 46863def58SMarcel Holtmann #define hci_pi(sk) ((struct hci_pinfo *) sk) 47863def58SMarcel Holtmann 48863def58SMarcel Holtmann struct hci_pinfo { 49863def58SMarcel Holtmann struct bt_sock bt; 50863def58SMarcel Holtmann struct hci_dev *hdev; 51863def58SMarcel Holtmann struct hci_filter filter; 52863def58SMarcel Holtmann __u32 cmsg_mask; 53863def58SMarcel Holtmann unsigned short channel; 546befc644SMarcel Holtmann unsigned long flags; 55863def58SMarcel Holtmann }; 56863def58SMarcel Holtmann 576befc644SMarcel Holtmann void hci_sock_set_flag(struct sock *sk, int nr) 586befc644SMarcel Holtmann { 596befc644SMarcel Holtmann set_bit(nr, &hci_pi(sk)->flags); 606befc644SMarcel Holtmann } 616befc644SMarcel Holtmann 626befc644SMarcel Holtmann void hci_sock_clear_flag(struct sock *sk, int nr) 636befc644SMarcel Holtmann { 646befc644SMarcel Holtmann clear_bit(nr, &hci_pi(sk)->flags); 656befc644SMarcel Holtmann } 666befc644SMarcel Holtmann 67c85be545SMarcel Holtmann int hci_sock_test_flag(struct sock *sk, int nr) 68c85be545SMarcel Holtmann { 69c85be545SMarcel Holtmann return test_bit(nr, &hci_pi(sk)->flags); 70c85be545SMarcel Holtmann } 71c85be545SMarcel Holtmann 72d0f172b1SJohan Hedberg unsigned short hci_sock_get_channel(struct sock *sk) 73d0f172b1SJohan Hedberg { 74d0f172b1SJohan Hedberg return hci_pi(sk)->channel; 75d0f172b1SJohan Hedberg } 76d0f172b1SJohan Hedberg 779391976aSJiri Slaby static inline int hci_test_bit(int nr, const void *addr) 781da177e4SLinus Torvalds { 799391976aSJiri Slaby return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds /* Security filter */ 833ad254f7SMarcel Holtmann #define HCI_SFLT_MAX_OGF 5 843ad254f7SMarcel Holtmann 853ad254f7SMarcel Holtmann struct hci_sec_filter { 863ad254f7SMarcel Holtmann __u32 type_mask; 873ad254f7SMarcel Holtmann __u32 event_mask[2]; 883ad254f7SMarcel Holtmann __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; 893ad254f7SMarcel Holtmann }; 903ad254f7SMarcel Holtmann 917e67c112SMarcel Holtmann static const struct hci_sec_filter hci_sec_filter = { 921da177e4SLinus Torvalds /* Packet types */ 931da177e4SLinus Torvalds 0x10, 941da177e4SLinus Torvalds /* Events */ 95dd7f5527SMarcel Holtmann { 0x1000d9fe, 0x0000b00c }, 961da177e4SLinus Torvalds /* Commands */ 971da177e4SLinus Torvalds { 981da177e4SLinus Torvalds { 0x0 }, 991da177e4SLinus Torvalds /* OGF_LINK_CTL */ 1007c631a67SMarcel Holtmann { 0xbe000006, 0x00000001, 0x00000000, 0x00 }, 1011da177e4SLinus Torvalds /* OGF_LINK_POLICY */ 1027c631a67SMarcel Holtmann { 0x00005200, 0x00000000, 0x00000000, 0x00 }, 1031da177e4SLinus Torvalds /* OGF_HOST_CTL */ 1047c631a67SMarcel Holtmann { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 }, 1051da177e4SLinus Torvalds /* OGF_INFO_PARAM */ 1067c631a67SMarcel Holtmann { 0x000002be, 0x00000000, 0x00000000, 0x00 }, 1071da177e4SLinus Torvalds /* OGF_STATUS_PARAM */ 1087c631a67SMarcel Holtmann { 0x000000ea, 0x00000000, 0x00000000, 0x00 } 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds }; 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds static struct bt_sock_list hci_sk_list = { 113d5fb2962SRobert P. J. Day .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) 1141da177e4SLinus Torvalds }; 1151da177e4SLinus Torvalds 116f81fe64fSMarcel Holtmann static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb) 117f81fe64fSMarcel Holtmann { 118f81fe64fSMarcel Holtmann struct hci_filter *flt; 119f81fe64fSMarcel Holtmann int flt_type, flt_event; 120f81fe64fSMarcel Holtmann 121f81fe64fSMarcel Holtmann /* Apply filter */ 122f81fe64fSMarcel Holtmann flt = &hci_pi(sk)->filter; 123f81fe64fSMarcel Holtmann 124d79f34e3SMarcel Holtmann flt_type = hci_skb_pkt_type(skb) & HCI_FLT_TYPE_BITS; 125f81fe64fSMarcel Holtmann 126f81fe64fSMarcel Holtmann if (!test_bit(flt_type, &flt->type_mask)) 127f81fe64fSMarcel Holtmann return true; 128f81fe64fSMarcel Holtmann 129f81fe64fSMarcel Holtmann /* Extra filter for event packets only */ 130d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT) 131f81fe64fSMarcel Holtmann return false; 132f81fe64fSMarcel Holtmann 133f81fe64fSMarcel Holtmann flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); 134f81fe64fSMarcel Holtmann 135f81fe64fSMarcel Holtmann if (!hci_test_bit(flt_event, &flt->event_mask)) 136f81fe64fSMarcel Holtmann return true; 137f81fe64fSMarcel Holtmann 138f81fe64fSMarcel Holtmann /* Check filter only when opcode is set */ 139f81fe64fSMarcel Holtmann if (!flt->opcode) 140f81fe64fSMarcel Holtmann return false; 141f81fe64fSMarcel Holtmann 142f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_COMPLETE && 143f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 3))) 144f81fe64fSMarcel Holtmann return true; 145f81fe64fSMarcel Holtmann 146f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_STATUS && 147f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 4))) 148f81fe64fSMarcel Holtmann return true; 149f81fe64fSMarcel Holtmann 150f81fe64fSMarcel Holtmann return false; 151f81fe64fSMarcel Holtmann } 152f81fe64fSMarcel Holtmann 1531da177e4SLinus Torvalds /* Send frame to RAW socket */ 154470fe1b5SMarcel Holtmann void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds struct sock *sk; 157e0edf373SMarcel Holtmann struct sk_buff *skb_copy = NULL; 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds BT_DBG("hdev %p len %d", hdev, skb->len); 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds read_lock(&hci_sk_list.lock); 162470fe1b5SMarcel Holtmann 163b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 1641da177e4SLinus Torvalds struct sk_buff *nskb; 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 1671da177e4SLinus Torvalds continue; 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds /* Don't send frame to the socket it came from */ 1701da177e4SLinus Torvalds if (skb->sk == sk) 1711da177e4SLinus Torvalds continue; 1721da177e4SLinus Torvalds 17323500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { 174d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && 175d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 176d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 177d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) 178bb77543eSMarcel Holtmann continue; 179f81fe64fSMarcel Holtmann if (is_filtered_packet(sk, skb)) 1801da177e4SLinus Torvalds continue; 18123500189SMarcel Holtmann } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 18223500189SMarcel Holtmann if (!bt_cb(skb)->incoming) 18323500189SMarcel Holtmann continue; 184d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 185d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 186d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) 18723500189SMarcel Holtmann continue; 18823500189SMarcel Holtmann } else { 18923500189SMarcel Holtmann /* Don't send frame to other channel types */ 19023500189SMarcel Holtmann continue; 19123500189SMarcel Holtmann } 1921da177e4SLinus Torvalds 193e0edf373SMarcel Holtmann if (!skb_copy) { 194e0edf373SMarcel Holtmann /* Create a private copy with headroom */ 195bad93e9dSOctavian Purdila skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true); 196e0edf373SMarcel Holtmann if (!skb_copy) 1971da177e4SLinus Torvalds continue; 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* Put type byte before the data */ 200d79f34e3SMarcel Holtmann memcpy(skb_push(skb_copy, 1), &hci_skb_pkt_type(skb), 1); 201e0edf373SMarcel Holtmann } 202e0edf373SMarcel Holtmann 203e0edf373SMarcel Holtmann nskb = skb_clone(skb_copy, GFP_ATOMIC); 204e0edf373SMarcel Holtmann if (!nskb) 205e0edf373SMarcel Holtmann continue; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds if (sock_queue_rcv_skb(sk, nskb)) 2081da177e4SLinus Torvalds kfree_skb(nskb); 2091da177e4SLinus Torvalds } 210470fe1b5SMarcel Holtmann 211470fe1b5SMarcel Holtmann read_unlock(&hci_sk_list.lock); 212e0edf373SMarcel Holtmann 213e0edf373SMarcel Holtmann kfree_skb(skb_copy); 214470fe1b5SMarcel Holtmann } 215470fe1b5SMarcel Holtmann 2167129069eSJohan Hedberg /* Send frame to sockets with specific channel */ 2177129069eSJohan Hedberg void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, 218c08b1a1dSMarcel Holtmann int flag, struct sock *skip_sk) 219470fe1b5SMarcel Holtmann { 220470fe1b5SMarcel Holtmann struct sock *sk; 221470fe1b5SMarcel Holtmann 2227129069eSJohan Hedberg BT_DBG("channel %u len %d", channel, skb->len); 223470fe1b5SMarcel Holtmann 224470fe1b5SMarcel Holtmann read_lock(&hci_sk_list.lock); 225470fe1b5SMarcel Holtmann 226b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 227470fe1b5SMarcel Holtmann struct sk_buff *nskb; 228470fe1b5SMarcel Holtmann 229c08b1a1dSMarcel Holtmann /* Ignore socket without the flag set */ 230c85be545SMarcel Holtmann if (!hci_sock_test_flag(sk, flag)) 231c08b1a1dSMarcel Holtmann continue; 232c08b1a1dSMarcel Holtmann 233470fe1b5SMarcel Holtmann /* Skip the original socket */ 234470fe1b5SMarcel Holtmann if (sk == skip_sk) 235470fe1b5SMarcel Holtmann continue; 236470fe1b5SMarcel Holtmann 237470fe1b5SMarcel Holtmann if (sk->sk_state != BT_BOUND) 238470fe1b5SMarcel Holtmann continue; 239470fe1b5SMarcel Holtmann 2407129069eSJohan Hedberg if (hci_pi(sk)->channel != channel) 241d7f72f61SMarcel Holtmann continue; 242d7f72f61SMarcel Holtmann 243d7f72f61SMarcel Holtmann nskb = skb_clone(skb, GFP_ATOMIC); 244d7f72f61SMarcel Holtmann if (!nskb) 245d7f72f61SMarcel Holtmann continue; 246d7f72f61SMarcel Holtmann 247d7f72f61SMarcel Holtmann if (sock_queue_rcv_skb(sk, nskb)) 248d7f72f61SMarcel Holtmann kfree_skb(nskb); 249d7f72f61SMarcel Holtmann } 250d7f72f61SMarcel Holtmann 251d7f72f61SMarcel Holtmann read_unlock(&hci_sk_list.lock); 252d7f72f61SMarcel Holtmann } 253d7f72f61SMarcel Holtmann 254cd82e61cSMarcel Holtmann /* Send frame to monitor socket */ 255cd82e61cSMarcel Holtmann void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) 256cd82e61cSMarcel Holtmann { 257cd82e61cSMarcel Holtmann struct sk_buff *skb_copy = NULL; 2582b531294SMarcel Holtmann struct hci_mon_hdr *hdr; 259cd82e61cSMarcel Holtmann __le16 opcode; 260cd82e61cSMarcel Holtmann 261cd82e61cSMarcel Holtmann if (!atomic_read(&monitor_promisc)) 262cd82e61cSMarcel Holtmann return; 263cd82e61cSMarcel Holtmann 264cd82e61cSMarcel Holtmann BT_DBG("hdev %p len %d", hdev, skb->len); 265cd82e61cSMarcel Holtmann 266d79f34e3SMarcel Holtmann switch (hci_skb_pkt_type(skb)) { 267cd82e61cSMarcel Holtmann case HCI_COMMAND_PKT: 268dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); 269cd82e61cSMarcel Holtmann break; 270cd82e61cSMarcel Holtmann case HCI_EVENT_PKT: 271dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_EVENT_PKT); 272cd82e61cSMarcel Holtmann break; 273cd82e61cSMarcel Holtmann case HCI_ACLDATA_PKT: 274cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 275dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); 276cd82e61cSMarcel Holtmann else 277dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); 278cd82e61cSMarcel Holtmann break; 279cd82e61cSMarcel Holtmann case HCI_SCODATA_PKT: 280cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 281dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); 282cd82e61cSMarcel Holtmann else 283dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); 284cd82e61cSMarcel Holtmann break; 285e875ff84SMarcel Holtmann case HCI_DIAG_PKT: 286e875ff84SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG); 287e875ff84SMarcel Holtmann break; 288cd82e61cSMarcel Holtmann default: 289cd82e61cSMarcel Holtmann return; 290cd82e61cSMarcel Holtmann } 291cd82e61cSMarcel Holtmann 2922b531294SMarcel Holtmann /* Create a private copy with headroom */ 2932b531294SMarcel Holtmann skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true); 2942b531294SMarcel Holtmann if (!skb_copy) 2952b531294SMarcel Holtmann return; 2962b531294SMarcel Holtmann 2972b531294SMarcel Holtmann /* Put header before the data */ 2982b531294SMarcel Holtmann hdr = (void *)skb_push(skb_copy, HCI_MON_HDR_SIZE); 2992b531294SMarcel Holtmann hdr->opcode = opcode; 3002b531294SMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 3012b531294SMarcel Holtmann hdr->len = cpu_to_le16(skb->len); 3022b531294SMarcel Holtmann 303c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, 304c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 305cd82e61cSMarcel Holtmann kfree_skb(skb_copy); 306cd82e61cSMarcel Holtmann } 307cd82e61cSMarcel Holtmann 308cd82e61cSMarcel Holtmann static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) 309cd82e61cSMarcel Holtmann { 310cd82e61cSMarcel Holtmann struct hci_mon_hdr *hdr; 311cd82e61cSMarcel Holtmann struct hci_mon_new_index *ni; 3126c566dd5SMarcel Holtmann struct hci_mon_index_info *ii; 313cd82e61cSMarcel Holtmann struct sk_buff *skb; 314cd82e61cSMarcel Holtmann __le16 opcode; 315cd82e61cSMarcel Holtmann 316cd82e61cSMarcel Holtmann switch (event) { 317cd82e61cSMarcel Holtmann case HCI_DEV_REG: 318cd82e61cSMarcel Holtmann skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC); 319cd82e61cSMarcel Holtmann if (!skb) 320cd82e61cSMarcel Holtmann return NULL; 321cd82e61cSMarcel Holtmann 322cd82e61cSMarcel Holtmann ni = (void *)skb_put(skb, HCI_MON_NEW_INDEX_SIZE); 323cd82e61cSMarcel Holtmann ni->type = hdev->dev_type; 324cd82e61cSMarcel Holtmann ni->bus = hdev->bus; 325cd82e61cSMarcel Holtmann bacpy(&ni->bdaddr, &hdev->bdaddr); 326cd82e61cSMarcel Holtmann memcpy(ni->name, hdev->name, 8); 327cd82e61cSMarcel Holtmann 328dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_NEW_INDEX); 329cd82e61cSMarcel Holtmann break; 330cd82e61cSMarcel Holtmann 331cd82e61cSMarcel Holtmann case HCI_DEV_UNREG: 332cd82e61cSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 333cd82e61cSMarcel Holtmann if (!skb) 334cd82e61cSMarcel Holtmann return NULL; 335cd82e61cSMarcel Holtmann 336dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_DEL_INDEX); 337cd82e61cSMarcel Holtmann break; 338cd82e61cSMarcel Holtmann 339e131d74aSMarcel Holtmann case HCI_DEV_SETUP: 340e131d74aSMarcel Holtmann if (hdev->manufacturer == 0xffff) 341e131d74aSMarcel Holtmann return NULL; 342e131d74aSMarcel Holtmann 343e131d74aSMarcel Holtmann /* fall through */ 344e131d74aSMarcel Holtmann 3456c566dd5SMarcel Holtmann case HCI_DEV_UP: 3466c566dd5SMarcel Holtmann skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC); 3476c566dd5SMarcel Holtmann if (!skb) 3486c566dd5SMarcel Holtmann return NULL; 3496c566dd5SMarcel Holtmann 3506c566dd5SMarcel Holtmann ii = (void *)skb_put(skb, HCI_MON_INDEX_INFO_SIZE); 3516c566dd5SMarcel Holtmann bacpy(&ii->bdaddr, &hdev->bdaddr); 3526c566dd5SMarcel Holtmann ii->manufacturer = cpu_to_le16(hdev->manufacturer); 3536c566dd5SMarcel Holtmann 3546c566dd5SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_INDEX_INFO); 3556c566dd5SMarcel Holtmann break; 3566c566dd5SMarcel Holtmann 35722db3cbcSMarcel Holtmann case HCI_DEV_OPEN: 35822db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 35922db3cbcSMarcel Holtmann if (!skb) 36022db3cbcSMarcel Holtmann return NULL; 36122db3cbcSMarcel Holtmann 36222db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_OPEN_INDEX); 36322db3cbcSMarcel Holtmann break; 36422db3cbcSMarcel Holtmann 36522db3cbcSMarcel Holtmann case HCI_DEV_CLOSE: 36622db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 36722db3cbcSMarcel Holtmann if (!skb) 36822db3cbcSMarcel Holtmann return NULL; 36922db3cbcSMarcel Holtmann 37022db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX); 37122db3cbcSMarcel Holtmann break; 37222db3cbcSMarcel Holtmann 373cd82e61cSMarcel Holtmann default: 374cd82e61cSMarcel Holtmann return NULL; 375cd82e61cSMarcel Holtmann } 376cd82e61cSMarcel Holtmann 377cd82e61cSMarcel Holtmann __net_timestamp(skb); 378cd82e61cSMarcel Holtmann 379cd82e61cSMarcel Holtmann hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE); 380cd82e61cSMarcel Holtmann hdr->opcode = opcode; 381cd82e61cSMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 382cd82e61cSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 383cd82e61cSMarcel Holtmann 384cd82e61cSMarcel Holtmann return skb; 385cd82e61cSMarcel Holtmann } 386cd82e61cSMarcel Holtmann 387787b306cSJohannes Berg static void __printf(2, 3) 388787b306cSJohannes Berg send_monitor_note(struct sock *sk, const char *fmt, ...) 389dd31506dSMarcel Holtmann { 390787b306cSJohannes Berg size_t len; 391dd31506dSMarcel Holtmann struct hci_mon_hdr *hdr; 392dd31506dSMarcel Holtmann struct sk_buff *skb; 393787b306cSJohannes Berg va_list args; 394787b306cSJohannes Berg 395787b306cSJohannes Berg va_start(args, fmt); 396787b306cSJohannes Berg len = vsnprintf(NULL, 0, fmt, args); 397787b306cSJohannes Berg va_end(args); 398dd31506dSMarcel Holtmann 399dd31506dSMarcel Holtmann skb = bt_skb_alloc(len + 1, GFP_ATOMIC); 400dd31506dSMarcel Holtmann if (!skb) 401dd31506dSMarcel Holtmann return; 402dd31506dSMarcel Holtmann 403787b306cSJohannes Berg va_start(args, fmt); 404787b306cSJohannes Berg vsprintf(skb_put(skb, len), fmt, args); 405787b306cSJohannes Berg *skb_put(skb, 1) = 0; 406787b306cSJohannes Berg va_end(args); 407dd31506dSMarcel Holtmann 408dd31506dSMarcel Holtmann __net_timestamp(skb); 409dd31506dSMarcel Holtmann 410dd31506dSMarcel Holtmann hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE); 411dd31506dSMarcel Holtmann hdr->opcode = cpu_to_le16(HCI_MON_SYSTEM_NOTE); 412dd31506dSMarcel Holtmann hdr->index = cpu_to_le16(HCI_DEV_NONE); 413dd31506dSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 414dd31506dSMarcel Holtmann 415dd31506dSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 416dd31506dSMarcel Holtmann kfree_skb(skb); 417dd31506dSMarcel Holtmann } 418dd31506dSMarcel Holtmann 419cd82e61cSMarcel Holtmann static void send_monitor_replay(struct sock *sk) 420cd82e61cSMarcel Holtmann { 421cd82e61cSMarcel Holtmann struct hci_dev *hdev; 422cd82e61cSMarcel Holtmann 423cd82e61cSMarcel Holtmann read_lock(&hci_dev_list_lock); 424cd82e61cSMarcel Holtmann 425cd82e61cSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 426cd82e61cSMarcel Holtmann struct sk_buff *skb; 427cd82e61cSMarcel Holtmann 428cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_REG); 429cd82e61cSMarcel Holtmann if (!skb) 430cd82e61cSMarcel Holtmann continue; 431cd82e61cSMarcel Holtmann 432cd82e61cSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 433cd82e61cSMarcel Holtmann kfree_skb(skb); 43422db3cbcSMarcel Holtmann 43522db3cbcSMarcel Holtmann if (!test_bit(HCI_RUNNING, &hdev->flags)) 43622db3cbcSMarcel Holtmann continue; 43722db3cbcSMarcel Holtmann 43822db3cbcSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_OPEN); 43922db3cbcSMarcel Holtmann if (!skb) 44022db3cbcSMarcel Holtmann continue; 44122db3cbcSMarcel Holtmann 44222db3cbcSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 44322db3cbcSMarcel Holtmann kfree_skb(skb); 4446c566dd5SMarcel Holtmann 445e131d74aSMarcel Holtmann if (test_bit(HCI_UP, &hdev->flags)) 4466c566dd5SMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_UP); 447e131d74aSMarcel Holtmann else if (hci_dev_test_flag(hdev, HCI_SETUP)) 448e131d74aSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_SETUP); 449e131d74aSMarcel Holtmann else 450e131d74aSMarcel Holtmann skb = NULL; 4516c566dd5SMarcel Holtmann 452e131d74aSMarcel Holtmann if (skb) { 4536c566dd5SMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 4546c566dd5SMarcel Holtmann kfree_skb(skb); 455cd82e61cSMarcel Holtmann } 456e131d74aSMarcel Holtmann } 457cd82e61cSMarcel Holtmann 458cd82e61cSMarcel Holtmann read_unlock(&hci_dev_list_lock); 459cd82e61cSMarcel Holtmann } 460cd82e61cSMarcel Holtmann 461040030efSMarcel Holtmann /* Generate internal stack event */ 462040030efSMarcel Holtmann static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 463040030efSMarcel Holtmann { 464040030efSMarcel Holtmann struct hci_event_hdr *hdr; 465040030efSMarcel Holtmann struct hci_ev_stack_internal *ev; 466040030efSMarcel Holtmann struct sk_buff *skb; 467040030efSMarcel Holtmann 468040030efSMarcel Holtmann skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 469040030efSMarcel Holtmann if (!skb) 470040030efSMarcel Holtmann return; 471040030efSMarcel Holtmann 472040030efSMarcel Holtmann hdr = (void *)skb_put(skb, HCI_EVENT_HDR_SIZE); 473040030efSMarcel Holtmann hdr->evt = HCI_EV_STACK_INTERNAL; 474040030efSMarcel Holtmann hdr->plen = sizeof(*ev) + dlen; 475040030efSMarcel Holtmann 476040030efSMarcel Holtmann ev = (void *)skb_put(skb, sizeof(*ev) + dlen); 477040030efSMarcel Holtmann ev->type = type; 478040030efSMarcel Holtmann memcpy(ev->data, data, dlen); 479040030efSMarcel Holtmann 480040030efSMarcel Holtmann bt_cb(skb)->incoming = 1; 481040030efSMarcel Holtmann __net_timestamp(skb); 482040030efSMarcel Holtmann 483d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_EVENT_PKT; 484040030efSMarcel Holtmann hci_send_to_sock(hdev, skb); 485040030efSMarcel Holtmann kfree_skb(skb); 486040030efSMarcel Holtmann } 487040030efSMarcel Holtmann 488040030efSMarcel Holtmann void hci_sock_dev_event(struct hci_dev *hdev, int event) 489040030efSMarcel Holtmann { 490040030efSMarcel Holtmann BT_DBG("hdev %s event %d", hdev->name, event); 491040030efSMarcel Holtmann 492cd82e61cSMarcel Holtmann if (atomic_read(&monitor_promisc)) { 493cd82e61cSMarcel Holtmann struct sk_buff *skb; 494cd82e61cSMarcel Holtmann 495ed1b28a4SMarcel Holtmann /* Send event to monitor */ 496cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, event); 497cd82e61cSMarcel Holtmann if (skb) { 498c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, 499c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 500cd82e61cSMarcel Holtmann kfree_skb(skb); 501cd82e61cSMarcel Holtmann } 502cd82e61cSMarcel Holtmann } 503cd82e61cSMarcel Holtmann 504ed1b28a4SMarcel Holtmann if (event <= HCI_DEV_DOWN) { 505ed1b28a4SMarcel Holtmann struct hci_ev_si_device ev; 506ed1b28a4SMarcel Holtmann 507040030efSMarcel Holtmann /* Send event to sockets */ 508040030efSMarcel Holtmann ev.event = event; 509040030efSMarcel Holtmann ev.dev_id = hdev->id; 510040030efSMarcel Holtmann hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); 511ed1b28a4SMarcel Holtmann } 512040030efSMarcel Holtmann 513040030efSMarcel Holtmann if (event == HCI_DEV_UNREG) { 514040030efSMarcel Holtmann struct sock *sk; 515040030efSMarcel Holtmann 516040030efSMarcel Holtmann /* Detach sockets from device */ 517040030efSMarcel Holtmann read_lock(&hci_sk_list.lock); 518b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 519040030efSMarcel Holtmann bh_lock_sock_nested(sk); 520040030efSMarcel Holtmann if (hci_pi(sk)->hdev == hdev) { 521040030efSMarcel Holtmann hci_pi(sk)->hdev = NULL; 522040030efSMarcel Holtmann sk->sk_err = EPIPE; 523040030efSMarcel Holtmann sk->sk_state = BT_OPEN; 524040030efSMarcel Holtmann sk->sk_state_change(sk); 525040030efSMarcel Holtmann 526040030efSMarcel Holtmann hci_dev_put(hdev); 527040030efSMarcel Holtmann } 528040030efSMarcel Holtmann bh_unlock_sock(sk); 529040030efSMarcel Holtmann } 530040030efSMarcel Holtmann read_unlock(&hci_sk_list.lock); 531040030efSMarcel Holtmann } 532040030efSMarcel Holtmann } 533040030efSMarcel Holtmann 534801c1e8dSJohan Hedberg static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel) 535801c1e8dSJohan Hedberg { 536801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 537801c1e8dSJohan Hedberg 538801c1e8dSJohan Hedberg list_for_each_entry(c, &mgmt_chan_list, list) { 539801c1e8dSJohan Hedberg if (c->channel == channel) 540801c1e8dSJohan Hedberg return c; 541801c1e8dSJohan Hedberg } 542801c1e8dSJohan Hedberg 543801c1e8dSJohan Hedberg return NULL; 544801c1e8dSJohan Hedberg } 545801c1e8dSJohan Hedberg 546801c1e8dSJohan Hedberg static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel) 547801c1e8dSJohan Hedberg { 548801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 549801c1e8dSJohan Hedberg 550801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 551801c1e8dSJohan Hedberg c = __hci_mgmt_chan_find(channel); 552801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 553801c1e8dSJohan Hedberg 554801c1e8dSJohan Hedberg return c; 555801c1e8dSJohan Hedberg } 556801c1e8dSJohan Hedberg 557801c1e8dSJohan Hedberg int hci_mgmt_chan_register(struct hci_mgmt_chan *c) 558801c1e8dSJohan Hedberg { 559801c1e8dSJohan Hedberg if (c->channel < HCI_CHANNEL_CONTROL) 560801c1e8dSJohan Hedberg return -EINVAL; 561801c1e8dSJohan Hedberg 562801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 563801c1e8dSJohan Hedberg if (__hci_mgmt_chan_find(c->channel)) { 564801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 565801c1e8dSJohan Hedberg return -EALREADY; 566801c1e8dSJohan Hedberg } 567801c1e8dSJohan Hedberg 568801c1e8dSJohan Hedberg list_add_tail(&c->list, &mgmt_chan_list); 569801c1e8dSJohan Hedberg 570801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 571801c1e8dSJohan Hedberg 572801c1e8dSJohan Hedberg return 0; 573801c1e8dSJohan Hedberg } 574801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_register); 575801c1e8dSJohan Hedberg 576801c1e8dSJohan Hedberg void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c) 577801c1e8dSJohan Hedberg { 578801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 579801c1e8dSJohan Hedberg list_del(&c->list); 580801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 581801c1e8dSJohan Hedberg } 582801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_unregister); 583801c1e8dSJohan Hedberg 5841da177e4SLinus Torvalds static int hci_sock_release(struct socket *sock) 5851da177e4SLinus Torvalds { 5861da177e4SLinus Torvalds struct sock *sk = sock->sk; 5877b005bd3SMarcel Holtmann struct hci_dev *hdev; 5881da177e4SLinus Torvalds 5891da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds if (!sk) 5921da177e4SLinus Torvalds return 0; 5931da177e4SLinus Torvalds 5947b005bd3SMarcel Holtmann hdev = hci_pi(sk)->hdev; 5957b005bd3SMarcel Holtmann 596cd82e61cSMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_MONITOR) 597cd82e61cSMarcel Holtmann atomic_dec(&monitor_promisc); 598cd82e61cSMarcel Holtmann 5991da177e4SLinus Torvalds bt_sock_unlink(&hci_sk_list, sk); 6001da177e4SLinus Torvalds 6011da177e4SLinus Torvalds if (hdev) { 60223500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 6036b3cc1dbSSimon Fels /* When releasing an user channel exclusive access, 6046b3cc1dbSSimon Fels * call hci_dev_do_close directly instead of calling 6056b3cc1dbSSimon Fels * hci_dev_close to ensure the exclusive access will 6066b3cc1dbSSimon Fels * be released and the controller brought back down. 6076b3cc1dbSSimon Fels * 6086b3cc1dbSSimon Fels * The checking of HCI_AUTO_OFF is not needed in this 6096b3cc1dbSSimon Fels * case since it will have been cleared already when 6106b3cc1dbSSimon Fels * opening the user channel. 6116b3cc1dbSSimon Fels */ 6126b3cc1dbSSimon Fels hci_dev_do_close(hdev); 6139380f9eaSLoic Poulain hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 6149380f9eaSLoic Poulain mgmt_index_added(hdev); 61523500189SMarcel Holtmann } 61623500189SMarcel Holtmann 6171da177e4SLinus Torvalds atomic_dec(&hdev->promisc); 6181da177e4SLinus Torvalds hci_dev_put(hdev); 6191da177e4SLinus Torvalds } 6201da177e4SLinus Torvalds 6211da177e4SLinus Torvalds sock_orphan(sk); 6221da177e4SLinus Torvalds 6231da177e4SLinus Torvalds skb_queue_purge(&sk->sk_receive_queue); 6241da177e4SLinus Torvalds skb_queue_purge(&sk->sk_write_queue); 6251da177e4SLinus Torvalds 6261da177e4SLinus Torvalds sock_put(sk); 6271da177e4SLinus Torvalds return 0; 6281da177e4SLinus Torvalds } 6291da177e4SLinus Torvalds 630b2a66aadSAntti Julku static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) 631f0358568SJohan Hedberg { 632f0358568SJohan Hedberg bdaddr_t bdaddr; 6335e762444SAntti Julku int err; 634f0358568SJohan Hedberg 635f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 636f0358568SJohan Hedberg return -EFAULT; 637f0358568SJohan Hedberg 63809fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6395e762444SAntti Julku 640dcc36c16SJohan Hedberg err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6415e762444SAntti Julku 64209fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6435e762444SAntti Julku 6445e762444SAntti Julku return err; 645f0358568SJohan Hedberg } 646f0358568SJohan Hedberg 647b2a66aadSAntti Julku static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) 648f0358568SJohan Hedberg { 649f0358568SJohan Hedberg bdaddr_t bdaddr; 6505e762444SAntti Julku int err; 651f0358568SJohan Hedberg 652f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 653f0358568SJohan Hedberg return -EFAULT; 654f0358568SJohan Hedberg 65509fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6565e762444SAntti Julku 657dcc36c16SJohan Hedberg err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6585e762444SAntti Julku 65909fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6605e762444SAntti Julku 6615e762444SAntti Julku return err; 662f0358568SJohan Hedberg } 663f0358568SJohan Hedberg 6641da177e4SLinus Torvalds /* Ioctls that require bound socket */ 6656039aa73SGustavo Padovan static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, 6666039aa73SGustavo Padovan unsigned long arg) 6671da177e4SLinus Torvalds { 6681da177e4SLinus Torvalds struct hci_dev *hdev = hci_pi(sk)->hdev; 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds if (!hdev) 6711da177e4SLinus Torvalds return -EBADFD; 6721da177e4SLinus Torvalds 673d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) 6740736cfa8SMarcel Holtmann return -EBUSY; 6750736cfa8SMarcel Holtmann 676d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 677fee746b0SMarcel Holtmann return -EOPNOTSUPP; 678fee746b0SMarcel Holtmann 679ca8bee5dSMarcel Holtmann if (hdev->dev_type != HCI_PRIMARY) 6805b69bef5SMarcel Holtmann return -EOPNOTSUPP; 6815b69bef5SMarcel Holtmann 6821da177e4SLinus Torvalds switch (cmd) { 6831da177e4SLinus Torvalds case HCISETRAW: 6841da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 685bf5b30b8SZhao Hongjiang return -EPERM; 686db596681SMarcel Holtmann return -EOPNOTSUPP; 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds case HCIGETCONNINFO: 6891da177e4SLinus Torvalds return hci_get_conn_info(hdev, (void __user *)arg); 6901da177e4SLinus Torvalds 69140be492fSMarcel Holtmann case HCIGETAUTHINFO: 69240be492fSMarcel Holtmann return hci_get_auth_info(hdev, (void __user *)arg); 69340be492fSMarcel Holtmann 694f0358568SJohan Hedberg case HCIBLOCKADDR: 695f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 696bf5b30b8SZhao Hongjiang return -EPERM; 697b2a66aadSAntti Julku return hci_sock_blacklist_add(hdev, (void __user *)arg); 698f0358568SJohan Hedberg 699f0358568SJohan Hedberg case HCIUNBLOCKADDR: 700f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 701bf5b30b8SZhao Hongjiang return -EPERM; 702b2a66aadSAntti Julku return hci_sock_blacklist_del(hdev, (void __user *)arg); 7030736cfa8SMarcel Holtmann } 704f0358568SJohan Hedberg 705324d36edSMarcel Holtmann return -ENOIOCTLCMD; 7061da177e4SLinus Torvalds } 7071da177e4SLinus Torvalds 7088fc9ced3SGustavo Padovan static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, 7098fc9ced3SGustavo Padovan unsigned long arg) 7101da177e4SLinus Torvalds { 7111da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 7120736cfa8SMarcel Holtmann struct sock *sk = sock->sk; 7131da177e4SLinus Torvalds int err; 7141da177e4SLinus Torvalds 7151da177e4SLinus Torvalds BT_DBG("cmd %x arg %lx", cmd, arg); 7161da177e4SLinus Torvalds 717c1c4f956SMarcel Holtmann lock_sock(sk); 718c1c4f956SMarcel Holtmann 719c1c4f956SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 720c1c4f956SMarcel Holtmann err = -EBADFD; 721c1c4f956SMarcel Holtmann goto done; 722c1c4f956SMarcel Holtmann } 723c1c4f956SMarcel Holtmann 724c1c4f956SMarcel Holtmann release_sock(sk); 725c1c4f956SMarcel Holtmann 7261da177e4SLinus Torvalds switch (cmd) { 7271da177e4SLinus Torvalds case HCIGETDEVLIST: 7281da177e4SLinus Torvalds return hci_get_dev_list(argp); 7291da177e4SLinus Torvalds 7301da177e4SLinus Torvalds case HCIGETDEVINFO: 7311da177e4SLinus Torvalds return hci_get_dev_info(argp); 7321da177e4SLinus Torvalds 7331da177e4SLinus Torvalds case HCIGETCONNLIST: 7341da177e4SLinus Torvalds return hci_get_conn_list(argp); 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds case HCIDEVUP: 7371da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 738bf5b30b8SZhao Hongjiang return -EPERM; 7391da177e4SLinus Torvalds return hci_dev_open(arg); 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds case HCIDEVDOWN: 7421da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 743bf5b30b8SZhao Hongjiang return -EPERM; 7441da177e4SLinus Torvalds return hci_dev_close(arg); 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds case HCIDEVRESET: 7471da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 748bf5b30b8SZhao Hongjiang return -EPERM; 7491da177e4SLinus Torvalds return hci_dev_reset(arg); 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds case HCIDEVRESTAT: 7521da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 753bf5b30b8SZhao Hongjiang return -EPERM; 7541da177e4SLinus Torvalds return hci_dev_reset_stat(arg); 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds case HCISETSCAN: 7571da177e4SLinus Torvalds case HCISETAUTH: 7581da177e4SLinus Torvalds case HCISETENCRYPT: 7591da177e4SLinus Torvalds case HCISETPTYPE: 7601da177e4SLinus Torvalds case HCISETLINKPOL: 7611da177e4SLinus Torvalds case HCISETLINKMODE: 7621da177e4SLinus Torvalds case HCISETACLMTU: 7631da177e4SLinus Torvalds case HCISETSCOMTU: 7641da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 765bf5b30b8SZhao Hongjiang return -EPERM; 7661da177e4SLinus Torvalds return hci_dev_cmd(cmd, argp); 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds case HCIINQUIRY: 7691da177e4SLinus Torvalds return hci_inquiry(argp); 770c1c4f956SMarcel Holtmann } 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds lock_sock(sk); 773c1c4f956SMarcel Holtmann 7741da177e4SLinus Torvalds err = hci_sock_bound_ioctl(sk, cmd, arg); 775c1c4f956SMarcel Holtmann 776c1c4f956SMarcel Holtmann done: 7771da177e4SLinus Torvalds release_sock(sk); 7781da177e4SLinus Torvalds return err; 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds 7818fc9ced3SGustavo Padovan static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, 7828fc9ced3SGustavo Padovan int addr_len) 7831da177e4SLinus Torvalds { 7840381101fSJohan Hedberg struct sockaddr_hci haddr; 7851da177e4SLinus Torvalds struct sock *sk = sock->sk; 7861da177e4SLinus Torvalds struct hci_dev *hdev = NULL; 7870381101fSJohan Hedberg int len, err = 0; 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 7901da177e4SLinus Torvalds 7910381101fSJohan Hedberg if (!addr) 7920381101fSJohan Hedberg return -EINVAL; 7930381101fSJohan Hedberg 7940381101fSJohan Hedberg memset(&haddr, 0, sizeof(haddr)); 7950381101fSJohan Hedberg len = min_t(unsigned int, sizeof(haddr), addr_len); 7960381101fSJohan Hedberg memcpy(&haddr, addr, len); 7970381101fSJohan Hedberg 7980381101fSJohan Hedberg if (haddr.hci_family != AF_BLUETOOTH) 7990381101fSJohan Hedberg return -EINVAL; 8000381101fSJohan Hedberg 8011da177e4SLinus Torvalds lock_sock(sk); 8021da177e4SLinus Torvalds 8037cc2ade2SMarcel Holtmann if (sk->sk_state == BT_BOUND) { 8047cc2ade2SMarcel Holtmann err = -EALREADY; 8057cc2ade2SMarcel Holtmann goto done; 8067cc2ade2SMarcel Holtmann } 8077cc2ade2SMarcel Holtmann 8087cc2ade2SMarcel Holtmann switch (haddr.hci_channel) { 8097cc2ade2SMarcel Holtmann case HCI_CHANNEL_RAW: 8107cc2ade2SMarcel Holtmann if (hci_pi(sk)->hdev) { 8111da177e4SLinus Torvalds err = -EALREADY; 8121da177e4SLinus Torvalds goto done; 8131da177e4SLinus Torvalds } 8141da177e4SLinus Torvalds 8150381101fSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 8160381101fSJohan Hedberg hdev = hci_dev_get(haddr.hci_dev); 81770f23020SAndrei Emeltchenko if (!hdev) { 8181da177e4SLinus Torvalds err = -ENODEV; 8191da177e4SLinus Torvalds goto done; 8201da177e4SLinus Torvalds } 8211da177e4SLinus Torvalds 8221da177e4SLinus Torvalds atomic_inc(&hdev->promisc); 8231da177e4SLinus Torvalds } 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds hci_pi(sk)->hdev = hdev; 8267cc2ade2SMarcel Holtmann break; 8277cc2ade2SMarcel Holtmann 82823500189SMarcel Holtmann case HCI_CHANNEL_USER: 82923500189SMarcel Holtmann if (hci_pi(sk)->hdev) { 83023500189SMarcel Holtmann err = -EALREADY; 83123500189SMarcel Holtmann goto done; 83223500189SMarcel Holtmann } 83323500189SMarcel Holtmann 83423500189SMarcel Holtmann if (haddr.hci_dev == HCI_DEV_NONE) { 83523500189SMarcel Holtmann err = -EINVAL; 83623500189SMarcel Holtmann goto done; 83723500189SMarcel Holtmann } 83823500189SMarcel Holtmann 83910a8b86fSMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 84023500189SMarcel Holtmann err = -EPERM; 84123500189SMarcel Holtmann goto done; 84223500189SMarcel Holtmann } 84323500189SMarcel Holtmann 84423500189SMarcel Holtmann hdev = hci_dev_get(haddr.hci_dev); 84523500189SMarcel Holtmann if (!hdev) { 84623500189SMarcel Holtmann err = -ENODEV; 84723500189SMarcel Holtmann goto done; 84823500189SMarcel Holtmann } 84923500189SMarcel Holtmann 850781f899fSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags) || 851d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_SETUP) || 852781f899fSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG) || 853781f899fSMarcel Holtmann (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) && 854781f899fSMarcel Holtmann test_bit(HCI_UP, &hdev->flags))) { 85523500189SMarcel Holtmann err = -EBUSY; 85623500189SMarcel Holtmann hci_dev_put(hdev); 85723500189SMarcel Holtmann goto done; 85823500189SMarcel Holtmann } 85923500189SMarcel Holtmann 860238be788SMarcel Holtmann if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) { 86123500189SMarcel Holtmann err = -EUSERS; 86223500189SMarcel Holtmann hci_dev_put(hdev); 86323500189SMarcel Holtmann goto done; 86423500189SMarcel Holtmann } 86523500189SMarcel Holtmann 86623500189SMarcel Holtmann mgmt_index_removed(hdev); 86723500189SMarcel Holtmann 86823500189SMarcel Holtmann err = hci_dev_open(hdev->id); 86923500189SMarcel Holtmann if (err) { 870781f899fSMarcel Holtmann if (err == -EALREADY) { 871781f899fSMarcel Holtmann /* In case the transport is already up and 872781f899fSMarcel Holtmann * running, clear the error here. 873781f899fSMarcel Holtmann * 874781f899fSMarcel Holtmann * This can happen when opening an user 875781f899fSMarcel Holtmann * channel and HCI_AUTO_OFF grace period 876781f899fSMarcel Holtmann * is still active. 877781f899fSMarcel Holtmann */ 878781f899fSMarcel Holtmann err = 0; 879781f899fSMarcel Holtmann } else { 880a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 881c6521401SMarcel Holtmann mgmt_index_added(hdev); 88223500189SMarcel Holtmann hci_dev_put(hdev); 88323500189SMarcel Holtmann goto done; 88423500189SMarcel Holtmann } 885781f899fSMarcel Holtmann } 88623500189SMarcel Holtmann 88723500189SMarcel Holtmann atomic_inc(&hdev->promisc); 88823500189SMarcel Holtmann 88923500189SMarcel Holtmann hci_pi(sk)->hdev = hdev; 89023500189SMarcel Holtmann break; 89123500189SMarcel Holtmann 892cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 893cd82e61cSMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 894cd82e61cSMarcel Holtmann err = -EINVAL; 895cd82e61cSMarcel Holtmann goto done; 896cd82e61cSMarcel Holtmann } 897cd82e61cSMarcel Holtmann 898cd82e61cSMarcel Holtmann if (!capable(CAP_NET_RAW)) { 899cd82e61cSMarcel Holtmann err = -EPERM; 900cd82e61cSMarcel Holtmann goto done; 901cd82e61cSMarcel Holtmann } 902cd82e61cSMarcel Holtmann 90350ebc055SMarcel Holtmann /* The monitor interface is restricted to CAP_NET_RAW 90450ebc055SMarcel Holtmann * capabilities and with that implicitly trusted. 90550ebc055SMarcel Holtmann */ 90650ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 90750ebc055SMarcel Holtmann 908787b306cSJohannes Berg send_monitor_note(sk, "Linux version %s (%s)", 909787b306cSJohannes Berg init_utsname()->release, 910787b306cSJohannes Berg init_utsname()->machine); 911787b306cSJohannes Berg send_monitor_note(sk, "Bluetooth subsystem version %s", 912dd31506dSMarcel Holtmann BT_SUBSYS_VERSION); 913cd82e61cSMarcel Holtmann send_monitor_replay(sk); 914cd82e61cSMarcel Holtmann 915cd82e61cSMarcel Holtmann atomic_inc(&monitor_promisc); 916cd82e61cSMarcel Holtmann break; 917cd82e61cSMarcel Holtmann 918ac714949SMarcel Holtmann case HCI_CHANNEL_LOGGING: 919ac714949SMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 920ac714949SMarcel Holtmann err = -EINVAL; 921ac714949SMarcel Holtmann goto done; 922ac714949SMarcel Holtmann } 923ac714949SMarcel Holtmann 924ac714949SMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 925ac714949SMarcel Holtmann err = -EPERM; 926ac714949SMarcel Holtmann goto done; 927ac714949SMarcel Holtmann } 928ac714949SMarcel Holtmann break; 929ac714949SMarcel Holtmann 9307cc2ade2SMarcel Holtmann default: 931801c1e8dSJohan Hedberg if (!hci_mgmt_chan_find(haddr.hci_channel)) { 9327cc2ade2SMarcel Holtmann err = -EINVAL; 9337cc2ade2SMarcel Holtmann goto done; 9347cc2ade2SMarcel Holtmann } 9357cc2ade2SMarcel Holtmann 936801c1e8dSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 937801c1e8dSJohan Hedberg err = -EINVAL; 938801c1e8dSJohan Hedberg goto done; 939801c1e8dSJohan Hedberg } 940801c1e8dSJohan Hedberg 9411195fbb8SMarcel Holtmann /* Users with CAP_NET_ADMIN capabilities are allowed 9421195fbb8SMarcel Holtmann * access to all management commands and events. For 9431195fbb8SMarcel Holtmann * untrusted users the interface is restricted and 9441195fbb8SMarcel Holtmann * also only untrusted events are sent. 94550ebc055SMarcel Holtmann */ 9461195fbb8SMarcel Holtmann if (capable(CAP_NET_ADMIN)) 94750ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 94850ebc055SMarcel Holtmann 949f9207338SMarcel Holtmann /* At the moment the index and unconfigured index events 950f9207338SMarcel Holtmann * are enabled unconditionally. Setting them on each 951f9207338SMarcel Holtmann * socket when binding keeps this functionality. They 952f9207338SMarcel Holtmann * however might be cleared later and then sending of these 953f9207338SMarcel Holtmann * events will be disabled, but that is then intentional. 954f6b7712eSMarcel Holtmann * 955f6b7712eSMarcel Holtmann * This also enables generic events that are safe to be 956f6b7712eSMarcel Holtmann * received by untrusted users. Example for such events 957f6b7712eSMarcel Holtmann * are changes to settings, class of device, name etc. 958f9207338SMarcel Holtmann */ 959f9207338SMarcel Holtmann if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { 960f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); 961f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); 962f6b7712eSMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS); 963f9207338SMarcel Holtmann } 964801c1e8dSJohan Hedberg break; 965801c1e8dSJohan Hedberg } 966801c1e8dSJohan Hedberg 9677cc2ade2SMarcel Holtmann 9687cc2ade2SMarcel Holtmann hci_pi(sk)->channel = haddr.hci_channel; 9691da177e4SLinus Torvalds sk->sk_state = BT_BOUND; 9701da177e4SLinus Torvalds 9711da177e4SLinus Torvalds done: 9721da177e4SLinus Torvalds release_sock(sk); 9731da177e4SLinus Torvalds return err; 9741da177e4SLinus Torvalds } 9751da177e4SLinus Torvalds 9768fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, 9778fc9ced3SGustavo Padovan int *addr_len, int peer) 9781da177e4SLinus Torvalds { 9791da177e4SLinus Torvalds struct sockaddr_hci *haddr = (struct sockaddr_hci *)addr; 9801da177e4SLinus Torvalds struct sock *sk = sock->sk; 9819d4b68b2SMarcel Holtmann struct hci_dev *hdev; 9829d4b68b2SMarcel Holtmann int err = 0; 9831da177e4SLinus Torvalds 9841da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 9851da177e4SLinus Torvalds 98606f43cbcSMarcel Holtmann if (peer) 98706f43cbcSMarcel Holtmann return -EOPNOTSUPP; 98806f43cbcSMarcel Holtmann 9891da177e4SLinus Torvalds lock_sock(sk); 9901da177e4SLinus Torvalds 9919d4b68b2SMarcel Holtmann hdev = hci_pi(sk)->hdev; 9929d4b68b2SMarcel Holtmann if (!hdev) { 9939d4b68b2SMarcel Holtmann err = -EBADFD; 9949d4b68b2SMarcel Holtmann goto done; 9959d4b68b2SMarcel Holtmann } 9969d4b68b2SMarcel Holtmann 9971da177e4SLinus Torvalds *addr_len = sizeof(*haddr); 9981da177e4SLinus Torvalds haddr->hci_family = AF_BLUETOOTH; 9997b005bd3SMarcel Holtmann haddr->hci_dev = hdev->id; 10009d4b68b2SMarcel Holtmann haddr->hci_channel= hci_pi(sk)->channel; 10011da177e4SLinus Torvalds 10029d4b68b2SMarcel Holtmann done: 10031da177e4SLinus Torvalds release_sock(sk); 10049d4b68b2SMarcel Holtmann return err; 10051da177e4SLinus Torvalds } 10061da177e4SLinus Torvalds 10076039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, 10086039aa73SGustavo Padovan struct sk_buff *skb) 10091da177e4SLinus Torvalds { 10101da177e4SLinus Torvalds __u32 mask = hci_pi(sk)->cmsg_mask; 10111da177e4SLinus Torvalds 10120d48d939SMarcel Holtmann if (mask & HCI_CMSG_DIR) { 10130d48d939SMarcel Holtmann int incoming = bt_cb(skb)->incoming; 10148fc9ced3SGustavo Padovan put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), 10158fc9ced3SGustavo Padovan &incoming); 10160d48d939SMarcel Holtmann } 10171da177e4SLinus Torvalds 1018a61bbcf2SPatrick McHardy if (mask & HCI_CMSG_TSTAMP) { 1019f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT 1020f6e623a6SJohann Felix Soden struct compat_timeval ctv; 1021f6e623a6SJohann Felix Soden #endif 1022a61bbcf2SPatrick McHardy struct timeval tv; 1023767c5eb5SMarcel Holtmann void *data; 1024767c5eb5SMarcel Holtmann int len; 1025a61bbcf2SPatrick McHardy 1026a61bbcf2SPatrick McHardy skb_get_timestamp(skb, &tv); 1027767c5eb5SMarcel Holtmann 10281da97f83SDavid S. Miller data = &tv; 10291da97f83SDavid S. Miller len = sizeof(tv); 10301da97f83SDavid S. Miller #ifdef CONFIG_COMPAT 1031da88cea1SH. J. Lu if (!COMPAT_USE_64BIT_TIME && 1032da88cea1SH. J. Lu (msg->msg_flags & MSG_CMSG_COMPAT)) { 1033767c5eb5SMarcel Holtmann ctv.tv_sec = tv.tv_sec; 1034767c5eb5SMarcel Holtmann ctv.tv_usec = tv.tv_usec; 1035767c5eb5SMarcel Holtmann data = &ctv; 1036767c5eb5SMarcel Holtmann len = sizeof(ctv); 1037767c5eb5SMarcel Holtmann } 10381da97f83SDavid S. Miller #endif 1039767c5eb5SMarcel Holtmann 1040767c5eb5SMarcel Holtmann put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 1041a61bbcf2SPatrick McHardy } 10421da177e4SLinus Torvalds } 10431da177e4SLinus Torvalds 10448528d3f7SMarcel Holtmann static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, 10458528d3f7SMarcel Holtmann size_t len, int flags) 10461da177e4SLinus Torvalds { 10471da177e4SLinus Torvalds int noblock = flags & MSG_DONTWAIT; 10481da177e4SLinus Torvalds struct sock *sk = sock->sk; 10491da177e4SLinus Torvalds struct sk_buff *skb; 10501da177e4SLinus Torvalds int copied, err; 105183871f8cSDenis Kenzior unsigned int skblen; 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 10541da177e4SLinus Torvalds 1055d94a6104SMarcel Holtmann if (flags & MSG_OOB) 10561da177e4SLinus Torvalds return -EOPNOTSUPP; 10571da177e4SLinus Torvalds 1058ac714949SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_LOGGING) 1059ac714949SMarcel Holtmann return -EOPNOTSUPP; 1060ac714949SMarcel Holtmann 10611da177e4SLinus Torvalds if (sk->sk_state == BT_CLOSED) 10621da177e4SLinus Torvalds return 0; 10631da177e4SLinus Torvalds 106470f23020SAndrei Emeltchenko skb = skb_recv_datagram(sk, flags, noblock, &err); 106570f23020SAndrei Emeltchenko if (!skb) 10661da177e4SLinus Torvalds return err; 10671da177e4SLinus Torvalds 106883871f8cSDenis Kenzior skblen = skb->len; 10691da177e4SLinus Torvalds copied = skb->len; 10701da177e4SLinus Torvalds if (len < copied) { 10711da177e4SLinus Torvalds msg->msg_flags |= MSG_TRUNC; 10721da177e4SLinus Torvalds copied = len; 10731da177e4SLinus Torvalds } 10741da177e4SLinus Torvalds 1075badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb); 107651f3d02bSDavid S. Miller err = skb_copy_datagram_msg(skb, 0, msg, copied); 10771da177e4SLinus Torvalds 10783a208627SMarcel Holtmann switch (hci_pi(sk)->channel) { 10793a208627SMarcel Holtmann case HCI_CHANNEL_RAW: 10801da177e4SLinus Torvalds hci_sock_cmsg(sk, msg, skb); 10813a208627SMarcel Holtmann break; 108223500189SMarcel Holtmann case HCI_CHANNEL_USER: 1083cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1084cd82e61cSMarcel Holtmann sock_recv_timestamp(msg, sk, skb); 1085cd82e61cSMarcel Holtmann break; 1086801c1e8dSJohan Hedberg default: 1087801c1e8dSJohan Hedberg if (hci_mgmt_chan_find(hci_pi(sk)->channel)) 1088801c1e8dSJohan Hedberg sock_recv_timestamp(msg, sk, skb); 1089801c1e8dSJohan Hedberg break; 10903a208627SMarcel Holtmann } 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds skb_free_datagram(sk, skb); 10931da177e4SLinus Torvalds 1094*4f34228bSLuiz Augusto von Dentz if (flags & MSG_TRUNC) 109583871f8cSDenis Kenzior copied = skblen; 109683871f8cSDenis Kenzior 10971da177e4SLinus Torvalds return err ? : copied; 10981da177e4SLinus Torvalds } 10991da177e4SLinus Torvalds 1100fa4335d7SJohan Hedberg static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, 1101fa4335d7SJohan Hedberg struct msghdr *msg, size_t msglen) 1102fa4335d7SJohan Hedberg { 1103fa4335d7SJohan Hedberg void *buf; 1104fa4335d7SJohan Hedberg u8 *cp; 1105fa4335d7SJohan Hedberg struct mgmt_hdr *hdr; 1106fa4335d7SJohan Hedberg u16 opcode, index, len; 1107fa4335d7SJohan Hedberg struct hci_dev *hdev = NULL; 1108fa4335d7SJohan Hedberg const struct hci_mgmt_handler *handler; 1109fa4335d7SJohan Hedberg bool var_len, no_hdev; 1110fa4335d7SJohan Hedberg int err; 1111fa4335d7SJohan Hedberg 1112fa4335d7SJohan Hedberg BT_DBG("got %zu bytes", msglen); 1113fa4335d7SJohan Hedberg 1114fa4335d7SJohan Hedberg if (msglen < sizeof(*hdr)) 1115fa4335d7SJohan Hedberg return -EINVAL; 1116fa4335d7SJohan Hedberg 1117fa4335d7SJohan Hedberg buf = kmalloc(msglen, GFP_KERNEL); 1118fa4335d7SJohan Hedberg if (!buf) 1119fa4335d7SJohan Hedberg return -ENOMEM; 1120fa4335d7SJohan Hedberg 1121fa4335d7SJohan Hedberg if (memcpy_from_msg(buf, msg, msglen)) { 1122fa4335d7SJohan Hedberg err = -EFAULT; 1123fa4335d7SJohan Hedberg goto done; 1124fa4335d7SJohan Hedberg } 1125fa4335d7SJohan Hedberg 1126fa4335d7SJohan Hedberg hdr = buf; 1127fa4335d7SJohan Hedberg opcode = __le16_to_cpu(hdr->opcode); 1128fa4335d7SJohan Hedberg index = __le16_to_cpu(hdr->index); 1129fa4335d7SJohan Hedberg len = __le16_to_cpu(hdr->len); 1130fa4335d7SJohan Hedberg 1131fa4335d7SJohan Hedberg if (len != msglen - sizeof(*hdr)) { 1132fa4335d7SJohan Hedberg err = -EINVAL; 1133fa4335d7SJohan Hedberg goto done; 1134fa4335d7SJohan Hedberg } 1135fa4335d7SJohan Hedberg 1136fa4335d7SJohan Hedberg if (opcode >= chan->handler_count || 1137fa4335d7SJohan Hedberg chan->handlers[opcode].func == NULL) { 1138fa4335d7SJohan Hedberg BT_DBG("Unknown op %u", opcode); 1139fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1140fa4335d7SJohan Hedberg MGMT_STATUS_UNKNOWN_COMMAND); 1141fa4335d7SJohan Hedberg goto done; 1142fa4335d7SJohan Hedberg } 1143fa4335d7SJohan Hedberg 1144fa4335d7SJohan Hedberg handler = &chan->handlers[opcode]; 1145fa4335d7SJohan Hedberg 1146fa4335d7SJohan Hedberg if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && 1147fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNTRUSTED)) { 1148fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1149fa4335d7SJohan Hedberg MGMT_STATUS_PERMISSION_DENIED); 1150fa4335d7SJohan Hedberg goto done; 1151fa4335d7SJohan Hedberg } 1152fa4335d7SJohan Hedberg 1153fa4335d7SJohan Hedberg if (index != MGMT_INDEX_NONE) { 1154fa4335d7SJohan Hedberg hdev = hci_dev_get(index); 1155fa4335d7SJohan Hedberg if (!hdev) { 1156fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1157fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1158fa4335d7SJohan Hedberg goto done; 1159fa4335d7SJohan Hedberg } 1160fa4335d7SJohan Hedberg 1161fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_SETUP) || 1162fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_CONFIG) || 1163fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 1164fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1165fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1166fa4335d7SJohan Hedberg goto done; 1167fa4335d7SJohan Hedberg } 1168fa4335d7SJohan Hedberg 1169fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 1170fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNCONFIGURED)) { 1171fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1172fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1173fa4335d7SJohan Hedberg goto done; 1174fa4335d7SJohan Hedberg } 1175fa4335d7SJohan Hedberg } 1176fa4335d7SJohan Hedberg 1177fa4335d7SJohan Hedberg no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); 1178fa4335d7SJohan Hedberg if (no_hdev != !hdev) { 1179fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1180fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1181fa4335d7SJohan Hedberg goto done; 1182fa4335d7SJohan Hedberg } 1183fa4335d7SJohan Hedberg 1184fa4335d7SJohan Hedberg var_len = (handler->flags & HCI_MGMT_VAR_LEN); 1185fa4335d7SJohan Hedberg if ((var_len && len < handler->data_len) || 1186fa4335d7SJohan Hedberg (!var_len && len != handler->data_len)) { 1187fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1188fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_PARAMS); 1189fa4335d7SJohan Hedberg goto done; 1190fa4335d7SJohan Hedberg } 1191fa4335d7SJohan Hedberg 1192fa4335d7SJohan Hedberg if (hdev && chan->hdev_init) 1193fa4335d7SJohan Hedberg chan->hdev_init(sk, hdev); 1194fa4335d7SJohan Hedberg 1195fa4335d7SJohan Hedberg cp = buf + sizeof(*hdr); 1196fa4335d7SJohan Hedberg 1197fa4335d7SJohan Hedberg err = handler->func(sk, hdev, cp, len); 1198fa4335d7SJohan Hedberg if (err < 0) 1199fa4335d7SJohan Hedberg goto done; 1200fa4335d7SJohan Hedberg 1201fa4335d7SJohan Hedberg err = msglen; 1202fa4335d7SJohan Hedberg 1203fa4335d7SJohan Hedberg done: 1204fa4335d7SJohan Hedberg if (hdev) 1205fa4335d7SJohan Hedberg hci_dev_put(hdev); 1206fa4335d7SJohan Hedberg 1207fa4335d7SJohan Hedberg kfree(buf); 1208fa4335d7SJohan Hedberg return err; 1209fa4335d7SJohan Hedberg } 1210fa4335d7SJohan Hedberg 1211ac714949SMarcel Holtmann static int hci_logging_frame(struct sock *sk, struct msghdr *msg, int len) 1212ac714949SMarcel Holtmann { 1213ac714949SMarcel Holtmann struct hci_mon_hdr *hdr; 1214ac714949SMarcel Holtmann struct sk_buff *skb; 1215ac714949SMarcel Holtmann struct hci_dev *hdev; 1216ac714949SMarcel Holtmann u16 index; 1217ac714949SMarcel Holtmann int err; 1218ac714949SMarcel Holtmann 1219ac714949SMarcel Holtmann /* The logging frame consists at minimum of the standard header, 1220ac714949SMarcel Holtmann * the priority byte, the ident length byte and at least one string 1221ac714949SMarcel Holtmann * terminator NUL byte. Anything shorter are invalid packets. 1222ac714949SMarcel Holtmann */ 1223ac714949SMarcel Holtmann if (len < sizeof(*hdr) + 3) 1224ac714949SMarcel Holtmann return -EINVAL; 1225ac714949SMarcel Holtmann 1226ac714949SMarcel Holtmann skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 1227ac714949SMarcel Holtmann if (!skb) 1228ac714949SMarcel Holtmann return err; 1229ac714949SMarcel Holtmann 1230ac714949SMarcel Holtmann if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 1231ac714949SMarcel Holtmann err = -EFAULT; 1232ac714949SMarcel Holtmann goto drop; 1233ac714949SMarcel Holtmann } 1234ac714949SMarcel Holtmann 1235ac714949SMarcel Holtmann hdr = (void *)skb->data; 1236ac714949SMarcel Holtmann 1237ac714949SMarcel Holtmann if (__le16_to_cpu(hdr->len) != len - sizeof(*hdr)) { 1238ac714949SMarcel Holtmann err = -EINVAL; 1239ac714949SMarcel Holtmann goto drop; 1240ac714949SMarcel Holtmann } 1241ac714949SMarcel Holtmann 1242ac714949SMarcel Holtmann if (__le16_to_cpu(hdr->opcode) == 0x0000) { 1243ac714949SMarcel Holtmann __u8 priority = skb->data[sizeof(*hdr)]; 1244ac714949SMarcel Holtmann __u8 ident_len = skb->data[sizeof(*hdr) + 1]; 1245ac714949SMarcel Holtmann 1246ac714949SMarcel Holtmann /* Only the priorities 0-7 are valid and with that any other 1247ac714949SMarcel Holtmann * value results in an invalid packet. 1248ac714949SMarcel Holtmann * 1249ac714949SMarcel Holtmann * The priority byte is followed by an ident length byte and 1250ac714949SMarcel Holtmann * the NUL terminated ident string. Check that the ident 1251ac714949SMarcel Holtmann * length is not overflowing the packet and also that the 1252ac714949SMarcel Holtmann * ident string itself is NUL terminated. In case the ident 1253ac714949SMarcel Holtmann * length is zero, the length value actually doubles as NUL 1254ac714949SMarcel Holtmann * terminator identifier. 1255ac714949SMarcel Holtmann * 1256ac714949SMarcel Holtmann * The message follows the ident string (if present) and 1257ac714949SMarcel Holtmann * must be NUL terminated. Otherwise it is not a valid packet. 1258ac714949SMarcel Holtmann */ 1259ac714949SMarcel Holtmann if (priority > 7 || skb->data[len - 1] != 0x00 || 1260ac714949SMarcel Holtmann ident_len > len - sizeof(*hdr) - 3 || 1261ac714949SMarcel Holtmann skb->data[sizeof(*hdr) + ident_len + 1] != 0x00) { 1262ac714949SMarcel Holtmann err = -EINVAL; 1263ac714949SMarcel Holtmann goto drop; 1264ac714949SMarcel Holtmann } 1265ac714949SMarcel Holtmann } else { 1266ac714949SMarcel Holtmann err = -EINVAL; 1267ac714949SMarcel Holtmann goto drop; 1268ac714949SMarcel Holtmann } 1269ac714949SMarcel Holtmann 1270ac714949SMarcel Holtmann index = __le16_to_cpu(hdr->index); 1271ac714949SMarcel Holtmann 1272ac714949SMarcel Holtmann if (index != MGMT_INDEX_NONE) { 1273ac714949SMarcel Holtmann hdev = hci_dev_get(index); 1274ac714949SMarcel Holtmann if (!hdev) { 1275ac714949SMarcel Holtmann err = -ENODEV; 1276ac714949SMarcel Holtmann goto drop; 1277ac714949SMarcel Holtmann } 1278ac714949SMarcel Holtmann } else { 1279ac714949SMarcel Holtmann hdev = NULL; 1280ac714949SMarcel Holtmann } 1281ac714949SMarcel Holtmann 1282ac714949SMarcel Holtmann hdr->opcode = cpu_to_le16(HCI_MON_USER_LOGGING); 1283ac714949SMarcel Holtmann 1284ac714949SMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, HCI_SOCK_TRUSTED, NULL); 1285ac714949SMarcel Holtmann err = len; 1286ac714949SMarcel Holtmann 1287ac714949SMarcel Holtmann if (hdev) 1288ac714949SMarcel Holtmann hci_dev_put(hdev); 1289ac714949SMarcel Holtmann 1290ac714949SMarcel Holtmann drop: 1291ac714949SMarcel Holtmann kfree_skb(skb); 1292ac714949SMarcel Holtmann return err; 1293ac714949SMarcel Holtmann } 1294ac714949SMarcel Holtmann 12951b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, 12961b784140SYing Xue size_t len) 12971da177e4SLinus Torvalds { 12981da177e4SLinus Torvalds struct sock *sk = sock->sk; 1299801c1e8dSJohan Hedberg struct hci_mgmt_chan *chan; 13001da177e4SLinus Torvalds struct hci_dev *hdev; 13011da177e4SLinus Torvalds struct sk_buff *skb; 13021da177e4SLinus Torvalds int err; 13031da177e4SLinus Torvalds 13041da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 13051da177e4SLinus Torvalds 13061da177e4SLinus Torvalds if (msg->msg_flags & MSG_OOB) 13071da177e4SLinus Torvalds return -EOPNOTSUPP; 13081da177e4SLinus Torvalds 13091da177e4SLinus Torvalds if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 13101da177e4SLinus Torvalds return -EINVAL; 13111da177e4SLinus Torvalds 13121da177e4SLinus Torvalds if (len < 4 || len > HCI_MAX_FRAME_SIZE) 13131da177e4SLinus Torvalds return -EINVAL; 13141da177e4SLinus Torvalds 13151da177e4SLinus Torvalds lock_sock(sk); 13161da177e4SLinus Torvalds 13170381101fSJohan Hedberg switch (hci_pi(sk)->channel) { 13180381101fSJohan Hedberg case HCI_CHANNEL_RAW: 131923500189SMarcel Holtmann case HCI_CHANNEL_USER: 13200381101fSJohan Hedberg break; 1321cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1322cd82e61cSMarcel Holtmann err = -EOPNOTSUPP; 1323cd82e61cSMarcel Holtmann goto done; 1324ac714949SMarcel Holtmann case HCI_CHANNEL_LOGGING: 1325ac714949SMarcel Holtmann err = hci_logging_frame(sk, msg, len); 1326ac714949SMarcel Holtmann goto done; 13270381101fSJohan Hedberg default: 1328801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 1329801c1e8dSJohan Hedberg chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); 1330801c1e8dSJohan Hedberg if (chan) 1331fa4335d7SJohan Hedberg err = hci_mgmt_cmd(chan, sk, msg, len); 1332801c1e8dSJohan Hedberg else 13330381101fSJohan Hedberg err = -EINVAL; 1334801c1e8dSJohan Hedberg 1335801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 13360381101fSJohan Hedberg goto done; 13370381101fSJohan Hedberg } 13380381101fSJohan Hedberg 133970f23020SAndrei Emeltchenko hdev = hci_pi(sk)->hdev; 134070f23020SAndrei Emeltchenko if (!hdev) { 13411da177e4SLinus Torvalds err = -EBADFD; 13421da177e4SLinus Torvalds goto done; 13431da177e4SLinus Torvalds } 13441da177e4SLinus Torvalds 13457e21addcSMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) { 13467e21addcSMarcel Holtmann err = -ENETDOWN; 13477e21addcSMarcel Holtmann goto done; 13487e21addcSMarcel Holtmann } 13497e21addcSMarcel Holtmann 135070f23020SAndrei Emeltchenko skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 135170f23020SAndrei Emeltchenko if (!skb) 13521da177e4SLinus Torvalds goto done; 13531da177e4SLinus Torvalds 13546ce8e9ceSAl Viro if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 13551da177e4SLinus Torvalds err = -EFAULT; 13561da177e4SLinus Torvalds goto drop; 13571da177e4SLinus Torvalds } 13581da177e4SLinus Torvalds 13598528d3f7SMarcel Holtmann hci_skb_pkt_type(skb) = skb->data[0]; 13601da177e4SLinus Torvalds skb_pull(skb, 1); 13611da177e4SLinus Torvalds 13621bc5ad16SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 13631bc5ad16SMarcel Holtmann /* No permission check is needed for user channel 13641bc5ad16SMarcel Holtmann * since that gets enforced when binding the socket. 13651bc5ad16SMarcel Holtmann * 13661bc5ad16SMarcel Holtmann * However check that the packet type is valid. 13671bc5ad16SMarcel Holtmann */ 1368d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && 1369d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 1370d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { 13711bc5ad16SMarcel Holtmann err = -EINVAL; 13721bc5ad16SMarcel Holtmann goto drop; 13731bc5ad16SMarcel Holtmann } 13741bc5ad16SMarcel Holtmann 13751bc5ad16SMarcel Holtmann skb_queue_tail(&hdev->raw_q, skb); 13761bc5ad16SMarcel Holtmann queue_work(hdev->workqueue, &hdev->tx_work); 1377d79f34e3SMarcel Holtmann } else if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) { 137883985319SHarvey Harrison u16 opcode = get_unaligned_le16(skb->data); 13791da177e4SLinus Torvalds u16 ogf = hci_opcode_ogf(opcode); 13801da177e4SLinus Torvalds u16 ocf = hci_opcode_ocf(opcode); 13811da177e4SLinus Torvalds 13821da177e4SLinus Torvalds if (((ogf > HCI_SFLT_MAX_OGF) || 13833bb3c755SGustavo Padovan !hci_test_bit(ocf & HCI_FLT_OCF_BITS, 13843bb3c755SGustavo Padovan &hci_sec_filter.ocf_mask[ogf])) && 13851da177e4SLinus Torvalds !capable(CAP_NET_RAW)) { 13861da177e4SLinus Torvalds err = -EPERM; 13871da177e4SLinus Torvalds goto drop; 13881da177e4SLinus Torvalds } 13891da177e4SLinus Torvalds 13901982162bSMarcel Holtmann /* Since the opcode has already been extracted here, store 13911982162bSMarcel Holtmann * a copy of the value for later use by the drivers. 13921982162bSMarcel Holtmann */ 13931982162bSMarcel Holtmann hci_skb_opcode(skb) = opcode; 13941982162bSMarcel Holtmann 1395fee746b0SMarcel Holtmann if (ogf == 0x3f) { 13961da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 13973eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 13981da177e4SLinus Torvalds } else { 139949c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as 140011714b3dSJohan Hedberg * single-command requests. 140111714b3dSJohan Hedberg */ 140244d27137SJohan Hedberg bt_cb(skb)->hci.req_flags |= HCI_REQ_START; 140311714b3dSJohan Hedberg 14041da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb); 1405c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 14061da177e4SLinus Torvalds } 14071da177e4SLinus Torvalds } else { 14081da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 14091da177e4SLinus Torvalds err = -EPERM; 14101da177e4SLinus Torvalds goto drop; 14111da177e4SLinus Torvalds } 14121da177e4SLinus Torvalds 1413d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 1414d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { 1415bb77543eSMarcel Holtmann err = -EINVAL; 1416bb77543eSMarcel Holtmann goto drop; 1417bb77543eSMarcel Holtmann } 1418bb77543eSMarcel Holtmann 14191da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 14203eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds err = len; 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds done: 14261da177e4SLinus Torvalds release_sock(sk); 14271da177e4SLinus Torvalds return err; 14281da177e4SLinus Torvalds 14291da177e4SLinus Torvalds drop: 14301da177e4SLinus Torvalds kfree_skb(skb); 14311da177e4SLinus Torvalds goto done; 14321da177e4SLinus Torvalds } 14331da177e4SLinus Torvalds 14348fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname, 14358fc9ced3SGustavo Padovan char __user *optval, unsigned int len) 14361da177e4SLinus Torvalds { 14371da177e4SLinus Torvalds struct hci_ufilter uf = { .opcode = 0 }; 14381da177e4SLinus Torvalds struct sock *sk = sock->sk; 14391da177e4SLinus Torvalds int err = 0, opt = 0; 14401da177e4SLinus Torvalds 14411da177e4SLinus Torvalds BT_DBG("sk %p, opt %d", sk, optname); 14421da177e4SLinus Torvalds 14431da177e4SLinus Torvalds lock_sock(sk); 14441da177e4SLinus Torvalds 14452f39cdb7SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1446c2371e80SMarcel Holtmann err = -EBADFD; 14472f39cdb7SMarcel Holtmann goto done; 14482f39cdb7SMarcel Holtmann } 14492f39cdb7SMarcel Holtmann 14501da177e4SLinus Torvalds switch (optname) { 14511da177e4SLinus Torvalds case HCI_DATA_DIR: 14521da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 14531da177e4SLinus Torvalds err = -EFAULT; 14541da177e4SLinus Torvalds break; 14551da177e4SLinus Torvalds } 14561da177e4SLinus Torvalds 14571da177e4SLinus Torvalds if (opt) 14581da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 14591da177e4SLinus Torvalds else 14601da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 14611da177e4SLinus Torvalds break; 14621da177e4SLinus Torvalds 14631da177e4SLinus Torvalds case HCI_TIME_STAMP: 14641da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 14651da177e4SLinus Torvalds err = -EFAULT; 14661da177e4SLinus Torvalds break; 14671da177e4SLinus Torvalds } 14681da177e4SLinus Torvalds 14691da177e4SLinus Torvalds if (opt) 14701da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 14711da177e4SLinus Torvalds else 14721da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 14731da177e4SLinus Torvalds break; 14741da177e4SLinus Torvalds 14751da177e4SLinus Torvalds case HCI_FILTER: 14760878b666SMarcel Holtmann { 14770878b666SMarcel Holtmann struct hci_filter *f = &hci_pi(sk)->filter; 14780878b666SMarcel Holtmann 14790878b666SMarcel Holtmann uf.type_mask = f->type_mask; 14800878b666SMarcel Holtmann uf.opcode = f->opcode; 14810878b666SMarcel Holtmann uf.event_mask[0] = *((u32 *) f->event_mask + 0); 14820878b666SMarcel Holtmann uf.event_mask[1] = *((u32 *) f->event_mask + 1); 14830878b666SMarcel Holtmann } 14840878b666SMarcel Holtmann 14851da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 14861da177e4SLinus Torvalds if (copy_from_user(&uf, optval, len)) { 14871da177e4SLinus Torvalds err = -EFAULT; 14881da177e4SLinus Torvalds break; 14891da177e4SLinus Torvalds } 14901da177e4SLinus Torvalds 14911da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 14921da177e4SLinus Torvalds uf.type_mask &= hci_sec_filter.type_mask; 14931da177e4SLinus Torvalds uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 14941da177e4SLinus Torvalds uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 14951da177e4SLinus Torvalds } 14961da177e4SLinus Torvalds 14971da177e4SLinus Torvalds { 14981da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 14991da177e4SLinus Torvalds 15001da177e4SLinus Torvalds f->type_mask = uf.type_mask; 15011da177e4SLinus Torvalds f->opcode = uf.opcode; 15021da177e4SLinus Torvalds *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 15031da177e4SLinus Torvalds *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 15041da177e4SLinus Torvalds } 15051da177e4SLinus Torvalds break; 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds default: 15081da177e4SLinus Torvalds err = -ENOPROTOOPT; 15091da177e4SLinus Torvalds break; 15101da177e4SLinus Torvalds } 15111da177e4SLinus Torvalds 15122f39cdb7SMarcel Holtmann done: 15131da177e4SLinus Torvalds release_sock(sk); 15141da177e4SLinus Torvalds return err; 15151da177e4SLinus Torvalds } 15161da177e4SLinus Torvalds 15178fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname, 15188fc9ced3SGustavo Padovan char __user *optval, int __user *optlen) 15191da177e4SLinus Torvalds { 15201da177e4SLinus Torvalds struct hci_ufilter uf; 15211da177e4SLinus Torvalds struct sock *sk = sock->sk; 1522cedc5469SMarcel Holtmann int len, opt, err = 0; 1523cedc5469SMarcel Holtmann 1524cedc5469SMarcel Holtmann BT_DBG("sk %p, opt %d", sk, optname); 15251da177e4SLinus Torvalds 15261da177e4SLinus Torvalds if (get_user(len, optlen)) 15271da177e4SLinus Torvalds return -EFAULT; 15281da177e4SLinus Torvalds 1529cedc5469SMarcel Holtmann lock_sock(sk); 1530cedc5469SMarcel Holtmann 1531cedc5469SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1532c2371e80SMarcel Holtmann err = -EBADFD; 1533cedc5469SMarcel Holtmann goto done; 1534cedc5469SMarcel Holtmann } 1535cedc5469SMarcel Holtmann 15361da177e4SLinus Torvalds switch (optname) { 15371da177e4SLinus Torvalds case HCI_DATA_DIR: 15381da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 15391da177e4SLinus Torvalds opt = 1; 15401da177e4SLinus Torvalds else 15411da177e4SLinus Torvalds opt = 0; 15421da177e4SLinus Torvalds 15431da177e4SLinus Torvalds if (put_user(opt, optval)) 1544cedc5469SMarcel Holtmann err = -EFAULT; 15451da177e4SLinus Torvalds break; 15461da177e4SLinus Torvalds 15471da177e4SLinus Torvalds case HCI_TIME_STAMP: 15481da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 15491da177e4SLinus Torvalds opt = 1; 15501da177e4SLinus Torvalds else 15511da177e4SLinus Torvalds opt = 0; 15521da177e4SLinus Torvalds 15531da177e4SLinus Torvalds if (put_user(opt, optval)) 1554cedc5469SMarcel Holtmann err = -EFAULT; 15551da177e4SLinus Torvalds break; 15561da177e4SLinus Torvalds 15571da177e4SLinus Torvalds case HCI_FILTER: 15581da177e4SLinus Torvalds { 15591da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 15601da177e4SLinus Torvalds 1561e15ca9a0SMathias Krause memset(&uf, 0, sizeof(uf)); 15621da177e4SLinus Torvalds uf.type_mask = f->type_mask; 15631da177e4SLinus Torvalds uf.opcode = f->opcode; 15641da177e4SLinus Torvalds uf.event_mask[0] = *((u32 *) f->event_mask + 0); 15651da177e4SLinus Torvalds uf.event_mask[1] = *((u32 *) f->event_mask + 1); 15661da177e4SLinus Torvalds } 15671da177e4SLinus Torvalds 15681da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 15691da177e4SLinus Torvalds if (copy_to_user(optval, &uf, len)) 1570cedc5469SMarcel Holtmann err = -EFAULT; 15711da177e4SLinus Torvalds break; 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds default: 1574cedc5469SMarcel Holtmann err = -ENOPROTOOPT; 15751da177e4SLinus Torvalds break; 15761da177e4SLinus Torvalds } 15771da177e4SLinus Torvalds 1578cedc5469SMarcel Holtmann done: 1579cedc5469SMarcel Holtmann release_sock(sk); 1580cedc5469SMarcel Holtmann return err; 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds 158390ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = { 15841da177e4SLinus Torvalds .family = PF_BLUETOOTH, 15851da177e4SLinus Torvalds .owner = THIS_MODULE, 15861da177e4SLinus Torvalds .release = hci_sock_release, 15871da177e4SLinus Torvalds .bind = hci_sock_bind, 15881da177e4SLinus Torvalds .getname = hci_sock_getname, 15891da177e4SLinus Torvalds .sendmsg = hci_sock_sendmsg, 15901da177e4SLinus Torvalds .recvmsg = hci_sock_recvmsg, 15911da177e4SLinus Torvalds .ioctl = hci_sock_ioctl, 15921da177e4SLinus Torvalds .poll = datagram_poll, 15931da177e4SLinus Torvalds .listen = sock_no_listen, 15941da177e4SLinus Torvalds .shutdown = sock_no_shutdown, 15951da177e4SLinus Torvalds .setsockopt = hci_sock_setsockopt, 15961da177e4SLinus Torvalds .getsockopt = hci_sock_getsockopt, 15971da177e4SLinus Torvalds .connect = sock_no_connect, 15981da177e4SLinus Torvalds .socketpair = sock_no_socketpair, 15991da177e4SLinus Torvalds .accept = sock_no_accept, 16001da177e4SLinus Torvalds .mmap = sock_no_mmap 16011da177e4SLinus Torvalds }; 16021da177e4SLinus Torvalds 16031da177e4SLinus Torvalds static struct proto hci_sk_proto = { 16041da177e4SLinus Torvalds .name = "HCI", 16051da177e4SLinus Torvalds .owner = THIS_MODULE, 16061da177e4SLinus Torvalds .obj_size = sizeof(struct hci_pinfo) 16071da177e4SLinus Torvalds }; 16081da177e4SLinus Torvalds 16093f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 16103f378b68SEric Paris int kern) 16111da177e4SLinus Torvalds { 16121da177e4SLinus Torvalds struct sock *sk; 16131da177e4SLinus Torvalds 16141da177e4SLinus Torvalds BT_DBG("sock %p", sock); 16151da177e4SLinus Torvalds 16161da177e4SLinus Torvalds if (sock->type != SOCK_RAW) 16171da177e4SLinus Torvalds return -ESOCKTNOSUPPORT; 16181da177e4SLinus Torvalds 16191da177e4SLinus Torvalds sock->ops = &hci_sock_ops; 16201da177e4SLinus Torvalds 162111aa9c28SEric W. Biederman sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern); 16221da177e4SLinus Torvalds if (!sk) 16231da177e4SLinus Torvalds return -ENOMEM; 16241da177e4SLinus Torvalds 16251da177e4SLinus Torvalds sock_init_data(sock, sk); 16261da177e4SLinus Torvalds 16271da177e4SLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 16281da177e4SLinus Torvalds 16291da177e4SLinus Torvalds sk->sk_protocol = protocol; 16301da177e4SLinus Torvalds 16311da177e4SLinus Torvalds sock->state = SS_UNCONNECTED; 16321da177e4SLinus Torvalds sk->sk_state = BT_OPEN; 16331da177e4SLinus Torvalds 16341da177e4SLinus Torvalds bt_sock_link(&hci_sk_list, sk); 16351da177e4SLinus Torvalds return 0; 16361da177e4SLinus Torvalds } 16371da177e4SLinus Torvalds 1638ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = { 16391da177e4SLinus Torvalds .family = PF_BLUETOOTH, 16401da177e4SLinus Torvalds .owner = THIS_MODULE, 16411da177e4SLinus Torvalds .create = hci_sock_create, 16421da177e4SLinus Torvalds }; 16431da177e4SLinus Torvalds 16441da177e4SLinus Torvalds int __init hci_sock_init(void) 16451da177e4SLinus Torvalds { 16461da177e4SLinus Torvalds int err; 16471da177e4SLinus Torvalds 1648b0a8e282SMarcel Holtmann BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr)); 1649b0a8e282SMarcel Holtmann 16501da177e4SLinus Torvalds err = proto_register(&hci_sk_proto, 0); 16511da177e4SLinus Torvalds if (err < 0) 16521da177e4SLinus Torvalds return err; 16531da177e4SLinus Torvalds 16541da177e4SLinus Torvalds err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 1655f7c86637SMasatake YAMATO if (err < 0) { 1656f7c86637SMasatake YAMATO BT_ERR("HCI socket registration failed"); 16571da177e4SLinus Torvalds goto error; 1658f7c86637SMasatake YAMATO } 1659f7c86637SMasatake YAMATO 1660b0316615SAl Viro err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL); 1661f7c86637SMasatake YAMATO if (err < 0) { 1662f7c86637SMasatake YAMATO BT_ERR("Failed to create HCI proc file"); 1663f7c86637SMasatake YAMATO bt_sock_unregister(BTPROTO_HCI); 1664f7c86637SMasatake YAMATO goto error; 1665f7c86637SMasatake YAMATO } 16661da177e4SLinus Torvalds 16671da177e4SLinus Torvalds BT_INFO("HCI socket layer initialized"); 16681da177e4SLinus Torvalds 16691da177e4SLinus Torvalds return 0; 16701da177e4SLinus Torvalds 16711da177e4SLinus Torvalds error: 16721da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 16731da177e4SLinus Torvalds return err; 16741da177e4SLinus Torvalds } 16751da177e4SLinus Torvalds 1676b7440a14SAnand Gadiyar void hci_sock_cleanup(void) 16771da177e4SLinus Torvalds { 1678f7c86637SMasatake YAMATO bt_procfs_cleanup(&init_net, "hci"); 16795e9d7f86SDavid Herrmann bt_sock_unregister(BTPROTO_HCI); 16801da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 16811da177e4SLinus Torvalds } 1682