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> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 311da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 32cd82e61cSMarcel Holtmann #include <net/bluetooth/hci_mon.h> 33fa4335d7SJohan Hedberg #include <net/bluetooth/mgmt.h> 34fa4335d7SJohan Hedberg 35fa4335d7SJohan Hedberg #include "mgmt_util.h" 361da177e4SLinus Torvalds 37801c1e8dSJohan Hedberg static LIST_HEAD(mgmt_chan_list); 38801c1e8dSJohan Hedberg static DEFINE_MUTEX(mgmt_chan_list_lock); 39801c1e8dSJohan Hedberg 40cd82e61cSMarcel Holtmann static atomic_t monitor_promisc = ATOMIC_INIT(0); 41cd82e61cSMarcel Holtmann 421da177e4SLinus Torvalds /* ----- HCI socket interface ----- */ 431da177e4SLinus Torvalds 44863def58SMarcel Holtmann /* Socket info */ 45863def58SMarcel Holtmann #define hci_pi(sk) ((struct hci_pinfo *) sk) 46863def58SMarcel Holtmann 47863def58SMarcel Holtmann struct hci_pinfo { 48863def58SMarcel Holtmann struct bt_sock bt; 49863def58SMarcel Holtmann struct hci_dev *hdev; 50863def58SMarcel Holtmann struct hci_filter filter; 51863def58SMarcel Holtmann __u32 cmsg_mask; 52863def58SMarcel Holtmann unsigned short channel; 536befc644SMarcel Holtmann unsigned long flags; 54863def58SMarcel Holtmann }; 55863def58SMarcel Holtmann 566befc644SMarcel Holtmann void hci_sock_set_flag(struct sock *sk, int nr) 576befc644SMarcel Holtmann { 586befc644SMarcel Holtmann set_bit(nr, &hci_pi(sk)->flags); 596befc644SMarcel Holtmann } 606befc644SMarcel Holtmann 616befc644SMarcel Holtmann void hci_sock_clear_flag(struct sock *sk, int nr) 626befc644SMarcel Holtmann { 636befc644SMarcel Holtmann clear_bit(nr, &hci_pi(sk)->flags); 646befc644SMarcel Holtmann } 656befc644SMarcel Holtmann 66c85be545SMarcel Holtmann int hci_sock_test_flag(struct sock *sk, int nr) 67c85be545SMarcel Holtmann { 68c85be545SMarcel Holtmann return test_bit(nr, &hci_pi(sk)->flags); 69c85be545SMarcel Holtmann } 70c85be545SMarcel Holtmann 71d0f172b1SJohan Hedberg unsigned short hci_sock_get_channel(struct sock *sk) 72d0f172b1SJohan Hedberg { 73d0f172b1SJohan Hedberg return hci_pi(sk)->channel; 74d0f172b1SJohan Hedberg } 75d0f172b1SJohan Hedberg 769391976aSJiri Slaby static inline int hci_test_bit(int nr, const void *addr) 771da177e4SLinus Torvalds { 789391976aSJiri Slaby return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds /* Security filter */ 823ad254f7SMarcel Holtmann #define HCI_SFLT_MAX_OGF 5 833ad254f7SMarcel Holtmann 843ad254f7SMarcel Holtmann struct hci_sec_filter { 853ad254f7SMarcel Holtmann __u32 type_mask; 863ad254f7SMarcel Holtmann __u32 event_mask[2]; 873ad254f7SMarcel Holtmann __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; 883ad254f7SMarcel Holtmann }; 893ad254f7SMarcel Holtmann 907e67c112SMarcel Holtmann static const struct hci_sec_filter hci_sec_filter = { 911da177e4SLinus Torvalds /* Packet types */ 921da177e4SLinus Torvalds 0x10, 931da177e4SLinus Torvalds /* Events */ 94dd7f5527SMarcel Holtmann { 0x1000d9fe, 0x0000b00c }, 951da177e4SLinus Torvalds /* Commands */ 961da177e4SLinus Torvalds { 971da177e4SLinus Torvalds { 0x0 }, 981da177e4SLinus Torvalds /* OGF_LINK_CTL */ 997c631a67SMarcel Holtmann { 0xbe000006, 0x00000001, 0x00000000, 0x00 }, 1001da177e4SLinus Torvalds /* OGF_LINK_POLICY */ 1017c631a67SMarcel Holtmann { 0x00005200, 0x00000000, 0x00000000, 0x00 }, 1021da177e4SLinus Torvalds /* OGF_HOST_CTL */ 1037c631a67SMarcel Holtmann { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 }, 1041da177e4SLinus Torvalds /* OGF_INFO_PARAM */ 1057c631a67SMarcel Holtmann { 0x000002be, 0x00000000, 0x00000000, 0x00 }, 1061da177e4SLinus Torvalds /* OGF_STATUS_PARAM */ 1077c631a67SMarcel Holtmann { 0x000000ea, 0x00000000, 0x00000000, 0x00 } 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds }; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds static struct bt_sock_list hci_sk_list = { 112d5fb2962SRobert P. J. Day .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) 1131da177e4SLinus Torvalds }; 1141da177e4SLinus Torvalds 115f81fe64fSMarcel Holtmann static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb) 116f81fe64fSMarcel Holtmann { 117f81fe64fSMarcel Holtmann struct hci_filter *flt; 118f81fe64fSMarcel Holtmann int flt_type, flt_event; 119f81fe64fSMarcel Holtmann 120f81fe64fSMarcel Holtmann /* Apply filter */ 121f81fe64fSMarcel Holtmann flt = &hci_pi(sk)->filter; 122f81fe64fSMarcel Holtmann 123f81fe64fSMarcel Holtmann if (bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) 124f81fe64fSMarcel Holtmann flt_type = 0; 125f81fe64fSMarcel Holtmann else 126f81fe64fSMarcel Holtmann flt_type = bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS; 127f81fe64fSMarcel Holtmann 128f81fe64fSMarcel Holtmann if (!test_bit(flt_type, &flt->type_mask)) 129f81fe64fSMarcel Holtmann return true; 130f81fe64fSMarcel Holtmann 131f81fe64fSMarcel Holtmann /* Extra filter for event packets only */ 132f81fe64fSMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT) 133f81fe64fSMarcel Holtmann return false; 134f81fe64fSMarcel Holtmann 135f81fe64fSMarcel Holtmann flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); 136f81fe64fSMarcel Holtmann 137f81fe64fSMarcel Holtmann if (!hci_test_bit(flt_event, &flt->event_mask)) 138f81fe64fSMarcel Holtmann return true; 139f81fe64fSMarcel Holtmann 140f81fe64fSMarcel Holtmann /* Check filter only when opcode is set */ 141f81fe64fSMarcel Holtmann if (!flt->opcode) 142f81fe64fSMarcel Holtmann return false; 143f81fe64fSMarcel Holtmann 144f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_COMPLETE && 145f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 3))) 146f81fe64fSMarcel Holtmann return true; 147f81fe64fSMarcel Holtmann 148f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_STATUS && 149f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 4))) 150f81fe64fSMarcel Holtmann return true; 151f81fe64fSMarcel Holtmann 152f81fe64fSMarcel Holtmann return false; 153f81fe64fSMarcel Holtmann } 154f81fe64fSMarcel Holtmann 1551da177e4SLinus Torvalds /* Send frame to RAW socket */ 156470fe1b5SMarcel Holtmann void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) 1571da177e4SLinus Torvalds { 1581da177e4SLinus Torvalds struct sock *sk; 159e0edf373SMarcel Holtmann struct sk_buff *skb_copy = NULL; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds BT_DBG("hdev %p len %d", hdev, skb->len); 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds read_lock(&hci_sk_list.lock); 164470fe1b5SMarcel Holtmann 165b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 1661da177e4SLinus Torvalds struct sk_buff *nskb; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 1691da177e4SLinus Torvalds continue; 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds /* Don't send frame to the socket it came from */ 1721da177e4SLinus Torvalds if (skb->sk == sk) 1731da177e4SLinus Torvalds continue; 1741da177e4SLinus Torvalds 17523500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { 176f81fe64fSMarcel Holtmann if (is_filtered_packet(sk, skb)) 1771da177e4SLinus Torvalds continue; 17823500189SMarcel Holtmann } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 17923500189SMarcel Holtmann if (!bt_cb(skb)->incoming) 18023500189SMarcel Holtmann continue; 18123500189SMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT && 18223500189SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && 18323500189SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) 18423500189SMarcel Holtmann continue; 18523500189SMarcel Holtmann } else { 18623500189SMarcel Holtmann /* Don't send frame to other channel types */ 18723500189SMarcel Holtmann continue; 18823500189SMarcel Holtmann } 1891da177e4SLinus Torvalds 190e0edf373SMarcel Holtmann if (!skb_copy) { 191e0edf373SMarcel Holtmann /* Create a private copy with headroom */ 192bad93e9dSOctavian Purdila skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true); 193e0edf373SMarcel Holtmann if (!skb_copy) 1941da177e4SLinus Torvalds continue; 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds /* Put type byte before the data */ 197e0edf373SMarcel Holtmann memcpy(skb_push(skb_copy, 1), &bt_cb(skb)->pkt_type, 1); 198e0edf373SMarcel Holtmann } 199e0edf373SMarcel Holtmann 200e0edf373SMarcel Holtmann nskb = skb_clone(skb_copy, GFP_ATOMIC); 201e0edf373SMarcel Holtmann if (!nskb) 202e0edf373SMarcel Holtmann continue; 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds if (sock_queue_rcv_skb(sk, nskb)) 2051da177e4SLinus Torvalds kfree_skb(nskb); 2061da177e4SLinus Torvalds } 207470fe1b5SMarcel Holtmann 208470fe1b5SMarcel Holtmann read_unlock(&hci_sk_list.lock); 209e0edf373SMarcel Holtmann 210e0edf373SMarcel Holtmann kfree_skb(skb_copy); 211470fe1b5SMarcel Holtmann } 212470fe1b5SMarcel Holtmann 2137129069eSJohan Hedberg /* Send frame to sockets with specific channel */ 2147129069eSJohan Hedberg void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, 215c08b1a1dSMarcel Holtmann int flag, struct sock *skip_sk) 216470fe1b5SMarcel Holtmann { 217470fe1b5SMarcel Holtmann struct sock *sk; 218470fe1b5SMarcel Holtmann 2197129069eSJohan Hedberg BT_DBG("channel %u len %d", channel, skb->len); 220470fe1b5SMarcel Holtmann 221470fe1b5SMarcel Holtmann read_lock(&hci_sk_list.lock); 222470fe1b5SMarcel Holtmann 223b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 224470fe1b5SMarcel Holtmann struct sk_buff *nskb; 225470fe1b5SMarcel Holtmann 226c08b1a1dSMarcel Holtmann /* Ignore socket without the flag set */ 227c85be545SMarcel Holtmann if (!hci_sock_test_flag(sk, flag)) 228c08b1a1dSMarcel Holtmann continue; 229c08b1a1dSMarcel Holtmann 230470fe1b5SMarcel Holtmann /* Skip the original socket */ 231470fe1b5SMarcel Holtmann if (sk == skip_sk) 232470fe1b5SMarcel Holtmann continue; 233470fe1b5SMarcel Holtmann 234470fe1b5SMarcel Holtmann if (sk->sk_state != BT_BOUND) 235470fe1b5SMarcel Holtmann continue; 236470fe1b5SMarcel Holtmann 2377129069eSJohan Hedberg if (hci_pi(sk)->channel != channel) 238d7f72f61SMarcel Holtmann continue; 239d7f72f61SMarcel Holtmann 240d7f72f61SMarcel Holtmann nskb = skb_clone(skb, GFP_ATOMIC); 241d7f72f61SMarcel Holtmann if (!nskb) 242d7f72f61SMarcel Holtmann continue; 243d7f72f61SMarcel Holtmann 244d7f72f61SMarcel Holtmann if (sock_queue_rcv_skb(sk, nskb)) 245d7f72f61SMarcel Holtmann kfree_skb(nskb); 246d7f72f61SMarcel Holtmann } 247d7f72f61SMarcel Holtmann 248d7f72f61SMarcel Holtmann read_unlock(&hci_sk_list.lock); 249d7f72f61SMarcel Holtmann } 250d7f72f61SMarcel Holtmann 251cd82e61cSMarcel Holtmann /* Send frame to monitor socket */ 252cd82e61cSMarcel Holtmann void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) 253cd82e61cSMarcel Holtmann { 254cd82e61cSMarcel Holtmann struct sk_buff *skb_copy = NULL; 2552b531294SMarcel Holtmann struct hci_mon_hdr *hdr; 256cd82e61cSMarcel Holtmann __le16 opcode; 257cd82e61cSMarcel Holtmann 258cd82e61cSMarcel Holtmann if (!atomic_read(&monitor_promisc)) 259cd82e61cSMarcel Holtmann return; 260cd82e61cSMarcel Holtmann 261cd82e61cSMarcel Holtmann BT_DBG("hdev %p len %d", hdev, skb->len); 262cd82e61cSMarcel Holtmann 263cd82e61cSMarcel Holtmann switch (bt_cb(skb)->pkt_type) { 264cd82e61cSMarcel Holtmann case HCI_COMMAND_PKT: 265dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); 266cd82e61cSMarcel Holtmann break; 267cd82e61cSMarcel Holtmann case HCI_EVENT_PKT: 268dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_EVENT_PKT); 269cd82e61cSMarcel Holtmann break; 270cd82e61cSMarcel Holtmann case HCI_ACLDATA_PKT: 271cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 272dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); 273cd82e61cSMarcel Holtmann else 274dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); 275cd82e61cSMarcel Holtmann break; 276cd82e61cSMarcel Holtmann case HCI_SCODATA_PKT: 277cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 278dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); 279cd82e61cSMarcel Holtmann else 280dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); 281cd82e61cSMarcel Holtmann break; 282cd82e61cSMarcel Holtmann default: 283cd82e61cSMarcel Holtmann return; 284cd82e61cSMarcel Holtmann } 285cd82e61cSMarcel Holtmann 2862b531294SMarcel Holtmann /* Create a private copy with headroom */ 2872b531294SMarcel Holtmann skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true); 2882b531294SMarcel Holtmann if (!skb_copy) 2892b531294SMarcel Holtmann return; 2902b531294SMarcel Holtmann 2912b531294SMarcel Holtmann /* Put header before the data */ 2922b531294SMarcel Holtmann hdr = (void *) skb_push(skb_copy, HCI_MON_HDR_SIZE); 2932b531294SMarcel Holtmann hdr->opcode = opcode; 2942b531294SMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 2952b531294SMarcel Holtmann hdr->len = cpu_to_le16(skb->len); 2962b531294SMarcel Holtmann 297c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, 298c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 299cd82e61cSMarcel Holtmann kfree_skb(skb_copy); 300cd82e61cSMarcel Holtmann } 301cd82e61cSMarcel Holtmann 302cd82e61cSMarcel Holtmann static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) 303cd82e61cSMarcel Holtmann { 304cd82e61cSMarcel Holtmann struct hci_mon_hdr *hdr; 305cd82e61cSMarcel Holtmann struct hci_mon_new_index *ni; 306*6c566dd5SMarcel Holtmann struct hci_mon_index_info *ii; 307cd82e61cSMarcel Holtmann struct sk_buff *skb; 308cd82e61cSMarcel Holtmann __le16 opcode; 309cd82e61cSMarcel Holtmann 310cd82e61cSMarcel Holtmann switch (event) { 311cd82e61cSMarcel Holtmann case HCI_DEV_REG: 312cd82e61cSMarcel Holtmann skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC); 313cd82e61cSMarcel Holtmann if (!skb) 314cd82e61cSMarcel Holtmann return NULL; 315cd82e61cSMarcel Holtmann 316cd82e61cSMarcel Holtmann ni = (void *)skb_put(skb, HCI_MON_NEW_INDEX_SIZE); 317cd82e61cSMarcel Holtmann ni->type = hdev->dev_type; 318cd82e61cSMarcel Holtmann ni->bus = hdev->bus; 319cd82e61cSMarcel Holtmann bacpy(&ni->bdaddr, &hdev->bdaddr); 320cd82e61cSMarcel Holtmann memcpy(ni->name, hdev->name, 8); 321cd82e61cSMarcel Holtmann 322dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_NEW_INDEX); 323cd82e61cSMarcel Holtmann break; 324cd82e61cSMarcel Holtmann 325cd82e61cSMarcel Holtmann case HCI_DEV_UNREG: 326cd82e61cSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 327cd82e61cSMarcel Holtmann if (!skb) 328cd82e61cSMarcel Holtmann return NULL; 329cd82e61cSMarcel Holtmann 330dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_DEL_INDEX); 331cd82e61cSMarcel Holtmann break; 332cd82e61cSMarcel Holtmann 333*6c566dd5SMarcel Holtmann case HCI_DEV_UP: 334*6c566dd5SMarcel Holtmann skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC); 335*6c566dd5SMarcel Holtmann if (!skb) 336*6c566dd5SMarcel Holtmann return NULL; 337*6c566dd5SMarcel Holtmann 338*6c566dd5SMarcel Holtmann ii = (void *)skb_put(skb, HCI_MON_INDEX_INFO_SIZE); 339*6c566dd5SMarcel Holtmann bacpy(&ii->bdaddr, &hdev->bdaddr); 340*6c566dd5SMarcel Holtmann ii->manufacturer = cpu_to_le16(hdev->manufacturer); 341*6c566dd5SMarcel Holtmann 342*6c566dd5SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_INDEX_INFO); 343*6c566dd5SMarcel Holtmann break; 344*6c566dd5SMarcel Holtmann 34522db3cbcSMarcel Holtmann case HCI_DEV_OPEN: 34622db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 34722db3cbcSMarcel Holtmann if (!skb) 34822db3cbcSMarcel Holtmann return NULL; 34922db3cbcSMarcel Holtmann 35022db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_OPEN_INDEX); 35122db3cbcSMarcel Holtmann break; 35222db3cbcSMarcel Holtmann 35322db3cbcSMarcel Holtmann case HCI_DEV_CLOSE: 35422db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 35522db3cbcSMarcel Holtmann if (!skb) 35622db3cbcSMarcel Holtmann return NULL; 35722db3cbcSMarcel Holtmann 35822db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX); 35922db3cbcSMarcel Holtmann break; 36022db3cbcSMarcel Holtmann 361cd82e61cSMarcel Holtmann default: 362cd82e61cSMarcel Holtmann return NULL; 363cd82e61cSMarcel Holtmann } 364cd82e61cSMarcel Holtmann 365cd82e61cSMarcel Holtmann __net_timestamp(skb); 366cd82e61cSMarcel Holtmann 367cd82e61cSMarcel Holtmann hdr = (void *) skb_push(skb, HCI_MON_HDR_SIZE); 368cd82e61cSMarcel Holtmann hdr->opcode = opcode; 369cd82e61cSMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 370cd82e61cSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 371cd82e61cSMarcel Holtmann 372cd82e61cSMarcel Holtmann return skb; 373cd82e61cSMarcel Holtmann } 374cd82e61cSMarcel Holtmann 375cd82e61cSMarcel Holtmann static void send_monitor_replay(struct sock *sk) 376cd82e61cSMarcel Holtmann { 377cd82e61cSMarcel Holtmann struct hci_dev *hdev; 378cd82e61cSMarcel Holtmann 379cd82e61cSMarcel Holtmann read_lock(&hci_dev_list_lock); 380cd82e61cSMarcel Holtmann 381cd82e61cSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 382cd82e61cSMarcel Holtmann struct sk_buff *skb; 383cd82e61cSMarcel Holtmann 384cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_REG); 385cd82e61cSMarcel Holtmann if (!skb) 386cd82e61cSMarcel Holtmann continue; 387cd82e61cSMarcel Holtmann 388cd82e61cSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 389cd82e61cSMarcel Holtmann kfree_skb(skb); 39022db3cbcSMarcel Holtmann 39122db3cbcSMarcel Holtmann if (!test_bit(HCI_RUNNING, &hdev->flags)) 39222db3cbcSMarcel Holtmann continue; 39322db3cbcSMarcel Holtmann 39422db3cbcSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_OPEN); 39522db3cbcSMarcel Holtmann if (!skb) 39622db3cbcSMarcel Holtmann continue; 39722db3cbcSMarcel Holtmann 39822db3cbcSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 39922db3cbcSMarcel Holtmann kfree_skb(skb); 400*6c566dd5SMarcel Holtmann 401*6c566dd5SMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) 402*6c566dd5SMarcel Holtmann continue; 403*6c566dd5SMarcel Holtmann 404*6c566dd5SMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_UP); 405*6c566dd5SMarcel Holtmann if (!skb) 406*6c566dd5SMarcel Holtmann continue; 407*6c566dd5SMarcel Holtmann 408*6c566dd5SMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 409*6c566dd5SMarcel Holtmann kfree_skb(skb); 410cd82e61cSMarcel Holtmann } 411cd82e61cSMarcel Holtmann 412cd82e61cSMarcel Holtmann read_unlock(&hci_dev_list_lock); 413cd82e61cSMarcel Holtmann } 414cd82e61cSMarcel Holtmann 415040030efSMarcel Holtmann /* Generate internal stack event */ 416040030efSMarcel Holtmann static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 417040030efSMarcel Holtmann { 418040030efSMarcel Holtmann struct hci_event_hdr *hdr; 419040030efSMarcel Holtmann struct hci_ev_stack_internal *ev; 420040030efSMarcel Holtmann struct sk_buff *skb; 421040030efSMarcel Holtmann 422040030efSMarcel Holtmann skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 423040030efSMarcel Holtmann if (!skb) 424040030efSMarcel Holtmann return; 425040030efSMarcel Holtmann 426040030efSMarcel Holtmann hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 427040030efSMarcel Holtmann hdr->evt = HCI_EV_STACK_INTERNAL; 428040030efSMarcel Holtmann hdr->plen = sizeof(*ev) + dlen; 429040030efSMarcel Holtmann 430040030efSMarcel Holtmann ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 431040030efSMarcel Holtmann ev->type = type; 432040030efSMarcel Holtmann memcpy(ev->data, data, dlen); 433040030efSMarcel Holtmann 434040030efSMarcel Holtmann bt_cb(skb)->incoming = 1; 435040030efSMarcel Holtmann __net_timestamp(skb); 436040030efSMarcel Holtmann 437040030efSMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 438040030efSMarcel Holtmann hci_send_to_sock(hdev, skb); 439040030efSMarcel Holtmann kfree_skb(skb); 440040030efSMarcel Holtmann } 441040030efSMarcel Holtmann 442040030efSMarcel Holtmann void hci_sock_dev_event(struct hci_dev *hdev, int event) 443040030efSMarcel Holtmann { 444040030efSMarcel Holtmann BT_DBG("hdev %s event %d", hdev->name, event); 445040030efSMarcel Holtmann 446cd82e61cSMarcel Holtmann if (atomic_read(&monitor_promisc)) { 447cd82e61cSMarcel Holtmann struct sk_buff *skb; 448cd82e61cSMarcel Holtmann 449ed1b28a4SMarcel Holtmann /* Send event to monitor */ 450cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, event); 451cd82e61cSMarcel Holtmann if (skb) { 452c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, 453c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 454cd82e61cSMarcel Holtmann kfree_skb(skb); 455cd82e61cSMarcel Holtmann } 456cd82e61cSMarcel Holtmann } 457cd82e61cSMarcel Holtmann 458ed1b28a4SMarcel Holtmann if (event <= HCI_DEV_DOWN) { 459ed1b28a4SMarcel Holtmann struct hci_ev_si_device ev; 460ed1b28a4SMarcel Holtmann 461040030efSMarcel Holtmann /* Send event to sockets */ 462040030efSMarcel Holtmann ev.event = event; 463040030efSMarcel Holtmann ev.dev_id = hdev->id; 464040030efSMarcel Holtmann hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); 465ed1b28a4SMarcel Holtmann } 466040030efSMarcel Holtmann 467040030efSMarcel Holtmann if (event == HCI_DEV_UNREG) { 468040030efSMarcel Holtmann struct sock *sk; 469040030efSMarcel Holtmann 470040030efSMarcel Holtmann /* Detach sockets from device */ 471040030efSMarcel Holtmann read_lock(&hci_sk_list.lock); 472b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 473040030efSMarcel Holtmann bh_lock_sock_nested(sk); 474040030efSMarcel Holtmann if (hci_pi(sk)->hdev == hdev) { 475040030efSMarcel Holtmann hci_pi(sk)->hdev = NULL; 476040030efSMarcel Holtmann sk->sk_err = EPIPE; 477040030efSMarcel Holtmann sk->sk_state = BT_OPEN; 478040030efSMarcel Holtmann sk->sk_state_change(sk); 479040030efSMarcel Holtmann 480040030efSMarcel Holtmann hci_dev_put(hdev); 481040030efSMarcel Holtmann } 482040030efSMarcel Holtmann bh_unlock_sock(sk); 483040030efSMarcel Holtmann } 484040030efSMarcel Holtmann read_unlock(&hci_sk_list.lock); 485040030efSMarcel Holtmann } 486040030efSMarcel Holtmann } 487040030efSMarcel Holtmann 488801c1e8dSJohan Hedberg static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel) 489801c1e8dSJohan Hedberg { 490801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 491801c1e8dSJohan Hedberg 492801c1e8dSJohan Hedberg list_for_each_entry(c, &mgmt_chan_list, list) { 493801c1e8dSJohan Hedberg if (c->channel == channel) 494801c1e8dSJohan Hedberg return c; 495801c1e8dSJohan Hedberg } 496801c1e8dSJohan Hedberg 497801c1e8dSJohan Hedberg return NULL; 498801c1e8dSJohan Hedberg } 499801c1e8dSJohan Hedberg 500801c1e8dSJohan Hedberg static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel) 501801c1e8dSJohan Hedberg { 502801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 503801c1e8dSJohan Hedberg 504801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 505801c1e8dSJohan Hedberg c = __hci_mgmt_chan_find(channel); 506801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 507801c1e8dSJohan Hedberg 508801c1e8dSJohan Hedberg return c; 509801c1e8dSJohan Hedberg } 510801c1e8dSJohan Hedberg 511801c1e8dSJohan Hedberg int hci_mgmt_chan_register(struct hci_mgmt_chan *c) 512801c1e8dSJohan Hedberg { 513801c1e8dSJohan Hedberg if (c->channel < HCI_CHANNEL_CONTROL) 514801c1e8dSJohan Hedberg return -EINVAL; 515801c1e8dSJohan Hedberg 516801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 517801c1e8dSJohan Hedberg if (__hci_mgmt_chan_find(c->channel)) { 518801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 519801c1e8dSJohan Hedberg return -EALREADY; 520801c1e8dSJohan Hedberg } 521801c1e8dSJohan Hedberg 522801c1e8dSJohan Hedberg list_add_tail(&c->list, &mgmt_chan_list); 523801c1e8dSJohan Hedberg 524801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 525801c1e8dSJohan Hedberg 526801c1e8dSJohan Hedberg return 0; 527801c1e8dSJohan Hedberg } 528801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_register); 529801c1e8dSJohan Hedberg 530801c1e8dSJohan Hedberg void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c) 531801c1e8dSJohan Hedberg { 532801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 533801c1e8dSJohan Hedberg list_del(&c->list); 534801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 535801c1e8dSJohan Hedberg } 536801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_unregister); 537801c1e8dSJohan Hedberg 5381da177e4SLinus Torvalds static int hci_sock_release(struct socket *sock) 5391da177e4SLinus Torvalds { 5401da177e4SLinus Torvalds struct sock *sk = sock->sk; 5417b005bd3SMarcel Holtmann struct hci_dev *hdev; 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds if (!sk) 5461da177e4SLinus Torvalds return 0; 5471da177e4SLinus Torvalds 5487b005bd3SMarcel Holtmann hdev = hci_pi(sk)->hdev; 5497b005bd3SMarcel Holtmann 550cd82e61cSMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_MONITOR) 551cd82e61cSMarcel Holtmann atomic_dec(&monitor_promisc); 552cd82e61cSMarcel Holtmann 5531da177e4SLinus Torvalds bt_sock_unlink(&hci_sk_list, sk); 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds if (hdev) { 55623500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 5576b3cc1dbSSimon Fels /* When releasing an user channel exclusive access, 5586b3cc1dbSSimon Fels * call hci_dev_do_close directly instead of calling 5596b3cc1dbSSimon Fels * hci_dev_close to ensure the exclusive access will 5606b3cc1dbSSimon Fels * be released and the controller brought back down. 5616b3cc1dbSSimon Fels * 5626b3cc1dbSSimon Fels * The checking of HCI_AUTO_OFF is not needed in this 5636b3cc1dbSSimon Fels * case since it will have been cleared already when 5646b3cc1dbSSimon Fels * opening the user channel. 5656b3cc1dbSSimon Fels */ 5666b3cc1dbSSimon Fels hci_dev_do_close(hdev); 5679380f9eaSLoic Poulain hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 5689380f9eaSLoic Poulain mgmt_index_added(hdev); 56923500189SMarcel Holtmann } 57023500189SMarcel Holtmann 5711da177e4SLinus Torvalds atomic_dec(&hdev->promisc); 5721da177e4SLinus Torvalds hci_dev_put(hdev); 5731da177e4SLinus Torvalds } 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds sock_orphan(sk); 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds skb_queue_purge(&sk->sk_receive_queue); 5781da177e4SLinus Torvalds skb_queue_purge(&sk->sk_write_queue); 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds sock_put(sk); 5811da177e4SLinus Torvalds return 0; 5821da177e4SLinus Torvalds } 5831da177e4SLinus Torvalds 584b2a66aadSAntti Julku static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) 585f0358568SJohan Hedberg { 586f0358568SJohan Hedberg bdaddr_t bdaddr; 5875e762444SAntti Julku int err; 588f0358568SJohan Hedberg 589f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 590f0358568SJohan Hedberg return -EFAULT; 591f0358568SJohan Hedberg 59209fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 5935e762444SAntti Julku 594dcc36c16SJohan Hedberg err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 5955e762444SAntti Julku 59609fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 5975e762444SAntti Julku 5985e762444SAntti Julku return err; 599f0358568SJohan Hedberg } 600f0358568SJohan Hedberg 601b2a66aadSAntti Julku static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) 602f0358568SJohan Hedberg { 603f0358568SJohan Hedberg bdaddr_t bdaddr; 6045e762444SAntti Julku int err; 605f0358568SJohan Hedberg 606f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 607f0358568SJohan Hedberg return -EFAULT; 608f0358568SJohan Hedberg 60909fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6105e762444SAntti Julku 611dcc36c16SJohan Hedberg err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6125e762444SAntti Julku 61309fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6145e762444SAntti Julku 6155e762444SAntti Julku return err; 616f0358568SJohan Hedberg } 617f0358568SJohan Hedberg 6181da177e4SLinus Torvalds /* Ioctls that require bound socket */ 6196039aa73SGustavo Padovan static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, 6206039aa73SGustavo Padovan unsigned long arg) 6211da177e4SLinus Torvalds { 6221da177e4SLinus Torvalds struct hci_dev *hdev = hci_pi(sk)->hdev; 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds if (!hdev) 6251da177e4SLinus Torvalds return -EBADFD; 6261da177e4SLinus Torvalds 627d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) 6280736cfa8SMarcel Holtmann return -EBUSY; 6290736cfa8SMarcel Holtmann 630d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 631fee746b0SMarcel Holtmann return -EOPNOTSUPP; 632fee746b0SMarcel Holtmann 6335b69bef5SMarcel Holtmann if (hdev->dev_type != HCI_BREDR) 6345b69bef5SMarcel Holtmann return -EOPNOTSUPP; 6355b69bef5SMarcel Holtmann 6361da177e4SLinus Torvalds switch (cmd) { 6371da177e4SLinus Torvalds case HCISETRAW: 6381da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 639bf5b30b8SZhao Hongjiang return -EPERM; 640db596681SMarcel Holtmann return -EOPNOTSUPP; 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds case HCIGETCONNINFO: 6431da177e4SLinus Torvalds return hci_get_conn_info(hdev, (void __user *) arg); 6441da177e4SLinus Torvalds 64540be492fSMarcel Holtmann case HCIGETAUTHINFO: 64640be492fSMarcel Holtmann return hci_get_auth_info(hdev, (void __user *) arg); 64740be492fSMarcel Holtmann 648f0358568SJohan Hedberg case HCIBLOCKADDR: 649f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 650bf5b30b8SZhao Hongjiang return -EPERM; 651b2a66aadSAntti Julku return hci_sock_blacklist_add(hdev, (void __user *) arg); 652f0358568SJohan Hedberg 653f0358568SJohan Hedberg case HCIUNBLOCKADDR: 654f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 655bf5b30b8SZhao Hongjiang return -EPERM; 656b2a66aadSAntti Julku return hci_sock_blacklist_del(hdev, (void __user *) arg); 6570736cfa8SMarcel Holtmann } 658f0358568SJohan Hedberg 659324d36edSMarcel Holtmann return -ENOIOCTLCMD; 6601da177e4SLinus Torvalds } 6611da177e4SLinus Torvalds 6628fc9ced3SGustavo Padovan static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, 6638fc9ced3SGustavo Padovan unsigned long arg) 6641da177e4SLinus Torvalds { 6651da177e4SLinus Torvalds void __user *argp = (void __user *) arg; 6660736cfa8SMarcel Holtmann struct sock *sk = sock->sk; 6671da177e4SLinus Torvalds int err; 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds BT_DBG("cmd %x arg %lx", cmd, arg); 6701da177e4SLinus Torvalds 671c1c4f956SMarcel Holtmann lock_sock(sk); 672c1c4f956SMarcel Holtmann 673c1c4f956SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 674c1c4f956SMarcel Holtmann err = -EBADFD; 675c1c4f956SMarcel Holtmann goto done; 676c1c4f956SMarcel Holtmann } 677c1c4f956SMarcel Holtmann 678c1c4f956SMarcel Holtmann release_sock(sk); 679c1c4f956SMarcel Holtmann 6801da177e4SLinus Torvalds switch (cmd) { 6811da177e4SLinus Torvalds case HCIGETDEVLIST: 6821da177e4SLinus Torvalds return hci_get_dev_list(argp); 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds case HCIGETDEVINFO: 6851da177e4SLinus Torvalds return hci_get_dev_info(argp); 6861da177e4SLinus Torvalds 6871da177e4SLinus Torvalds case HCIGETCONNLIST: 6881da177e4SLinus Torvalds return hci_get_conn_list(argp); 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds case HCIDEVUP: 6911da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 692bf5b30b8SZhao Hongjiang return -EPERM; 6931da177e4SLinus Torvalds return hci_dev_open(arg); 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds case HCIDEVDOWN: 6961da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 697bf5b30b8SZhao Hongjiang return -EPERM; 6981da177e4SLinus Torvalds return hci_dev_close(arg); 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds case HCIDEVRESET: 7011da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 702bf5b30b8SZhao Hongjiang return -EPERM; 7031da177e4SLinus Torvalds return hci_dev_reset(arg); 7041da177e4SLinus Torvalds 7051da177e4SLinus Torvalds case HCIDEVRESTAT: 7061da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 707bf5b30b8SZhao Hongjiang return -EPERM; 7081da177e4SLinus Torvalds return hci_dev_reset_stat(arg); 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds case HCISETSCAN: 7111da177e4SLinus Torvalds case HCISETAUTH: 7121da177e4SLinus Torvalds case HCISETENCRYPT: 7131da177e4SLinus Torvalds case HCISETPTYPE: 7141da177e4SLinus Torvalds case HCISETLINKPOL: 7151da177e4SLinus Torvalds case HCISETLINKMODE: 7161da177e4SLinus Torvalds case HCISETACLMTU: 7171da177e4SLinus Torvalds case HCISETSCOMTU: 7181da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 719bf5b30b8SZhao Hongjiang return -EPERM; 7201da177e4SLinus Torvalds return hci_dev_cmd(cmd, argp); 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds case HCIINQUIRY: 7231da177e4SLinus Torvalds return hci_inquiry(argp); 724c1c4f956SMarcel Holtmann } 7251da177e4SLinus Torvalds 7261da177e4SLinus Torvalds lock_sock(sk); 727c1c4f956SMarcel Holtmann 7281da177e4SLinus Torvalds err = hci_sock_bound_ioctl(sk, cmd, arg); 729c1c4f956SMarcel Holtmann 730c1c4f956SMarcel Holtmann done: 7311da177e4SLinus Torvalds release_sock(sk); 7321da177e4SLinus Torvalds return err; 7331da177e4SLinus Torvalds } 7341da177e4SLinus Torvalds 7358fc9ced3SGustavo Padovan static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, 7368fc9ced3SGustavo Padovan int addr_len) 7371da177e4SLinus Torvalds { 7380381101fSJohan Hedberg struct sockaddr_hci haddr; 7391da177e4SLinus Torvalds struct sock *sk = sock->sk; 7401da177e4SLinus Torvalds struct hci_dev *hdev = NULL; 7410381101fSJohan Hedberg int len, err = 0; 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 7441da177e4SLinus Torvalds 7450381101fSJohan Hedberg if (!addr) 7460381101fSJohan Hedberg return -EINVAL; 7470381101fSJohan Hedberg 7480381101fSJohan Hedberg memset(&haddr, 0, sizeof(haddr)); 7490381101fSJohan Hedberg len = min_t(unsigned int, sizeof(haddr), addr_len); 7500381101fSJohan Hedberg memcpy(&haddr, addr, len); 7510381101fSJohan Hedberg 7520381101fSJohan Hedberg if (haddr.hci_family != AF_BLUETOOTH) 7530381101fSJohan Hedberg return -EINVAL; 7540381101fSJohan Hedberg 7551da177e4SLinus Torvalds lock_sock(sk); 7561da177e4SLinus Torvalds 7577cc2ade2SMarcel Holtmann if (sk->sk_state == BT_BOUND) { 7587cc2ade2SMarcel Holtmann err = -EALREADY; 7597cc2ade2SMarcel Holtmann goto done; 7607cc2ade2SMarcel Holtmann } 7617cc2ade2SMarcel Holtmann 7627cc2ade2SMarcel Holtmann switch (haddr.hci_channel) { 7637cc2ade2SMarcel Holtmann case HCI_CHANNEL_RAW: 7647cc2ade2SMarcel Holtmann if (hci_pi(sk)->hdev) { 7651da177e4SLinus Torvalds err = -EALREADY; 7661da177e4SLinus Torvalds goto done; 7671da177e4SLinus Torvalds } 7681da177e4SLinus Torvalds 7690381101fSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 7700381101fSJohan Hedberg hdev = hci_dev_get(haddr.hci_dev); 77170f23020SAndrei Emeltchenko if (!hdev) { 7721da177e4SLinus Torvalds err = -ENODEV; 7731da177e4SLinus Torvalds goto done; 7741da177e4SLinus Torvalds } 7751da177e4SLinus Torvalds 7761da177e4SLinus Torvalds atomic_inc(&hdev->promisc); 7771da177e4SLinus Torvalds } 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds hci_pi(sk)->hdev = hdev; 7807cc2ade2SMarcel Holtmann break; 7817cc2ade2SMarcel Holtmann 78223500189SMarcel Holtmann case HCI_CHANNEL_USER: 78323500189SMarcel Holtmann if (hci_pi(sk)->hdev) { 78423500189SMarcel Holtmann err = -EALREADY; 78523500189SMarcel Holtmann goto done; 78623500189SMarcel Holtmann } 78723500189SMarcel Holtmann 78823500189SMarcel Holtmann if (haddr.hci_dev == HCI_DEV_NONE) { 78923500189SMarcel Holtmann err = -EINVAL; 79023500189SMarcel Holtmann goto done; 79123500189SMarcel Holtmann } 79223500189SMarcel Holtmann 79310a8b86fSMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 79423500189SMarcel Holtmann err = -EPERM; 79523500189SMarcel Holtmann goto done; 79623500189SMarcel Holtmann } 79723500189SMarcel Holtmann 79823500189SMarcel Holtmann hdev = hci_dev_get(haddr.hci_dev); 79923500189SMarcel Holtmann if (!hdev) { 80023500189SMarcel Holtmann err = -ENODEV; 80123500189SMarcel Holtmann goto done; 80223500189SMarcel Holtmann } 80323500189SMarcel Holtmann 804781f899fSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags) || 805d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_SETUP) || 806781f899fSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG) || 807781f899fSMarcel Holtmann (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) && 808781f899fSMarcel Holtmann test_bit(HCI_UP, &hdev->flags))) { 80923500189SMarcel Holtmann err = -EBUSY; 81023500189SMarcel Holtmann hci_dev_put(hdev); 81123500189SMarcel Holtmann goto done; 81223500189SMarcel Holtmann } 81323500189SMarcel Holtmann 814238be788SMarcel Holtmann if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) { 81523500189SMarcel Holtmann err = -EUSERS; 81623500189SMarcel Holtmann hci_dev_put(hdev); 81723500189SMarcel Holtmann goto done; 81823500189SMarcel Holtmann } 81923500189SMarcel Holtmann 82023500189SMarcel Holtmann mgmt_index_removed(hdev); 82123500189SMarcel Holtmann 82223500189SMarcel Holtmann err = hci_dev_open(hdev->id); 82323500189SMarcel Holtmann if (err) { 824781f899fSMarcel Holtmann if (err == -EALREADY) { 825781f899fSMarcel Holtmann /* In case the transport is already up and 826781f899fSMarcel Holtmann * running, clear the error here. 827781f899fSMarcel Holtmann * 828781f899fSMarcel Holtmann * This can happen when opening an user 829781f899fSMarcel Holtmann * channel and HCI_AUTO_OFF grace period 830781f899fSMarcel Holtmann * is still active. 831781f899fSMarcel Holtmann */ 832781f899fSMarcel Holtmann err = 0; 833781f899fSMarcel Holtmann } else { 834a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 835c6521401SMarcel Holtmann mgmt_index_added(hdev); 83623500189SMarcel Holtmann hci_dev_put(hdev); 83723500189SMarcel Holtmann goto done; 83823500189SMarcel Holtmann } 839781f899fSMarcel Holtmann } 84023500189SMarcel Holtmann 84123500189SMarcel Holtmann atomic_inc(&hdev->promisc); 84223500189SMarcel Holtmann 84323500189SMarcel Holtmann hci_pi(sk)->hdev = hdev; 84423500189SMarcel Holtmann break; 84523500189SMarcel Holtmann 846cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 847cd82e61cSMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 848cd82e61cSMarcel Holtmann err = -EINVAL; 849cd82e61cSMarcel Holtmann goto done; 850cd82e61cSMarcel Holtmann } 851cd82e61cSMarcel Holtmann 852cd82e61cSMarcel Holtmann if (!capable(CAP_NET_RAW)) { 853cd82e61cSMarcel Holtmann err = -EPERM; 854cd82e61cSMarcel Holtmann goto done; 855cd82e61cSMarcel Holtmann } 856cd82e61cSMarcel Holtmann 85750ebc055SMarcel Holtmann /* The monitor interface is restricted to CAP_NET_RAW 85850ebc055SMarcel Holtmann * capabilities and with that implicitly trusted. 85950ebc055SMarcel Holtmann */ 86050ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 86150ebc055SMarcel Holtmann 862cd82e61cSMarcel Holtmann send_monitor_replay(sk); 863cd82e61cSMarcel Holtmann 864cd82e61cSMarcel Holtmann atomic_inc(&monitor_promisc); 865cd82e61cSMarcel Holtmann break; 866cd82e61cSMarcel Holtmann 8677cc2ade2SMarcel Holtmann default: 868801c1e8dSJohan Hedberg if (!hci_mgmt_chan_find(haddr.hci_channel)) { 8697cc2ade2SMarcel Holtmann err = -EINVAL; 8707cc2ade2SMarcel Holtmann goto done; 8717cc2ade2SMarcel Holtmann } 8727cc2ade2SMarcel Holtmann 873801c1e8dSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 874801c1e8dSJohan Hedberg err = -EINVAL; 875801c1e8dSJohan Hedberg goto done; 876801c1e8dSJohan Hedberg } 877801c1e8dSJohan Hedberg 8781195fbb8SMarcel Holtmann /* Users with CAP_NET_ADMIN capabilities are allowed 8791195fbb8SMarcel Holtmann * access to all management commands and events. For 8801195fbb8SMarcel Holtmann * untrusted users the interface is restricted and 8811195fbb8SMarcel Holtmann * also only untrusted events are sent. 88250ebc055SMarcel Holtmann */ 8831195fbb8SMarcel Holtmann if (capable(CAP_NET_ADMIN)) 88450ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 88550ebc055SMarcel Holtmann 886f9207338SMarcel Holtmann /* At the moment the index and unconfigured index events 887f9207338SMarcel Holtmann * are enabled unconditionally. Setting them on each 888f9207338SMarcel Holtmann * socket when binding keeps this functionality. They 889f9207338SMarcel Holtmann * however might be cleared later and then sending of these 890f9207338SMarcel Holtmann * events will be disabled, but that is then intentional. 891f6b7712eSMarcel Holtmann * 892f6b7712eSMarcel Holtmann * This also enables generic events that are safe to be 893f6b7712eSMarcel Holtmann * received by untrusted users. Example for such events 894f6b7712eSMarcel Holtmann * are changes to settings, class of device, name etc. 895f9207338SMarcel Holtmann */ 896f9207338SMarcel Holtmann if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { 897f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); 898f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); 899f6b7712eSMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS); 900f9207338SMarcel Holtmann } 901801c1e8dSJohan Hedberg break; 902801c1e8dSJohan Hedberg } 903801c1e8dSJohan Hedberg 9047cc2ade2SMarcel Holtmann 9057cc2ade2SMarcel Holtmann hci_pi(sk)->channel = haddr.hci_channel; 9061da177e4SLinus Torvalds sk->sk_state = BT_BOUND; 9071da177e4SLinus Torvalds 9081da177e4SLinus Torvalds done: 9091da177e4SLinus Torvalds release_sock(sk); 9101da177e4SLinus Torvalds return err; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds 9138fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, 9148fc9ced3SGustavo Padovan int *addr_len, int peer) 9151da177e4SLinus Torvalds { 9161da177e4SLinus Torvalds struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 9171da177e4SLinus Torvalds struct sock *sk = sock->sk; 9189d4b68b2SMarcel Holtmann struct hci_dev *hdev; 9199d4b68b2SMarcel Holtmann int err = 0; 9201da177e4SLinus Torvalds 9211da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 9221da177e4SLinus Torvalds 92306f43cbcSMarcel Holtmann if (peer) 92406f43cbcSMarcel Holtmann return -EOPNOTSUPP; 92506f43cbcSMarcel Holtmann 9261da177e4SLinus Torvalds lock_sock(sk); 9271da177e4SLinus Torvalds 9289d4b68b2SMarcel Holtmann hdev = hci_pi(sk)->hdev; 9299d4b68b2SMarcel Holtmann if (!hdev) { 9309d4b68b2SMarcel Holtmann err = -EBADFD; 9319d4b68b2SMarcel Holtmann goto done; 9329d4b68b2SMarcel Holtmann } 9339d4b68b2SMarcel Holtmann 9341da177e4SLinus Torvalds *addr_len = sizeof(*haddr); 9351da177e4SLinus Torvalds haddr->hci_family = AF_BLUETOOTH; 9367b005bd3SMarcel Holtmann haddr->hci_dev = hdev->id; 9379d4b68b2SMarcel Holtmann haddr->hci_channel= hci_pi(sk)->channel; 9381da177e4SLinus Torvalds 9399d4b68b2SMarcel Holtmann done: 9401da177e4SLinus Torvalds release_sock(sk); 9419d4b68b2SMarcel Holtmann return err; 9421da177e4SLinus Torvalds } 9431da177e4SLinus Torvalds 9446039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, 9456039aa73SGustavo Padovan struct sk_buff *skb) 9461da177e4SLinus Torvalds { 9471da177e4SLinus Torvalds __u32 mask = hci_pi(sk)->cmsg_mask; 9481da177e4SLinus Torvalds 9490d48d939SMarcel Holtmann if (mask & HCI_CMSG_DIR) { 9500d48d939SMarcel Holtmann int incoming = bt_cb(skb)->incoming; 9518fc9ced3SGustavo Padovan put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), 9528fc9ced3SGustavo Padovan &incoming); 9530d48d939SMarcel Holtmann } 9541da177e4SLinus Torvalds 955a61bbcf2SPatrick McHardy if (mask & HCI_CMSG_TSTAMP) { 956f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT 957f6e623a6SJohann Felix Soden struct compat_timeval ctv; 958f6e623a6SJohann Felix Soden #endif 959a61bbcf2SPatrick McHardy struct timeval tv; 960767c5eb5SMarcel Holtmann void *data; 961767c5eb5SMarcel Holtmann int len; 962a61bbcf2SPatrick McHardy 963a61bbcf2SPatrick McHardy skb_get_timestamp(skb, &tv); 964767c5eb5SMarcel Holtmann 9651da97f83SDavid S. Miller data = &tv; 9661da97f83SDavid S. Miller len = sizeof(tv); 9671da97f83SDavid S. Miller #ifdef CONFIG_COMPAT 968da88cea1SH. J. Lu if (!COMPAT_USE_64BIT_TIME && 969da88cea1SH. J. Lu (msg->msg_flags & MSG_CMSG_COMPAT)) { 970767c5eb5SMarcel Holtmann ctv.tv_sec = tv.tv_sec; 971767c5eb5SMarcel Holtmann ctv.tv_usec = tv.tv_usec; 972767c5eb5SMarcel Holtmann data = &ctv; 973767c5eb5SMarcel Holtmann len = sizeof(ctv); 974767c5eb5SMarcel Holtmann } 9751da97f83SDavid S. Miller #endif 976767c5eb5SMarcel Holtmann 977767c5eb5SMarcel Holtmann put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 978a61bbcf2SPatrick McHardy } 9791da177e4SLinus Torvalds } 9801da177e4SLinus Torvalds 9811b784140SYing Xue static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 9821b784140SYing Xue int flags) 9831da177e4SLinus Torvalds { 9841da177e4SLinus Torvalds int noblock = flags & MSG_DONTWAIT; 9851da177e4SLinus Torvalds struct sock *sk = sock->sk; 9861da177e4SLinus Torvalds struct sk_buff *skb; 9871da177e4SLinus Torvalds int copied, err; 9881da177e4SLinus Torvalds 9891da177e4SLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds if (flags & (MSG_OOB)) 9921da177e4SLinus Torvalds return -EOPNOTSUPP; 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds if (sk->sk_state == BT_CLOSED) 9951da177e4SLinus Torvalds return 0; 9961da177e4SLinus Torvalds 99770f23020SAndrei Emeltchenko skb = skb_recv_datagram(sk, flags, noblock, &err); 99870f23020SAndrei Emeltchenko if (!skb) 9991da177e4SLinus Torvalds return err; 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds copied = skb->len; 10021da177e4SLinus Torvalds if (len < copied) { 10031da177e4SLinus Torvalds msg->msg_flags |= MSG_TRUNC; 10041da177e4SLinus Torvalds copied = len; 10051da177e4SLinus Torvalds } 10061da177e4SLinus Torvalds 1007badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb); 100851f3d02bSDavid S. Miller err = skb_copy_datagram_msg(skb, 0, msg, copied); 10091da177e4SLinus Torvalds 10103a208627SMarcel Holtmann switch (hci_pi(sk)->channel) { 10113a208627SMarcel Holtmann case HCI_CHANNEL_RAW: 10121da177e4SLinus Torvalds hci_sock_cmsg(sk, msg, skb); 10133a208627SMarcel Holtmann break; 101423500189SMarcel Holtmann case HCI_CHANNEL_USER: 1015cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1016cd82e61cSMarcel Holtmann sock_recv_timestamp(msg, sk, skb); 1017cd82e61cSMarcel Holtmann break; 1018801c1e8dSJohan Hedberg default: 1019801c1e8dSJohan Hedberg if (hci_mgmt_chan_find(hci_pi(sk)->channel)) 1020801c1e8dSJohan Hedberg sock_recv_timestamp(msg, sk, skb); 1021801c1e8dSJohan Hedberg break; 10223a208627SMarcel Holtmann } 10231da177e4SLinus Torvalds 10241da177e4SLinus Torvalds skb_free_datagram(sk, skb); 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds return err ? : copied; 10271da177e4SLinus Torvalds } 10281da177e4SLinus Torvalds 1029fa4335d7SJohan Hedberg static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, 1030fa4335d7SJohan Hedberg struct msghdr *msg, size_t msglen) 1031fa4335d7SJohan Hedberg { 1032fa4335d7SJohan Hedberg void *buf; 1033fa4335d7SJohan Hedberg u8 *cp; 1034fa4335d7SJohan Hedberg struct mgmt_hdr *hdr; 1035fa4335d7SJohan Hedberg u16 opcode, index, len; 1036fa4335d7SJohan Hedberg struct hci_dev *hdev = NULL; 1037fa4335d7SJohan Hedberg const struct hci_mgmt_handler *handler; 1038fa4335d7SJohan Hedberg bool var_len, no_hdev; 1039fa4335d7SJohan Hedberg int err; 1040fa4335d7SJohan Hedberg 1041fa4335d7SJohan Hedberg BT_DBG("got %zu bytes", msglen); 1042fa4335d7SJohan Hedberg 1043fa4335d7SJohan Hedberg if (msglen < sizeof(*hdr)) 1044fa4335d7SJohan Hedberg return -EINVAL; 1045fa4335d7SJohan Hedberg 1046fa4335d7SJohan Hedberg buf = kmalloc(msglen, GFP_KERNEL); 1047fa4335d7SJohan Hedberg if (!buf) 1048fa4335d7SJohan Hedberg return -ENOMEM; 1049fa4335d7SJohan Hedberg 1050fa4335d7SJohan Hedberg if (memcpy_from_msg(buf, msg, msglen)) { 1051fa4335d7SJohan Hedberg err = -EFAULT; 1052fa4335d7SJohan Hedberg goto done; 1053fa4335d7SJohan Hedberg } 1054fa4335d7SJohan Hedberg 1055fa4335d7SJohan Hedberg hdr = buf; 1056fa4335d7SJohan Hedberg opcode = __le16_to_cpu(hdr->opcode); 1057fa4335d7SJohan Hedberg index = __le16_to_cpu(hdr->index); 1058fa4335d7SJohan Hedberg len = __le16_to_cpu(hdr->len); 1059fa4335d7SJohan Hedberg 1060fa4335d7SJohan Hedberg if (len != msglen - sizeof(*hdr)) { 1061fa4335d7SJohan Hedberg err = -EINVAL; 1062fa4335d7SJohan Hedberg goto done; 1063fa4335d7SJohan Hedberg } 1064fa4335d7SJohan Hedberg 1065fa4335d7SJohan Hedberg if (opcode >= chan->handler_count || 1066fa4335d7SJohan Hedberg chan->handlers[opcode].func == NULL) { 1067fa4335d7SJohan Hedberg BT_DBG("Unknown op %u", opcode); 1068fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1069fa4335d7SJohan Hedberg MGMT_STATUS_UNKNOWN_COMMAND); 1070fa4335d7SJohan Hedberg goto done; 1071fa4335d7SJohan Hedberg } 1072fa4335d7SJohan Hedberg 1073fa4335d7SJohan Hedberg handler = &chan->handlers[opcode]; 1074fa4335d7SJohan Hedberg 1075fa4335d7SJohan Hedberg if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && 1076fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNTRUSTED)) { 1077fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1078fa4335d7SJohan Hedberg MGMT_STATUS_PERMISSION_DENIED); 1079fa4335d7SJohan Hedberg goto done; 1080fa4335d7SJohan Hedberg } 1081fa4335d7SJohan Hedberg 1082fa4335d7SJohan Hedberg if (index != MGMT_INDEX_NONE) { 1083fa4335d7SJohan Hedberg hdev = hci_dev_get(index); 1084fa4335d7SJohan Hedberg if (!hdev) { 1085fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1086fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1087fa4335d7SJohan Hedberg goto done; 1088fa4335d7SJohan Hedberg } 1089fa4335d7SJohan Hedberg 1090fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_SETUP) || 1091fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_CONFIG) || 1092fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 1093fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1094fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1095fa4335d7SJohan Hedberg goto done; 1096fa4335d7SJohan Hedberg } 1097fa4335d7SJohan Hedberg 1098fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 1099fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNCONFIGURED)) { 1100fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1101fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1102fa4335d7SJohan Hedberg goto done; 1103fa4335d7SJohan Hedberg } 1104fa4335d7SJohan Hedberg } 1105fa4335d7SJohan Hedberg 1106fa4335d7SJohan Hedberg no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); 1107fa4335d7SJohan Hedberg if (no_hdev != !hdev) { 1108fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1109fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1110fa4335d7SJohan Hedberg goto done; 1111fa4335d7SJohan Hedberg } 1112fa4335d7SJohan Hedberg 1113fa4335d7SJohan Hedberg var_len = (handler->flags & HCI_MGMT_VAR_LEN); 1114fa4335d7SJohan Hedberg if ((var_len && len < handler->data_len) || 1115fa4335d7SJohan Hedberg (!var_len && len != handler->data_len)) { 1116fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1117fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_PARAMS); 1118fa4335d7SJohan Hedberg goto done; 1119fa4335d7SJohan Hedberg } 1120fa4335d7SJohan Hedberg 1121fa4335d7SJohan Hedberg if (hdev && chan->hdev_init) 1122fa4335d7SJohan Hedberg chan->hdev_init(sk, hdev); 1123fa4335d7SJohan Hedberg 1124fa4335d7SJohan Hedberg cp = buf + sizeof(*hdr); 1125fa4335d7SJohan Hedberg 1126fa4335d7SJohan Hedberg err = handler->func(sk, hdev, cp, len); 1127fa4335d7SJohan Hedberg if (err < 0) 1128fa4335d7SJohan Hedberg goto done; 1129fa4335d7SJohan Hedberg 1130fa4335d7SJohan Hedberg err = msglen; 1131fa4335d7SJohan Hedberg 1132fa4335d7SJohan Hedberg done: 1133fa4335d7SJohan Hedberg if (hdev) 1134fa4335d7SJohan Hedberg hci_dev_put(hdev); 1135fa4335d7SJohan Hedberg 1136fa4335d7SJohan Hedberg kfree(buf); 1137fa4335d7SJohan Hedberg return err; 1138fa4335d7SJohan Hedberg } 1139fa4335d7SJohan Hedberg 11401b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, 11411b784140SYing Xue size_t len) 11421da177e4SLinus Torvalds { 11431da177e4SLinus Torvalds struct sock *sk = sock->sk; 1144801c1e8dSJohan Hedberg struct hci_mgmt_chan *chan; 11451da177e4SLinus Torvalds struct hci_dev *hdev; 11461da177e4SLinus Torvalds struct sk_buff *skb; 11471da177e4SLinus Torvalds int err; 11481da177e4SLinus Torvalds 11491da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 11501da177e4SLinus Torvalds 11511da177e4SLinus Torvalds if (msg->msg_flags & MSG_OOB) 11521da177e4SLinus Torvalds return -EOPNOTSUPP; 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 11551da177e4SLinus Torvalds return -EINVAL; 11561da177e4SLinus Torvalds 11571da177e4SLinus Torvalds if (len < 4 || len > HCI_MAX_FRAME_SIZE) 11581da177e4SLinus Torvalds return -EINVAL; 11591da177e4SLinus Torvalds 11601da177e4SLinus Torvalds lock_sock(sk); 11611da177e4SLinus Torvalds 11620381101fSJohan Hedberg switch (hci_pi(sk)->channel) { 11630381101fSJohan Hedberg case HCI_CHANNEL_RAW: 116423500189SMarcel Holtmann case HCI_CHANNEL_USER: 11650381101fSJohan Hedberg break; 1166cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1167cd82e61cSMarcel Holtmann err = -EOPNOTSUPP; 1168cd82e61cSMarcel Holtmann goto done; 11690381101fSJohan Hedberg default: 1170801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 1171801c1e8dSJohan Hedberg chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); 1172801c1e8dSJohan Hedberg if (chan) 1173fa4335d7SJohan Hedberg err = hci_mgmt_cmd(chan, sk, msg, len); 1174801c1e8dSJohan Hedberg else 11750381101fSJohan Hedberg err = -EINVAL; 1176801c1e8dSJohan Hedberg 1177801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 11780381101fSJohan Hedberg goto done; 11790381101fSJohan Hedberg } 11800381101fSJohan Hedberg 118170f23020SAndrei Emeltchenko hdev = hci_pi(sk)->hdev; 118270f23020SAndrei Emeltchenko if (!hdev) { 11831da177e4SLinus Torvalds err = -EBADFD; 11841da177e4SLinus Torvalds goto done; 11851da177e4SLinus Torvalds } 11861da177e4SLinus Torvalds 11877e21addcSMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) { 11887e21addcSMarcel Holtmann err = -ENETDOWN; 11897e21addcSMarcel Holtmann goto done; 11907e21addcSMarcel Holtmann } 11917e21addcSMarcel Holtmann 119270f23020SAndrei Emeltchenko skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 119370f23020SAndrei Emeltchenko if (!skb) 11941da177e4SLinus Torvalds goto done; 11951da177e4SLinus Torvalds 11966ce8e9ceSAl Viro if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 11971da177e4SLinus Torvalds err = -EFAULT; 11981da177e4SLinus Torvalds goto drop; 11991da177e4SLinus Torvalds } 12001da177e4SLinus Torvalds 12010d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); 12021da177e4SLinus Torvalds skb_pull(skb, 1); 12031da177e4SLinus Torvalds 12041bc5ad16SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 12051bc5ad16SMarcel Holtmann /* No permission check is needed for user channel 12061bc5ad16SMarcel Holtmann * since that gets enforced when binding the socket. 12071bc5ad16SMarcel Holtmann * 12081bc5ad16SMarcel Holtmann * However check that the packet type is valid. 12091bc5ad16SMarcel Holtmann */ 12101bc5ad16SMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT && 12111bc5ad16SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && 12121bc5ad16SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { 12131bc5ad16SMarcel Holtmann err = -EINVAL; 12141bc5ad16SMarcel Holtmann goto drop; 12151bc5ad16SMarcel Holtmann } 12161bc5ad16SMarcel Holtmann 12171bc5ad16SMarcel Holtmann skb_queue_tail(&hdev->raw_q, skb); 12181bc5ad16SMarcel Holtmann queue_work(hdev->workqueue, &hdev->tx_work); 12191bc5ad16SMarcel Holtmann } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { 122083985319SHarvey Harrison u16 opcode = get_unaligned_le16(skb->data); 12211da177e4SLinus Torvalds u16 ogf = hci_opcode_ogf(opcode); 12221da177e4SLinus Torvalds u16 ocf = hci_opcode_ocf(opcode); 12231da177e4SLinus Torvalds 12241da177e4SLinus Torvalds if (((ogf > HCI_SFLT_MAX_OGF) || 12253bb3c755SGustavo Padovan !hci_test_bit(ocf & HCI_FLT_OCF_BITS, 12263bb3c755SGustavo Padovan &hci_sec_filter.ocf_mask[ogf])) && 12271da177e4SLinus Torvalds !capable(CAP_NET_RAW)) { 12281da177e4SLinus Torvalds err = -EPERM; 12291da177e4SLinus Torvalds goto drop; 12301da177e4SLinus Torvalds } 12311da177e4SLinus Torvalds 1232fee746b0SMarcel Holtmann if (ogf == 0x3f) { 12331da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 12343eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 12351da177e4SLinus Torvalds } else { 123649c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as 123711714b3dSJohan Hedberg * single-command requests. 123811714b3dSJohan Hedberg */ 1239db6e3e8dSJohan Hedberg bt_cb(skb)->req.start = true; 124011714b3dSJohan Hedberg 12411da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb); 1242c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 12431da177e4SLinus Torvalds } 12441da177e4SLinus Torvalds } else { 12451da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 12461da177e4SLinus Torvalds err = -EPERM; 12471da177e4SLinus Torvalds goto drop; 12481da177e4SLinus Torvalds } 12491da177e4SLinus Torvalds 12501da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 12513eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 12521da177e4SLinus Torvalds } 12531da177e4SLinus Torvalds 12541da177e4SLinus Torvalds err = len; 12551da177e4SLinus Torvalds 12561da177e4SLinus Torvalds done: 12571da177e4SLinus Torvalds release_sock(sk); 12581da177e4SLinus Torvalds return err; 12591da177e4SLinus Torvalds 12601da177e4SLinus Torvalds drop: 12611da177e4SLinus Torvalds kfree_skb(skb); 12621da177e4SLinus Torvalds goto done; 12631da177e4SLinus Torvalds } 12641da177e4SLinus Torvalds 12658fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname, 12668fc9ced3SGustavo Padovan char __user *optval, unsigned int len) 12671da177e4SLinus Torvalds { 12681da177e4SLinus Torvalds struct hci_ufilter uf = { .opcode = 0 }; 12691da177e4SLinus Torvalds struct sock *sk = sock->sk; 12701da177e4SLinus Torvalds int err = 0, opt = 0; 12711da177e4SLinus Torvalds 12721da177e4SLinus Torvalds BT_DBG("sk %p, opt %d", sk, optname); 12731da177e4SLinus Torvalds 12741da177e4SLinus Torvalds lock_sock(sk); 12751da177e4SLinus Torvalds 12762f39cdb7SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1277c2371e80SMarcel Holtmann err = -EBADFD; 12782f39cdb7SMarcel Holtmann goto done; 12792f39cdb7SMarcel Holtmann } 12802f39cdb7SMarcel Holtmann 12811da177e4SLinus Torvalds switch (optname) { 12821da177e4SLinus Torvalds case HCI_DATA_DIR: 12831da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 12841da177e4SLinus Torvalds err = -EFAULT; 12851da177e4SLinus Torvalds break; 12861da177e4SLinus Torvalds } 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds if (opt) 12891da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 12901da177e4SLinus Torvalds else 12911da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 12921da177e4SLinus Torvalds break; 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds case HCI_TIME_STAMP: 12951da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 12961da177e4SLinus Torvalds err = -EFAULT; 12971da177e4SLinus Torvalds break; 12981da177e4SLinus Torvalds } 12991da177e4SLinus Torvalds 13001da177e4SLinus Torvalds if (opt) 13011da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 13021da177e4SLinus Torvalds else 13031da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 13041da177e4SLinus Torvalds break; 13051da177e4SLinus Torvalds 13061da177e4SLinus Torvalds case HCI_FILTER: 13070878b666SMarcel Holtmann { 13080878b666SMarcel Holtmann struct hci_filter *f = &hci_pi(sk)->filter; 13090878b666SMarcel Holtmann 13100878b666SMarcel Holtmann uf.type_mask = f->type_mask; 13110878b666SMarcel Holtmann uf.opcode = f->opcode; 13120878b666SMarcel Holtmann uf.event_mask[0] = *((u32 *) f->event_mask + 0); 13130878b666SMarcel Holtmann uf.event_mask[1] = *((u32 *) f->event_mask + 1); 13140878b666SMarcel Holtmann } 13150878b666SMarcel Holtmann 13161da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 13171da177e4SLinus Torvalds if (copy_from_user(&uf, optval, len)) { 13181da177e4SLinus Torvalds err = -EFAULT; 13191da177e4SLinus Torvalds break; 13201da177e4SLinus Torvalds } 13211da177e4SLinus Torvalds 13221da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 13231da177e4SLinus Torvalds uf.type_mask &= hci_sec_filter.type_mask; 13241da177e4SLinus Torvalds uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 13251da177e4SLinus Torvalds uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 13261da177e4SLinus Torvalds } 13271da177e4SLinus Torvalds 13281da177e4SLinus Torvalds { 13291da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 13301da177e4SLinus Torvalds 13311da177e4SLinus Torvalds f->type_mask = uf.type_mask; 13321da177e4SLinus Torvalds f->opcode = uf.opcode; 13331da177e4SLinus Torvalds *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 13341da177e4SLinus Torvalds *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 13351da177e4SLinus Torvalds } 13361da177e4SLinus Torvalds break; 13371da177e4SLinus Torvalds 13381da177e4SLinus Torvalds default: 13391da177e4SLinus Torvalds err = -ENOPROTOOPT; 13401da177e4SLinus Torvalds break; 13411da177e4SLinus Torvalds } 13421da177e4SLinus Torvalds 13432f39cdb7SMarcel Holtmann done: 13441da177e4SLinus Torvalds release_sock(sk); 13451da177e4SLinus Torvalds return err; 13461da177e4SLinus Torvalds } 13471da177e4SLinus Torvalds 13488fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname, 13498fc9ced3SGustavo Padovan char __user *optval, int __user *optlen) 13501da177e4SLinus Torvalds { 13511da177e4SLinus Torvalds struct hci_ufilter uf; 13521da177e4SLinus Torvalds struct sock *sk = sock->sk; 1353cedc5469SMarcel Holtmann int len, opt, err = 0; 1354cedc5469SMarcel Holtmann 1355cedc5469SMarcel Holtmann BT_DBG("sk %p, opt %d", sk, optname); 13561da177e4SLinus Torvalds 13571da177e4SLinus Torvalds if (get_user(len, optlen)) 13581da177e4SLinus Torvalds return -EFAULT; 13591da177e4SLinus Torvalds 1360cedc5469SMarcel Holtmann lock_sock(sk); 1361cedc5469SMarcel Holtmann 1362cedc5469SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1363c2371e80SMarcel Holtmann err = -EBADFD; 1364cedc5469SMarcel Holtmann goto done; 1365cedc5469SMarcel Holtmann } 1366cedc5469SMarcel Holtmann 13671da177e4SLinus Torvalds switch (optname) { 13681da177e4SLinus Torvalds case HCI_DATA_DIR: 13691da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 13701da177e4SLinus Torvalds opt = 1; 13711da177e4SLinus Torvalds else 13721da177e4SLinus Torvalds opt = 0; 13731da177e4SLinus Torvalds 13741da177e4SLinus Torvalds if (put_user(opt, optval)) 1375cedc5469SMarcel Holtmann err = -EFAULT; 13761da177e4SLinus Torvalds break; 13771da177e4SLinus Torvalds 13781da177e4SLinus Torvalds case HCI_TIME_STAMP: 13791da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 13801da177e4SLinus Torvalds opt = 1; 13811da177e4SLinus Torvalds else 13821da177e4SLinus Torvalds opt = 0; 13831da177e4SLinus Torvalds 13841da177e4SLinus Torvalds if (put_user(opt, optval)) 1385cedc5469SMarcel Holtmann err = -EFAULT; 13861da177e4SLinus Torvalds break; 13871da177e4SLinus Torvalds 13881da177e4SLinus Torvalds case HCI_FILTER: 13891da177e4SLinus Torvalds { 13901da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 13911da177e4SLinus Torvalds 1392e15ca9a0SMathias Krause memset(&uf, 0, sizeof(uf)); 13931da177e4SLinus Torvalds uf.type_mask = f->type_mask; 13941da177e4SLinus Torvalds uf.opcode = f->opcode; 13951da177e4SLinus Torvalds uf.event_mask[0] = *((u32 *) f->event_mask + 0); 13961da177e4SLinus Torvalds uf.event_mask[1] = *((u32 *) f->event_mask + 1); 13971da177e4SLinus Torvalds } 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 14001da177e4SLinus Torvalds if (copy_to_user(optval, &uf, len)) 1401cedc5469SMarcel Holtmann err = -EFAULT; 14021da177e4SLinus Torvalds break; 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds default: 1405cedc5469SMarcel Holtmann err = -ENOPROTOOPT; 14061da177e4SLinus Torvalds break; 14071da177e4SLinus Torvalds } 14081da177e4SLinus Torvalds 1409cedc5469SMarcel Holtmann done: 1410cedc5469SMarcel Holtmann release_sock(sk); 1411cedc5469SMarcel Holtmann return err; 14121da177e4SLinus Torvalds } 14131da177e4SLinus Torvalds 141490ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = { 14151da177e4SLinus Torvalds .family = PF_BLUETOOTH, 14161da177e4SLinus Torvalds .owner = THIS_MODULE, 14171da177e4SLinus Torvalds .release = hci_sock_release, 14181da177e4SLinus Torvalds .bind = hci_sock_bind, 14191da177e4SLinus Torvalds .getname = hci_sock_getname, 14201da177e4SLinus Torvalds .sendmsg = hci_sock_sendmsg, 14211da177e4SLinus Torvalds .recvmsg = hci_sock_recvmsg, 14221da177e4SLinus Torvalds .ioctl = hci_sock_ioctl, 14231da177e4SLinus Torvalds .poll = datagram_poll, 14241da177e4SLinus Torvalds .listen = sock_no_listen, 14251da177e4SLinus Torvalds .shutdown = sock_no_shutdown, 14261da177e4SLinus Torvalds .setsockopt = hci_sock_setsockopt, 14271da177e4SLinus Torvalds .getsockopt = hci_sock_getsockopt, 14281da177e4SLinus Torvalds .connect = sock_no_connect, 14291da177e4SLinus Torvalds .socketpair = sock_no_socketpair, 14301da177e4SLinus Torvalds .accept = sock_no_accept, 14311da177e4SLinus Torvalds .mmap = sock_no_mmap 14321da177e4SLinus Torvalds }; 14331da177e4SLinus Torvalds 14341da177e4SLinus Torvalds static struct proto hci_sk_proto = { 14351da177e4SLinus Torvalds .name = "HCI", 14361da177e4SLinus Torvalds .owner = THIS_MODULE, 14371da177e4SLinus Torvalds .obj_size = sizeof(struct hci_pinfo) 14381da177e4SLinus Torvalds }; 14391da177e4SLinus Torvalds 14403f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 14413f378b68SEric Paris int kern) 14421da177e4SLinus Torvalds { 14431da177e4SLinus Torvalds struct sock *sk; 14441da177e4SLinus Torvalds 14451da177e4SLinus Torvalds BT_DBG("sock %p", sock); 14461da177e4SLinus Torvalds 14471da177e4SLinus Torvalds if (sock->type != SOCK_RAW) 14481da177e4SLinus Torvalds return -ESOCKTNOSUPPORT; 14491da177e4SLinus Torvalds 14501da177e4SLinus Torvalds sock->ops = &hci_sock_ops; 14511da177e4SLinus Torvalds 145211aa9c28SEric W. Biederman sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern); 14531da177e4SLinus Torvalds if (!sk) 14541da177e4SLinus Torvalds return -ENOMEM; 14551da177e4SLinus Torvalds 14561da177e4SLinus Torvalds sock_init_data(sock, sk); 14571da177e4SLinus Torvalds 14581da177e4SLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 14591da177e4SLinus Torvalds 14601da177e4SLinus Torvalds sk->sk_protocol = protocol; 14611da177e4SLinus Torvalds 14621da177e4SLinus Torvalds sock->state = SS_UNCONNECTED; 14631da177e4SLinus Torvalds sk->sk_state = BT_OPEN; 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds bt_sock_link(&hci_sk_list, sk); 14661da177e4SLinus Torvalds return 0; 14671da177e4SLinus Torvalds } 14681da177e4SLinus Torvalds 1469ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = { 14701da177e4SLinus Torvalds .family = PF_BLUETOOTH, 14711da177e4SLinus Torvalds .owner = THIS_MODULE, 14721da177e4SLinus Torvalds .create = hci_sock_create, 14731da177e4SLinus Torvalds }; 14741da177e4SLinus Torvalds 14751da177e4SLinus Torvalds int __init hci_sock_init(void) 14761da177e4SLinus Torvalds { 14771da177e4SLinus Torvalds int err; 14781da177e4SLinus Torvalds 1479b0a8e282SMarcel Holtmann BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr)); 1480b0a8e282SMarcel Holtmann 14811da177e4SLinus Torvalds err = proto_register(&hci_sk_proto, 0); 14821da177e4SLinus Torvalds if (err < 0) 14831da177e4SLinus Torvalds return err; 14841da177e4SLinus Torvalds 14851da177e4SLinus Torvalds err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 1486f7c86637SMasatake YAMATO if (err < 0) { 1487f7c86637SMasatake YAMATO BT_ERR("HCI socket registration failed"); 14881da177e4SLinus Torvalds goto error; 1489f7c86637SMasatake YAMATO } 1490f7c86637SMasatake YAMATO 1491b0316615SAl Viro err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL); 1492f7c86637SMasatake YAMATO if (err < 0) { 1493f7c86637SMasatake YAMATO BT_ERR("Failed to create HCI proc file"); 1494f7c86637SMasatake YAMATO bt_sock_unregister(BTPROTO_HCI); 1495f7c86637SMasatake YAMATO goto error; 1496f7c86637SMasatake YAMATO } 14971da177e4SLinus Torvalds 14981da177e4SLinus Torvalds BT_INFO("HCI socket layer initialized"); 14991da177e4SLinus Torvalds 15001da177e4SLinus Torvalds return 0; 15011da177e4SLinus Torvalds 15021da177e4SLinus Torvalds error: 15031da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 15041da177e4SLinus Torvalds return err; 15051da177e4SLinus Torvalds } 15061da177e4SLinus Torvalds 1507b7440a14SAnand Gadiyar void hci_sock_cleanup(void) 15081da177e4SLinus Torvalds { 1509f7c86637SMasatake YAMATO bt_procfs_cleanup(&init_net, "hci"); 15105e9d7f86SDavid Herrmann bt_sock_unregister(BTPROTO_HCI); 15111da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 15121da177e4SLinus Torvalds } 1513