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 123d79f34e3SMarcel Holtmann flt_type = hci_skb_pkt_type(skb) & HCI_FLT_TYPE_BITS; 124f81fe64fSMarcel Holtmann 125f81fe64fSMarcel Holtmann if (!test_bit(flt_type, &flt->type_mask)) 126f81fe64fSMarcel Holtmann return true; 127f81fe64fSMarcel Holtmann 128f81fe64fSMarcel Holtmann /* Extra filter for event packets only */ 129d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT) 130f81fe64fSMarcel Holtmann return false; 131f81fe64fSMarcel Holtmann 132f81fe64fSMarcel Holtmann flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); 133f81fe64fSMarcel Holtmann 134f81fe64fSMarcel Holtmann if (!hci_test_bit(flt_event, &flt->event_mask)) 135f81fe64fSMarcel Holtmann return true; 136f81fe64fSMarcel Holtmann 137f81fe64fSMarcel Holtmann /* Check filter only when opcode is set */ 138f81fe64fSMarcel Holtmann if (!flt->opcode) 139f81fe64fSMarcel Holtmann return false; 140f81fe64fSMarcel Holtmann 141f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_COMPLETE && 142f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 3))) 143f81fe64fSMarcel Holtmann return true; 144f81fe64fSMarcel Holtmann 145f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_STATUS && 146f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 4))) 147f81fe64fSMarcel Holtmann return true; 148f81fe64fSMarcel Holtmann 149f81fe64fSMarcel Holtmann return false; 150f81fe64fSMarcel Holtmann } 151f81fe64fSMarcel Holtmann 1521da177e4SLinus Torvalds /* Send frame to RAW socket */ 153470fe1b5SMarcel Holtmann void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) 1541da177e4SLinus Torvalds { 1551da177e4SLinus Torvalds struct sock *sk; 156e0edf373SMarcel Holtmann struct sk_buff *skb_copy = NULL; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds BT_DBG("hdev %p len %d", hdev, skb->len); 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds read_lock(&hci_sk_list.lock); 161470fe1b5SMarcel Holtmann 162b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 1631da177e4SLinus Torvalds struct sk_buff *nskb; 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 1661da177e4SLinus Torvalds continue; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* Don't send frame to the socket it came from */ 1691da177e4SLinus Torvalds if (skb->sk == sk) 1701da177e4SLinus Torvalds continue; 1711da177e4SLinus Torvalds 17223500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { 173d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && 174d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 175d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 176d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) 177bb77543eSMarcel Holtmann continue; 178f81fe64fSMarcel Holtmann if (is_filtered_packet(sk, skb)) 1791da177e4SLinus Torvalds continue; 18023500189SMarcel Holtmann } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 18123500189SMarcel Holtmann if (!bt_cb(skb)->incoming) 18223500189SMarcel Holtmann continue; 183d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 184d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 185d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) 18623500189SMarcel Holtmann continue; 18723500189SMarcel Holtmann } else { 18823500189SMarcel Holtmann /* Don't send frame to other channel types */ 18923500189SMarcel Holtmann continue; 19023500189SMarcel Holtmann } 1911da177e4SLinus Torvalds 192e0edf373SMarcel Holtmann if (!skb_copy) { 193e0edf373SMarcel Holtmann /* Create a private copy with headroom */ 194bad93e9dSOctavian Purdila skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true); 195e0edf373SMarcel Holtmann if (!skb_copy) 1961da177e4SLinus Torvalds continue; 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds /* Put type byte before the data */ 199d79f34e3SMarcel Holtmann memcpy(skb_push(skb_copy, 1), &hci_skb_pkt_type(skb), 1); 200e0edf373SMarcel Holtmann } 201e0edf373SMarcel Holtmann 202e0edf373SMarcel Holtmann nskb = skb_clone(skb_copy, GFP_ATOMIC); 203e0edf373SMarcel Holtmann if (!nskb) 204e0edf373SMarcel Holtmann continue; 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds if (sock_queue_rcv_skb(sk, nskb)) 2071da177e4SLinus Torvalds kfree_skb(nskb); 2081da177e4SLinus Torvalds } 209470fe1b5SMarcel Holtmann 210470fe1b5SMarcel Holtmann read_unlock(&hci_sk_list.lock); 211e0edf373SMarcel Holtmann 212e0edf373SMarcel Holtmann kfree_skb(skb_copy); 213470fe1b5SMarcel Holtmann } 214470fe1b5SMarcel Holtmann 2157129069eSJohan Hedberg /* Send frame to sockets with specific channel */ 2167129069eSJohan Hedberg void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, 217c08b1a1dSMarcel Holtmann int flag, struct sock *skip_sk) 218470fe1b5SMarcel Holtmann { 219470fe1b5SMarcel Holtmann struct sock *sk; 220470fe1b5SMarcel Holtmann 2217129069eSJohan Hedberg BT_DBG("channel %u len %d", channel, skb->len); 222470fe1b5SMarcel Holtmann 223470fe1b5SMarcel Holtmann read_lock(&hci_sk_list.lock); 224470fe1b5SMarcel Holtmann 225b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 226470fe1b5SMarcel Holtmann struct sk_buff *nskb; 227470fe1b5SMarcel Holtmann 228c08b1a1dSMarcel Holtmann /* Ignore socket without the flag set */ 229c85be545SMarcel Holtmann if (!hci_sock_test_flag(sk, flag)) 230c08b1a1dSMarcel Holtmann continue; 231c08b1a1dSMarcel Holtmann 232470fe1b5SMarcel Holtmann /* Skip the original socket */ 233470fe1b5SMarcel Holtmann if (sk == skip_sk) 234470fe1b5SMarcel Holtmann continue; 235470fe1b5SMarcel Holtmann 236470fe1b5SMarcel Holtmann if (sk->sk_state != BT_BOUND) 237470fe1b5SMarcel Holtmann continue; 238470fe1b5SMarcel Holtmann 2397129069eSJohan Hedberg if (hci_pi(sk)->channel != channel) 240d7f72f61SMarcel Holtmann continue; 241d7f72f61SMarcel Holtmann 242d7f72f61SMarcel Holtmann nskb = skb_clone(skb, GFP_ATOMIC); 243d7f72f61SMarcel Holtmann if (!nskb) 244d7f72f61SMarcel Holtmann continue; 245d7f72f61SMarcel Holtmann 246d7f72f61SMarcel Holtmann if (sock_queue_rcv_skb(sk, nskb)) 247d7f72f61SMarcel Holtmann kfree_skb(nskb); 248d7f72f61SMarcel Holtmann } 249d7f72f61SMarcel Holtmann 250d7f72f61SMarcel Holtmann read_unlock(&hci_sk_list.lock); 251d7f72f61SMarcel Holtmann } 252d7f72f61SMarcel Holtmann 253cd82e61cSMarcel Holtmann /* Send frame to monitor socket */ 254cd82e61cSMarcel Holtmann void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) 255cd82e61cSMarcel Holtmann { 256cd82e61cSMarcel Holtmann struct sk_buff *skb_copy = NULL; 2572b531294SMarcel Holtmann struct hci_mon_hdr *hdr; 258cd82e61cSMarcel Holtmann __le16 opcode; 259cd82e61cSMarcel Holtmann 260cd82e61cSMarcel Holtmann if (!atomic_read(&monitor_promisc)) 261cd82e61cSMarcel Holtmann return; 262cd82e61cSMarcel Holtmann 263cd82e61cSMarcel Holtmann BT_DBG("hdev %p len %d", hdev, skb->len); 264cd82e61cSMarcel Holtmann 265d79f34e3SMarcel Holtmann switch (hci_skb_pkt_type(skb)) { 266cd82e61cSMarcel Holtmann case HCI_COMMAND_PKT: 267dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); 268cd82e61cSMarcel Holtmann break; 269cd82e61cSMarcel Holtmann case HCI_EVENT_PKT: 270dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_EVENT_PKT); 271cd82e61cSMarcel Holtmann break; 272cd82e61cSMarcel Holtmann case HCI_ACLDATA_PKT: 273cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 274dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); 275cd82e61cSMarcel Holtmann else 276dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); 277cd82e61cSMarcel Holtmann break; 278cd82e61cSMarcel Holtmann case HCI_SCODATA_PKT: 279cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 280dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); 281cd82e61cSMarcel Holtmann else 282dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); 283cd82e61cSMarcel Holtmann break; 284e875ff84SMarcel Holtmann case HCI_DIAG_PKT: 285e875ff84SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG); 286e875ff84SMarcel Holtmann break; 287cd82e61cSMarcel Holtmann default: 288cd82e61cSMarcel Holtmann return; 289cd82e61cSMarcel Holtmann } 290cd82e61cSMarcel Holtmann 2912b531294SMarcel Holtmann /* Create a private copy with headroom */ 2922b531294SMarcel Holtmann skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true); 2932b531294SMarcel Holtmann if (!skb_copy) 2942b531294SMarcel Holtmann return; 2952b531294SMarcel Holtmann 2962b531294SMarcel Holtmann /* Put header before the data */ 2972b531294SMarcel Holtmann hdr = (void *) skb_push(skb_copy, HCI_MON_HDR_SIZE); 2982b531294SMarcel Holtmann hdr->opcode = opcode; 2992b531294SMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 3002b531294SMarcel Holtmann hdr->len = cpu_to_le16(skb->len); 3012b531294SMarcel Holtmann 302c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, 303c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 304cd82e61cSMarcel Holtmann kfree_skb(skb_copy); 305cd82e61cSMarcel Holtmann } 306cd82e61cSMarcel Holtmann 307cd82e61cSMarcel Holtmann static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) 308cd82e61cSMarcel Holtmann { 309cd82e61cSMarcel Holtmann struct hci_mon_hdr *hdr; 310cd82e61cSMarcel Holtmann struct hci_mon_new_index *ni; 3116c566dd5SMarcel Holtmann struct hci_mon_index_info *ii; 312cd82e61cSMarcel Holtmann struct sk_buff *skb; 313cd82e61cSMarcel Holtmann __le16 opcode; 314cd82e61cSMarcel Holtmann 315cd82e61cSMarcel Holtmann switch (event) { 316cd82e61cSMarcel Holtmann case HCI_DEV_REG: 317cd82e61cSMarcel Holtmann skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC); 318cd82e61cSMarcel Holtmann if (!skb) 319cd82e61cSMarcel Holtmann return NULL; 320cd82e61cSMarcel Holtmann 321cd82e61cSMarcel Holtmann ni = (void *)skb_put(skb, HCI_MON_NEW_INDEX_SIZE); 322cd82e61cSMarcel Holtmann ni->type = hdev->dev_type; 323cd82e61cSMarcel Holtmann ni->bus = hdev->bus; 324cd82e61cSMarcel Holtmann bacpy(&ni->bdaddr, &hdev->bdaddr); 325cd82e61cSMarcel Holtmann memcpy(ni->name, hdev->name, 8); 326cd82e61cSMarcel Holtmann 327dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_NEW_INDEX); 328cd82e61cSMarcel Holtmann break; 329cd82e61cSMarcel Holtmann 330cd82e61cSMarcel Holtmann case HCI_DEV_UNREG: 331cd82e61cSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 332cd82e61cSMarcel Holtmann if (!skb) 333cd82e61cSMarcel Holtmann return NULL; 334cd82e61cSMarcel Holtmann 335dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_DEL_INDEX); 336cd82e61cSMarcel Holtmann break; 337cd82e61cSMarcel Holtmann 338e131d74aSMarcel Holtmann case HCI_DEV_SETUP: 339e131d74aSMarcel Holtmann if (hdev->manufacturer == 0xffff) 340e131d74aSMarcel Holtmann return NULL; 341e131d74aSMarcel Holtmann 342e131d74aSMarcel Holtmann /* fall through */ 343e131d74aSMarcel Holtmann 3446c566dd5SMarcel Holtmann case HCI_DEV_UP: 3456c566dd5SMarcel Holtmann skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC); 3466c566dd5SMarcel Holtmann if (!skb) 3476c566dd5SMarcel Holtmann return NULL; 3486c566dd5SMarcel Holtmann 3496c566dd5SMarcel Holtmann ii = (void *)skb_put(skb, HCI_MON_INDEX_INFO_SIZE); 3506c566dd5SMarcel Holtmann bacpy(&ii->bdaddr, &hdev->bdaddr); 3516c566dd5SMarcel Holtmann ii->manufacturer = cpu_to_le16(hdev->manufacturer); 3526c566dd5SMarcel Holtmann 3536c566dd5SMarcel Holtmann opcode = cpu_to_le16(HCI_MON_INDEX_INFO); 3546c566dd5SMarcel Holtmann break; 3556c566dd5SMarcel Holtmann 35622db3cbcSMarcel Holtmann case HCI_DEV_OPEN: 35722db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 35822db3cbcSMarcel Holtmann if (!skb) 35922db3cbcSMarcel Holtmann return NULL; 36022db3cbcSMarcel Holtmann 36122db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_OPEN_INDEX); 36222db3cbcSMarcel Holtmann break; 36322db3cbcSMarcel Holtmann 36422db3cbcSMarcel Holtmann case HCI_DEV_CLOSE: 36522db3cbcSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 36622db3cbcSMarcel Holtmann if (!skb) 36722db3cbcSMarcel Holtmann return NULL; 36822db3cbcSMarcel Holtmann 36922db3cbcSMarcel Holtmann opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX); 37022db3cbcSMarcel Holtmann break; 37122db3cbcSMarcel Holtmann 372cd82e61cSMarcel Holtmann default: 373cd82e61cSMarcel Holtmann return NULL; 374cd82e61cSMarcel Holtmann } 375cd82e61cSMarcel Holtmann 376cd82e61cSMarcel Holtmann __net_timestamp(skb); 377cd82e61cSMarcel Holtmann 378cd82e61cSMarcel Holtmann hdr = (void *) skb_push(skb, HCI_MON_HDR_SIZE); 379cd82e61cSMarcel Holtmann hdr->opcode = opcode; 380cd82e61cSMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 381cd82e61cSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 382cd82e61cSMarcel Holtmann 383cd82e61cSMarcel Holtmann return skb; 384cd82e61cSMarcel Holtmann } 385cd82e61cSMarcel Holtmann 386cd82e61cSMarcel Holtmann static void send_monitor_replay(struct sock *sk) 387cd82e61cSMarcel Holtmann { 388cd82e61cSMarcel Holtmann struct hci_dev *hdev; 389cd82e61cSMarcel Holtmann 390cd82e61cSMarcel Holtmann read_lock(&hci_dev_list_lock); 391cd82e61cSMarcel Holtmann 392cd82e61cSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 393cd82e61cSMarcel Holtmann struct sk_buff *skb; 394cd82e61cSMarcel Holtmann 395cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_REG); 396cd82e61cSMarcel Holtmann if (!skb) 397cd82e61cSMarcel Holtmann continue; 398cd82e61cSMarcel Holtmann 399cd82e61cSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 400cd82e61cSMarcel Holtmann kfree_skb(skb); 40122db3cbcSMarcel Holtmann 40222db3cbcSMarcel Holtmann if (!test_bit(HCI_RUNNING, &hdev->flags)) 40322db3cbcSMarcel Holtmann continue; 40422db3cbcSMarcel Holtmann 40522db3cbcSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_OPEN); 40622db3cbcSMarcel Holtmann if (!skb) 40722db3cbcSMarcel Holtmann continue; 40822db3cbcSMarcel Holtmann 40922db3cbcSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 41022db3cbcSMarcel Holtmann kfree_skb(skb); 4116c566dd5SMarcel Holtmann 412e131d74aSMarcel Holtmann if (test_bit(HCI_UP, &hdev->flags)) 4136c566dd5SMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_UP); 414e131d74aSMarcel Holtmann else if (hci_dev_test_flag(hdev, HCI_SETUP)) 415e131d74aSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_SETUP); 416e131d74aSMarcel Holtmann else 417e131d74aSMarcel Holtmann skb = NULL; 4186c566dd5SMarcel Holtmann 419e131d74aSMarcel Holtmann if (skb) { 4206c566dd5SMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 4216c566dd5SMarcel Holtmann kfree_skb(skb); 422cd82e61cSMarcel Holtmann } 423e131d74aSMarcel Holtmann } 424cd82e61cSMarcel Holtmann 425cd82e61cSMarcel Holtmann read_unlock(&hci_dev_list_lock); 426cd82e61cSMarcel Holtmann } 427cd82e61cSMarcel Holtmann 428040030efSMarcel Holtmann /* Generate internal stack event */ 429040030efSMarcel Holtmann static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 430040030efSMarcel Holtmann { 431040030efSMarcel Holtmann struct hci_event_hdr *hdr; 432040030efSMarcel Holtmann struct hci_ev_stack_internal *ev; 433040030efSMarcel Holtmann struct sk_buff *skb; 434040030efSMarcel Holtmann 435040030efSMarcel Holtmann skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 436040030efSMarcel Holtmann if (!skb) 437040030efSMarcel Holtmann return; 438040030efSMarcel Holtmann 439040030efSMarcel Holtmann hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 440040030efSMarcel Holtmann hdr->evt = HCI_EV_STACK_INTERNAL; 441040030efSMarcel Holtmann hdr->plen = sizeof(*ev) + dlen; 442040030efSMarcel Holtmann 443040030efSMarcel Holtmann ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 444040030efSMarcel Holtmann ev->type = type; 445040030efSMarcel Holtmann memcpy(ev->data, data, dlen); 446040030efSMarcel Holtmann 447040030efSMarcel Holtmann bt_cb(skb)->incoming = 1; 448040030efSMarcel Holtmann __net_timestamp(skb); 449040030efSMarcel Holtmann 450d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_EVENT_PKT; 451040030efSMarcel Holtmann hci_send_to_sock(hdev, skb); 452040030efSMarcel Holtmann kfree_skb(skb); 453040030efSMarcel Holtmann } 454040030efSMarcel Holtmann 455040030efSMarcel Holtmann void hci_sock_dev_event(struct hci_dev *hdev, int event) 456040030efSMarcel Holtmann { 457040030efSMarcel Holtmann BT_DBG("hdev %s event %d", hdev->name, event); 458040030efSMarcel Holtmann 459cd82e61cSMarcel Holtmann if (atomic_read(&monitor_promisc)) { 460cd82e61cSMarcel Holtmann struct sk_buff *skb; 461cd82e61cSMarcel Holtmann 462ed1b28a4SMarcel Holtmann /* Send event to monitor */ 463cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, event); 464cd82e61cSMarcel Holtmann if (skb) { 465c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, 466c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 467cd82e61cSMarcel Holtmann kfree_skb(skb); 468cd82e61cSMarcel Holtmann } 469cd82e61cSMarcel Holtmann } 470cd82e61cSMarcel Holtmann 471ed1b28a4SMarcel Holtmann if (event <= HCI_DEV_DOWN) { 472ed1b28a4SMarcel Holtmann struct hci_ev_si_device ev; 473ed1b28a4SMarcel Holtmann 474040030efSMarcel Holtmann /* Send event to sockets */ 475040030efSMarcel Holtmann ev.event = event; 476040030efSMarcel Holtmann ev.dev_id = hdev->id; 477040030efSMarcel Holtmann hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); 478ed1b28a4SMarcel Holtmann } 479040030efSMarcel Holtmann 480040030efSMarcel Holtmann if (event == HCI_DEV_UNREG) { 481040030efSMarcel Holtmann struct sock *sk; 482040030efSMarcel Holtmann 483040030efSMarcel Holtmann /* Detach sockets from device */ 484040030efSMarcel Holtmann read_lock(&hci_sk_list.lock); 485b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 486040030efSMarcel Holtmann bh_lock_sock_nested(sk); 487040030efSMarcel Holtmann if (hci_pi(sk)->hdev == hdev) { 488040030efSMarcel Holtmann hci_pi(sk)->hdev = NULL; 489040030efSMarcel Holtmann sk->sk_err = EPIPE; 490040030efSMarcel Holtmann sk->sk_state = BT_OPEN; 491040030efSMarcel Holtmann sk->sk_state_change(sk); 492040030efSMarcel Holtmann 493040030efSMarcel Holtmann hci_dev_put(hdev); 494040030efSMarcel Holtmann } 495040030efSMarcel Holtmann bh_unlock_sock(sk); 496040030efSMarcel Holtmann } 497040030efSMarcel Holtmann read_unlock(&hci_sk_list.lock); 498040030efSMarcel Holtmann } 499040030efSMarcel Holtmann } 500040030efSMarcel Holtmann 501801c1e8dSJohan Hedberg static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel) 502801c1e8dSJohan Hedberg { 503801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 504801c1e8dSJohan Hedberg 505801c1e8dSJohan Hedberg list_for_each_entry(c, &mgmt_chan_list, list) { 506801c1e8dSJohan Hedberg if (c->channel == channel) 507801c1e8dSJohan Hedberg return c; 508801c1e8dSJohan Hedberg } 509801c1e8dSJohan Hedberg 510801c1e8dSJohan Hedberg return NULL; 511801c1e8dSJohan Hedberg } 512801c1e8dSJohan Hedberg 513801c1e8dSJohan Hedberg static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel) 514801c1e8dSJohan Hedberg { 515801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 516801c1e8dSJohan Hedberg 517801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 518801c1e8dSJohan Hedberg c = __hci_mgmt_chan_find(channel); 519801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 520801c1e8dSJohan Hedberg 521801c1e8dSJohan Hedberg return c; 522801c1e8dSJohan Hedberg } 523801c1e8dSJohan Hedberg 524801c1e8dSJohan Hedberg int hci_mgmt_chan_register(struct hci_mgmt_chan *c) 525801c1e8dSJohan Hedberg { 526801c1e8dSJohan Hedberg if (c->channel < HCI_CHANNEL_CONTROL) 527801c1e8dSJohan Hedberg return -EINVAL; 528801c1e8dSJohan Hedberg 529801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 530801c1e8dSJohan Hedberg if (__hci_mgmt_chan_find(c->channel)) { 531801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 532801c1e8dSJohan Hedberg return -EALREADY; 533801c1e8dSJohan Hedberg } 534801c1e8dSJohan Hedberg 535801c1e8dSJohan Hedberg list_add_tail(&c->list, &mgmt_chan_list); 536801c1e8dSJohan Hedberg 537801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 538801c1e8dSJohan Hedberg 539801c1e8dSJohan Hedberg return 0; 540801c1e8dSJohan Hedberg } 541801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_register); 542801c1e8dSJohan Hedberg 543801c1e8dSJohan Hedberg void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c) 544801c1e8dSJohan Hedberg { 545801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 546801c1e8dSJohan Hedberg list_del(&c->list); 547801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 548801c1e8dSJohan Hedberg } 549801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_unregister); 550801c1e8dSJohan Hedberg 5511da177e4SLinus Torvalds static int hci_sock_release(struct socket *sock) 5521da177e4SLinus Torvalds { 5531da177e4SLinus Torvalds struct sock *sk = sock->sk; 5547b005bd3SMarcel Holtmann struct hci_dev *hdev; 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 5571da177e4SLinus Torvalds 5581da177e4SLinus Torvalds if (!sk) 5591da177e4SLinus Torvalds return 0; 5601da177e4SLinus Torvalds 5617b005bd3SMarcel Holtmann hdev = hci_pi(sk)->hdev; 5627b005bd3SMarcel Holtmann 563cd82e61cSMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_MONITOR) 564cd82e61cSMarcel Holtmann atomic_dec(&monitor_promisc); 565cd82e61cSMarcel Holtmann 5661da177e4SLinus Torvalds bt_sock_unlink(&hci_sk_list, sk); 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds if (hdev) { 56923500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 5706b3cc1dbSSimon Fels /* When releasing an user channel exclusive access, 5716b3cc1dbSSimon Fels * call hci_dev_do_close directly instead of calling 5726b3cc1dbSSimon Fels * hci_dev_close to ensure the exclusive access will 5736b3cc1dbSSimon Fels * be released and the controller brought back down. 5746b3cc1dbSSimon Fels * 5756b3cc1dbSSimon Fels * The checking of HCI_AUTO_OFF is not needed in this 5766b3cc1dbSSimon Fels * case since it will have been cleared already when 5776b3cc1dbSSimon Fels * opening the user channel. 5786b3cc1dbSSimon Fels */ 5796b3cc1dbSSimon Fels hci_dev_do_close(hdev); 5809380f9eaSLoic Poulain hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 5819380f9eaSLoic Poulain mgmt_index_added(hdev); 58223500189SMarcel Holtmann } 58323500189SMarcel Holtmann 5841da177e4SLinus Torvalds atomic_dec(&hdev->promisc); 5851da177e4SLinus Torvalds hci_dev_put(hdev); 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds 5881da177e4SLinus Torvalds sock_orphan(sk); 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds skb_queue_purge(&sk->sk_receive_queue); 5911da177e4SLinus Torvalds skb_queue_purge(&sk->sk_write_queue); 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds sock_put(sk); 5941da177e4SLinus Torvalds return 0; 5951da177e4SLinus Torvalds } 5961da177e4SLinus Torvalds 597b2a66aadSAntti Julku static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) 598f0358568SJohan Hedberg { 599f0358568SJohan Hedberg bdaddr_t bdaddr; 6005e762444SAntti Julku int err; 601f0358568SJohan Hedberg 602f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 603f0358568SJohan Hedberg return -EFAULT; 604f0358568SJohan Hedberg 60509fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6065e762444SAntti Julku 607dcc36c16SJohan Hedberg err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6085e762444SAntti Julku 60909fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6105e762444SAntti Julku 6115e762444SAntti Julku return err; 612f0358568SJohan Hedberg } 613f0358568SJohan Hedberg 614b2a66aadSAntti Julku static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) 615f0358568SJohan Hedberg { 616f0358568SJohan Hedberg bdaddr_t bdaddr; 6175e762444SAntti Julku int err; 618f0358568SJohan Hedberg 619f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 620f0358568SJohan Hedberg return -EFAULT; 621f0358568SJohan Hedberg 62209fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 6235e762444SAntti Julku 624dcc36c16SJohan Hedberg err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 6255e762444SAntti Julku 62609fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 6275e762444SAntti Julku 6285e762444SAntti Julku return err; 629f0358568SJohan Hedberg } 630f0358568SJohan Hedberg 6311da177e4SLinus Torvalds /* Ioctls that require bound socket */ 6326039aa73SGustavo Padovan static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, 6336039aa73SGustavo Padovan unsigned long arg) 6341da177e4SLinus Torvalds { 6351da177e4SLinus Torvalds struct hci_dev *hdev = hci_pi(sk)->hdev; 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds if (!hdev) 6381da177e4SLinus Torvalds return -EBADFD; 6391da177e4SLinus Torvalds 640d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) 6410736cfa8SMarcel Holtmann return -EBUSY; 6420736cfa8SMarcel Holtmann 643d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 644fee746b0SMarcel Holtmann return -EOPNOTSUPP; 645fee746b0SMarcel Holtmann 6465b69bef5SMarcel Holtmann if (hdev->dev_type != HCI_BREDR) 6475b69bef5SMarcel Holtmann return -EOPNOTSUPP; 6485b69bef5SMarcel Holtmann 6491da177e4SLinus Torvalds switch (cmd) { 6501da177e4SLinus Torvalds case HCISETRAW: 6511da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 652bf5b30b8SZhao Hongjiang return -EPERM; 653db596681SMarcel Holtmann return -EOPNOTSUPP; 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds case HCIGETCONNINFO: 6561da177e4SLinus Torvalds return hci_get_conn_info(hdev, (void __user *) arg); 6571da177e4SLinus Torvalds 65840be492fSMarcel Holtmann case HCIGETAUTHINFO: 65940be492fSMarcel Holtmann return hci_get_auth_info(hdev, (void __user *) arg); 66040be492fSMarcel Holtmann 661f0358568SJohan Hedberg case HCIBLOCKADDR: 662f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 663bf5b30b8SZhao Hongjiang return -EPERM; 664b2a66aadSAntti Julku return hci_sock_blacklist_add(hdev, (void __user *) arg); 665f0358568SJohan Hedberg 666f0358568SJohan Hedberg case HCIUNBLOCKADDR: 667f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 668bf5b30b8SZhao Hongjiang return -EPERM; 669b2a66aadSAntti Julku return hci_sock_blacklist_del(hdev, (void __user *) arg); 6700736cfa8SMarcel Holtmann } 671f0358568SJohan Hedberg 672324d36edSMarcel Holtmann return -ENOIOCTLCMD; 6731da177e4SLinus Torvalds } 6741da177e4SLinus Torvalds 6758fc9ced3SGustavo Padovan static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, 6768fc9ced3SGustavo Padovan unsigned long arg) 6771da177e4SLinus Torvalds { 6781da177e4SLinus Torvalds void __user *argp = (void __user *) arg; 6790736cfa8SMarcel Holtmann struct sock *sk = sock->sk; 6801da177e4SLinus Torvalds int err; 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds BT_DBG("cmd %x arg %lx", cmd, arg); 6831da177e4SLinus Torvalds 684c1c4f956SMarcel Holtmann lock_sock(sk); 685c1c4f956SMarcel Holtmann 686c1c4f956SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 687c1c4f956SMarcel Holtmann err = -EBADFD; 688c1c4f956SMarcel Holtmann goto done; 689c1c4f956SMarcel Holtmann } 690c1c4f956SMarcel Holtmann 691c1c4f956SMarcel Holtmann release_sock(sk); 692c1c4f956SMarcel Holtmann 6931da177e4SLinus Torvalds switch (cmd) { 6941da177e4SLinus Torvalds case HCIGETDEVLIST: 6951da177e4SLinus Torvalds return hci_get_dev_list(argp); 6961da177e4SLinus Torvalds 6971da177e4SLinus Torvalds case HCIGETDEVINFO: 6981da177e4SLinus Torvalds return hci_get_dev_info(argp); 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds case HCIGETCONNLIST: 7011da177e4SLinus Torvalds return hci_get_conn_list(argp); 7021da177e4SLinus Torvalds 7031da177e4SLinus Torvalds case HCIDEVUP: 7041da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 705bf5b30b8SZhao Hongjiang return -EPERM; 7061da177e4SLinus Torvalds return hci_dev_open(arg); 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds case HCIDEVDOWN: 7091da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 710bf5b30b8SZhao Hongjiang return -EPERM; 7111da177e4SLinus Torvalds return hci_dev_close(arg); 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds case HCIDEVRESET: 7141da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 715bf5b30b8SZhao Hongjiang return -EPERM; 7161da177e4SLinus Torvalds return hci_dev_reset(arg); 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds case HCIDEVRESTAT: 7191da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 720bf5b30b8SZhao Hongjiang return -EPERM; 7211da177e4SLinus Torvalds return hci_dev_reset_stat(arg); 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds case HCISETSCAN: 7241da177e4SLinus Torvalds case HCISETAUTH: 7251da177e4SLinus Torvalds case HCISETENCRYPT: 7261da177e4SLinus Torvalds case HCISETPTYPE: 7271da177e4SLinus Torvalds case HCISETLINKPOL: 7281da177e4SLinus Torvalds case HCISETLINKMODE: 7291da177e4SLinus Torvalds case HCISETACLMTU: 7301da177e4SLinus Torvalds case HCISETSCOMTU: 7311da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 732bf5b30b8SZhao Hongjiang return -EPERM; 7331da177e4SLinus Torvalds return hci_dev_cmd(cmd, argp); 7341da177e4SLinus Torvalds 7351da177e4SLinus Torvalds case HCIINQUIRY: 7361da177e4SLinus Torvalds return hci_inquiry(argp); 737c1c4f956SMarcel Holtmann } 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds lock_sock(sk); 740c1c4f956SMarcel Holtmann 7411da177e4SLinus Torvalds err = hci_sock_bound_ioctl(sk, cmd, arg); 742c1c4f956SMarcel Holtmann 743c1c4f956SMarcel Holtmann done: 7441da177e4SLinus Torvalds release_sock(sk); 7451da177e4SLinus Torvalds return err; 7461da177e4SLinus Torvalds } 7471da177e4SLinus Torvalds 7488fc9ced3SGustavo Padovan static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, 7498fc9ced3SGustavo Padovan int addr_len) 7501da177e4SLinus Torvalds { 7510381101fSJohan Hedberg struct sockaddr_hci haddr; 7521da177e4SLinus Torvalds struct sock *sk = sock->sk; 7531da177e4SLinus Torvalds struct hci_dev *hdev = NULL; 7540381101fSJohan Hedberg int len, err = 0; 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 7571da177e4SLinus Torvalds 7580381101fSJohan Hedberg if (!addr) 7590381101fSJohan Hedberg return -EINVAL; 7600381101fSJohan Hedberg 7610381101fSJohan Hedberg memset(&haddr, 0, sizeof(haddr)); 7620381101fSJohan Hedberg len = min_t(unsigned int, sizeof(haddr), addr_len); 7630381101fSJohan Hedberg memcpy(&haddr, addr, len); 7640381101fSJohan Hedberg 7650381101fSJohan Hedberg if (haddr.hci_family != AF_BLUETOOTH) 7660381101fSJohan Hedberg return -EINVAL; 7670381101fSJohan Hedberg 7681da177e4SLinus Torvalds lock_sock(sk); 7691da177e4SLinus Torvalds 7707cc2ade2SMarcel Holtmann if (sk->sk_state == BT_BOUND) { 7717cc2ade2SMarcel Holtmann err = -EALREADY; 7727cc2ade2SMarcel Holtmann goto done; 7737cc2ade2SMarcel Holtmann } 7747cc2ade2SMarcel Holtmann 7757cc2ade2SMarcel Holtmann switch (haddr.hci_channel) { 7767cc2ade2SMarcel Holtmann case HCI_CHANNEL_RAW: 7777cc2ade2SMarcel Holtmann if (hci_pi(sk)->hdev) { 7781da177e4SLinus Torvalds err = -EALREADY; 7791da177e4SLinus Torvalds goto done; 7801da177e4SLinus Torvalds } 7811da177e4SLinus Torvalds 7820381101fSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 7830381101fSJohan Hedberg hdev = hci_dev_get(haddr.hci_dev); 78470f23020SAndrei Emeltchenko if (!hdev) { 7851da177e4SLinus Torvalds err = -ENODEV; 7861da177e4SLinus Torvalds goto done; 7871da177e4SLinus Torvalds } 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds atomic_inc(&hdev->promisc); 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds hci_pi(sk)->hdev = hdev; 7937cc2ade2SMarcel Holtmann break; 7947cc2ade2SMarcel Holtmann 79523500189SMarcel Holtmann case HCI_CHANNEL_USER: 79623500189SMarcel Holtmann if (hci_pi(sk)->hdev) { 79723500189SMarcel Holtmann err = -EALREADY; 79823500189SMarcel Holtmann goto done; 79923500189SMarcel Holtmann } 80023500189SMarcel Holtmann 80123500189SMarcel Holtmann if (haddr.hci_dev == HCI_DEV_NONE) { 80223500189SMarcel Holtmann err = -EINVAL; 80323500189SMarcel Holtmann goto done; 80423500189SMarcel Holtmann } 80523500189SMarcel Holtmann 80610a8b86fSMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 80723500189SMarcel Holtmann err = -EPERM; 80823500189SMarcel Holtmann goto done; 80923500189SMarcel Holtmann } 81023500189SMarcel Holtmann 81123500189SMarcel Holtmann hdev = hci_dev_get(haddr.hci_dev); 81223500189SMarcel Holtmann if (!hdev) { 81323500189SMarcel Holtmann err = -ENODEV; 81423500189SMarcel Holtmann goto done; 81523500189SMarcel Holtmann } 81623500189SMarcel Holtmann 817781f899fSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags) || 818d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_SETUP) || 819781f899fSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG) || 820781f899fSMarcel Holtmann (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) && 821781f899fSMarcel Holtmann test_bit(HCI_UP, &hdev->flags))) { 82223500189SMarcel Holtmann err = -EBUSY; 82323500189SMarcel Holtmann hci_dev_put(hdev); 82423500189SMarcel Holtmann goto done; 82523500189SMarcel Holtmann } 82623500189SMarcel Holtmann 827238be788SMarcel Holtmann if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) { 82823500189SMarcel Holtmann err = -EUSERS; 82923500189SMarcel Holtmann hci_dev_put(hdev); 83023500189SMarcel Holtmann goto done; 83123500189SMarcel Holtmann } 83223500189SMarcel Holtmann 83323500189SMarcel Holtmann mgmt_index_removed(hdev); 83423500189SMarcel Holtmann 83523500189SMarcel Holtmann err = hci_dev_open(hdev->id); 83623500189SMarcel Holtmann if (err) { 837781f899fSMarcel Holtmann if (err == -EALREADY) { 838781f899fSMarcel Holtmann /* In case the transport is already up and 839781f899fSMarcel Holtmann * running, clear the error here. 840781f899fSMarcel Holtmann * 841781f899fSMarcel Holtmann * This can happen when opening an user 842781f899fSMarcel Holtmann * channel and HCI_AUTO_OFF grace period 843781f899fSMarcel Holtmann * is still active. 844781f899fSMarcel Holtmann */ 845781f899fSMarcel Holtmann err = 0; 846781f899fSMarcel Holtmann } else { 847a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 848c6521401SMarcel Holtmann mgmt_index_added(hdev); 84923500189SMarcel Holtmann hci_dev_put(hdev); 85023500189SMarcel Holtmann goto done; 85123500189SMarcel Holtmann } 852781f899fSMarcel Holtmann } 85323500189SMarcel Holtmann 85423500189SMarcel Holtmann atomic_inc(&hdev->promisc); 85523500189SMarcel Holtmann 85623500189SMarcel Holtmann hci_pi(sk)->hdev = hdev; 85723500189SMarcel Holtmann break; 85823500189SMarcel Holtmann 859cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 860cd82e61cSMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 861cd82e61cSMarcel Holtmann err = -EINVAL; 862cd82e61cSMarcel Holtmann goto done; 863cd82e61cSMarcel Holtmann } 864cd82e61cSMarcel Holtmann 865cd82e61cSMarcel Holtmann if (!capable(CAP_NET_RAW)) { 866cd82e61cSMarcel Holtmann err = -EPERM; 867cd82e61cSMarcel Holtmann goto done; 868cd82e61cSMarcel Holtmann } 869cd82e61cSMarcel Holtmann 87050ebc055SMarcel Holtmann /* The monitor interface is restricted to CAP_NET_RAW 87150ebc055SMarcel Holtmann * capabilities and with that implicitly trusted. 87250ebc055SMarcel Holtmann */ 87350ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 87450ebc055SMarcel Holtmann 875cd82e61cSMarcel Holtmann send_monitor_replay(sk); 876cd82e61cSMarcel Holtmann 877cd82e61cSMarcel Holtmann atomic_inc(&monitor_promisc); 878cd82e61cSMarcel Holtmann break; 879cd82e61cSMarcel Holtmann 8807cc2ade2SMarcel Holtmann default: 881801c1e8dSJohan Hedberg if (!hci_mgmt_chan_find(haddr.hci_channel)) { 8827cc2ade2SMarcel Holtmann err = -EINVAL; 8837cc2ade2SMarcel Holtmann goto done; 8847cc2ade2SMarcel Holtmann } 8857cc2ade2SMarcel Holtmann 886801c1e8dSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 887801c1e8dSJohan Hedberg err = -EINVAL; 888801c1e8dSJohan Hedberg goto done; 889801c1e8dSJohan Hedberg } 890801c1e8dSJohan Hedberg 8911195fbb8SMarcel Holtmann /* Users with CAP_NET_ADMIN capabilities are allowed 8921195fbb8SMarcel Holtmann * access to all management commands and events. For 8931195fbb8SMarcel Holtmann * untrusted users the interface is restricted and 8941195fbb8SMarcel Holtmann * also only untrusted events are sent. 89550ebc055SMarcel Holtmann */ 8961195fbb8SMarcel Holtmann if (capable(CAP_NET_ADMIN)) 89750ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 89850ebc055SMarcel Holtmann 899f9207338SMarcel Holtmann /* At the moment the index and unconfigured index events 900f9207338SMarcel Holtmann * are enabled unconditionally. Setting them on each 901f9207338SMarcel Holtmann * socket when binding keeps this functionality. They 902f9207338SMarcel Holtmann * however might be cleared later and then sending of these 903f9207338SMarcel Holtmann * events will be disabled, but that is then intentional. 904f6b7712eSMarcel Holtmann * 905f6b7712eSMarcel Holtmann * This also enables generic events that are safe to be 906f6b7712eSMarcel Holtmann * received by untrusted users. Example for such events 907f6b7712eSMarcel Holtmann * are changes to settings, class of device, name etc. 908f9207338SMarcel Holtmann */ 909f9207338SMarcel Holtmann if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { 910f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); 911f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); 912f6b7712eSMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS); 913f9207338SMarcel Holtmann } 914801c1e8dSJohan Hedberg break; 915801c1e8dSJohan Hedberg } 916801c1e8dSJohan Hedberg 9177cc2ade2SMarcel Holtmann 9187cc2ade2SMarcel Holtmann hci_pi(sk)->channel = haddr.hci_channel; 9191da177e4SLinus Torvalds sk->sk_state = BT_BOUND; 9201da177e4SLinus Torvalds 9211da177e4SLinus Torvalds done: 9221da177e4SLinus Torvalds release_sock(sk); 9231da177e4SLinus Torvalds return err; 9241da177e4SLinus Torvalds } 9251da177e4SLinus Torvalds 9268fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, 9278fc9ced3SGustavo Padovan int *addr_len, int peer) 9281da177e4SLinus Torvalds { 9291da177e4SLinus Torvalds struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 9301da177e4SLinus Torvalds struct sock *sk = sock->sk; 9319d4b68b2SMarcel Holtmann struct hci_dev *hdev; 9329d4b68b2SMarcel Holtmann int err = 0; 9331da177e4SLinus Torvalds 9341da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 9351da177e4SLinus Torvalds 93606f43cbcSMarcel Holtmann if (peer) 93706f43cbcSMarcel Holtmann return -EOPNOTSUPP; 93806f43cbcSMarcel Holtmann 9391da177e4SLinus Torvalds lock_sock(sk); 9401da177e4SLinus Torvalds 9419d4b68b2SMarcel Holtmann hdev = hci_pi(sk)->hdev; 9429d4b68b2SMarcel Holtmann if (!hdev) { 9439d4b68b2SMarcel Holtmann err = -EBADFD; 9449d4b68b2SMarcel Holtmann goto done; 9459d4b68b2SMarcel Holtmann } 9469d4b68b2SMarcel Holtmann 9471da177e4SLinus Torvalds *addr_len = sizeof(*haddr); 9481da177e4SLinus Torvalds haddr->hci_family = AF_BLUETOOTH; 9497b005bd3SMarcel Holtmann haddr->hci_dev = hdev->id; 9509d4b68b2SMarcel Holtmann haddr->hci_channel= hci_pi(sk)->channel; 9511da177e4SLinus Torvalds 9529d4b68b2SMarcel Holtmann done: 9531da177e4SLinus Torvalds release_sock(sk); 9549d4b68b2SMarcel Holtmann return err; 9551da177e4SLinus Torvalds } 9561da177e4SLinus Torvalds 9576039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, 9586039aa73SGustavo Padovan struct sk_buff *skb) 9591da177e4SLinus Torvalds { 9601da177e4SLinus Torvalds __u32 mask = hci_pi(sk)->cmsg_mask; 9611da177e4SLinus Torvalds 9620d48d939SMarcel Holtmann if (mask & HCI_CMSG_DIR) { 9630d48d939SMarcel Holtmann int incoming = bt_cb(skb)->incoming; 9648fc9ced3SGustavo Padovan put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), 9658fc9ced3SGustavo Padovan &incoming); 9660d48d939SMarcel Holtmann } 9671da177e4SLinus Torvalds 968a61bbcf2SPatrick McHardy if (mask & HCI_CMSG_TSTAMP) { 969f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT 970f6e623a6SJohann Felix Soden struct compat_timeval ctv; 971f6e623a6SJohann Felix Soden #endif 972a61bbcf2SPatrick McHardy struct timeval tv; 973767c5eb5SMarcel Holtmann void *data; 974767c5eb5SMarcel Holtmann int len; 975a61bbcf2SPatrick McHardy 976a61bbcf2SPatrick McHardy skb_get_timestamp(skb, &tv); 977767c5eb5SMarcel Holtmann 9781da97f83SDavid S. Miller data = &tv; 9791da97f83SDavid S. Miller len = sizeof(tv); 9801da97f83SDavid S. Miller #ifdef CONFIG_COMPAT 981da88cea1SH. J. Lu if (!COMPAT_USE_64BIT_TIME && 982da88cea1SH. J. Lu (msg->msg_flags & MSG_CMSG_COMPAT)) { 983767c5eb5SMarcel Holtmann ctv.tv_sec = tv.tv_sec; 984767c5eb5SMarcel Holtmann ctv.tv_usec = tv.tv_usec; 985767c5eb5SMarcel Holtmann data = &ctv; 986767c5eb5SMarcel Holtmann len = sizeof(ctv); 987767c5eb5SMarcel Holtmann } 9881da97f83SDavid S. Miller #endif 989767c5eb5SMarcel Holtmann 990767c5eb5SMarcel Holtmann put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 991a61bbcf2SPatrick McHardy } 9921da177e4SLinus Torvalds } 9931da177e4SLinus Torvalds 9941b784140SYing Xue static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 9951b784140SYing Xue int flags) 9961da177e4SLinus Torvalds { 9971da177e4SLinus Torvalds int noblock = flags & MSG_DONTWAIT; 9981da177e4SLinus Torvalds struct sock *sk = sock->sk; 9991da177e4SLinus Torvalds struct sk_buff *skb; 10001da177e4SLinus Torvalds int copied, err; 10011da177e4SLinus Torvalds 10021da177e4SLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 10031da177e4SLinus Torvalds 1004d94a6104SMarcel Holtmann if (flags & MSG_OOB) 10051da177e4SLinus Torvalds return -EOPNOTSUPP; 10061da177e4SLinus Torvalds 10071da177e4SLinus Torvalds if (sk->sk_state == BT_CLOSED) 10081da177e4SLinus Torvalds return 0; 10091da177e4SLinus Torvalds 101070f23020SAndrei Emeltchenko skb = skb_recv_datagram(sk, flags, noblock, &err); 101170f23020SAndrei Emeltchenko if (!skb) 10121da177e4SLinus Torvalds return err; 10131da177e4SLinus Torvalds 10141da177e4SLinus Torvalds copied = skb->len; 10151da177e4SLinus Torvalds if (len < copied) { 10161da177e4SLinus Torvalds msg->msg_flags |= MSG_TRUNC; 10171da177e4SLinus Torvalds copied = len; 10181da177e4SLinus Torvalds } 10191da177e4SLinus Torvalds 1020badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb); 102151f3d02bSDavid S. Miller err = skb_copy_datagram_msg(skb, 0, msg, copied); 10221da177e4SLinus Torvalds 10233a208627SMarcel Holtmann switch (hci_pi(sk)->channel) { 10243a208627SMarcel Holtmann case HCI_CHANNEL_RAW: 10251da177e4SLinus Torvalds hci_sock_cmsg(sk, msg, skb); 10263a208627SMarcel Holtmann break; 102723500189SMarcel Holtmann case HCI_CHANNEL_USER: 1028cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1029cd82e61cSMarcel Holtmann sock_recv_timestamp(msg, sk, skb); 1030cd82e61cSMarcel Holtmann break; 1031801c1e8dSJohan Hedberg default: 1032801c1e8dSJohan Hedberg if (hci_mgmt_chan_find(hci_pi(sk)->channel)) 1033801c1e8dSJohan Hedberg sock_recv_timestamp(msg, sk, skb); 1034801c1e8dSJohan Hedberg break; 10353a208627SMarcel Holtmann } 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds skb_free_datagram(sk, skb); 10381da177e4SLinus Torvalds 10391da177e4SLinus Torvalds return err ? : copied; 10401da177e4SLinus Torvalds } 10411da177e4SLinus Torvalds 1042fa4335d7SJohan Hedberg static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, 1043fa4335d7SJohan Hedberg struct msghdr *msg, size_t msglen) 1044fa4335d7SJohan Hedberg { 1045fa4335d7SJohan Hedberg void *buf; 1046fa4335d7SJohan Hedberg u8 *cp; 1047fa4335d7SJohan Hedberg struct mgmt_hdr *hdr; 1048fa4335d7SJohan Hedberg u16 opcode, index, len; 1049fa4335d7SJohan Hedberg struct hci_dev *hdev = NULL; 1050fa4335d7SJohan Hedberg const struct hci_mgmt_handler *handler; 1051fa4335d7SJohan Hedberg bool var_len, no_hdev; 1052fa4335d7SJohan Hedberg int err; 1053fa4335d7SJohan Hedberg 1054fa4335d7SJohan Hedberg BT_DBG("got %zu bytes", msglen); 1055fa4335d7SJohan Hedberg 1056fa4335d7SJohan Hedberg if (msglen < sizeof(*hdr)) 1057fa4335d7SJohan Hedberg return -EINVAL; 1058fa4335d7SJohan Hedberg 1059fa4335d7SJohan Hedberg buf = kmalloc(msglen, GFP_KERNEL); 1060fa4335d7SJohan Hedberg if (!buf) 1061fa4335d7SJohan Hedberg return -ENOMEM; 1062fa4335d7SJohan Hedberg 1063fa4335d7SJohan Hedberg if (memcpy_from_msg(buf, msg, msglen)) { 1064fa4335d7SJohan Hedberg err = -EFAULT; 1065fa4335d7SJohan Hedberg goto done; 1066fa4335d7SJohan Hedberg } 1067fa4335d7SJohan Hedberg 1068fa4335d7SJohan Hedberg hdr = buf; 1069fa4335d7SJohan Hedberg opcode = __le16_to_cpu(hdr->opcode); 1070fa4335d7SJohan Hedberg index = __le16_to_cpu(hdr->index); 1071fa4335d7SJohan Hedberg len = __le16_to_cpu(hdr->len); 1072fa4335d7SJohan Hedberg 1073fa4335d7SJohan Hedberg if (len != msglen - sizeof(*hdr)) { 1074fa4335d7SJohan Hedberg err = -EINVAL; 1075fa4335d7SJohan Hedberg goto done; 1076fa4335d7SJohan Hedberg } 1077fa4335d7SJohan Hedberg 1078fa4335d7SJohan Hedberg if (opcode >= chan->handler_count || 1079fa4335d7SJohan Hedberg chan->handlers[opcode].func == NULL) { 1080fa4335d7SJohan Hedberg BT_DBG("Unknown op %u", opcode); 1081fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1082fa4335d7SJohan Hedberg MGMT_STATUS_UNKNOWN_COMMAND); 1083fa4335d7SJohan Hedberg goto done; 1084fa4335d7SJohan Hedberg } 1085fa4335d7SJohan Hedberg 1086fa4335d7SJohan Hedberg handler = &chan->handlers[opcode]; 1087fa4335d7SJohan Hedberg 1088fa4335d7SJohan Hedberg if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) && 1089fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNTRUSTED)) { 1090fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1091fa4335d7SJohan Hedberg MGMT_STATUS_PERMISSION_DENIED); 1092fa4335d7SJohan Hedberg goto done; 1093fa4335d7SJohan Hedberg } 1094fa4335d7SJohan Hedberg 1095fa4335d7SJohan Hedberg if (index != MGMT_INDEX_NONE) { 1096fa4335d7SJohan Hedberg hdev = hci_dev_get(index); 1097fa4335d7SJohan Hedberg if (!hdev) { 1098fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1099fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1100fa4335d7SJohan Hedberg goto done; 1101fa4335d7SJohan Hedberg } 1102fa4335d7SJohan Hedberg 1103fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_SETUP) || 1104fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_CONFIG) || 1105fa4335d7SJohan Hedberg hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 1106fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1107fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1108fa4335d7SJohan Hedberg goto done; 1109fa4335d7SJohan Hedberg } 1110fa4335d7SJohan Hedberg 1111fa4335d7SJohan Hedberg if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 1112fa4335d7SJohan Hedberg !(handler->flags & HCI_MGMT_UNCONFIGURED)) { 1113fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1114fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1115fa4335d7SJohan Hedberg goto done; 1116fa4335d7SJohan Hedberg } 1117fa4335d7SJohan Hedberg } 1118fa4335d7SJohan Hedberg 1119fa4335d7SJohan Hedberg no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); 1120fa4335d7SJohan Hedberg if (no_hdev != !hdev) { 1121fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1122fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_INDEX); 1123fa4335d7SJohan Hedberg goto done; 1124fa4335d7SJohan Hedberg } 1125fa4335d7SJohan Hedberg 1126fa4335d7SJohan Hedberg var_len = (handler->flags & HCI_MGMT_VAR_LEN); 1127fa4335d7SJohan Hedberg if ((var_len && len < handler->data_len) || 1128fa4335d7SJohan Hedberg (!var_len && len != handler->data_len)) { 1129fa4335d7SJohan Hedberg err = mgmt_cmd_status(sk, index, opcode, 1130fa4335d7SJohan Hedberg MGMT_STATUS_INVALID_PARAMS); 1131fa4335d7SJohan Hedberg goto done; 1132fa4335d7SJohan Hedberg } 1133fa4335d7SJohan Hedberg 1134fa4335d7SJohan Hedberg if (hdev && chan->hdev_init) 1135fa4335d7SJohan Hedberg chan->hdev_init(sk, hdev); 1136fa4335d7SJohan Hedberg 1137fa4335d7SJohan Hedberg cp = buf + sizeof(*hdr); 1138fa4335d7SJohan Hedberg 1139fa4335d7SJohan Hedberg err = handler->func(sk, hdev, cp, len); 1140fa4335d7SJohan Hedberg if (err < 0) 1141fa4335d7SJohan Hedberg goto done; 1142fa4335d7SJohan Hedberg 1143fa4335d7SJohan Hedberg err = msglen; 1144fa4335d7SJohan Hedberg 1145fa4335d7SJohan Hedberg done: 1146fa4335d7SJohan Hedberg if (hdev) 1147fa4335d7SJohan Hedberg hci_dev_put(hdev); 1148fa4335d7SJohan Hedberg 1149fa4335d7SJohan Hedberg kfree(buf); 1150fa4335d7SJohan Hedberg return err; 1151fa4335d7SJohan Hedberg } 1152fa4335d7SJohan Hedberg 11531b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, 11541b784140SYing Xue size_t len) 11551da177e4SLinus Torvalds { 11561da177e4SLinus Torvalds struct sock *sk = sock->sk; 1157801c1e8dSJohan Hedberg struct hci_mgmt_chan *chan; 11581da177e4SLinus Torvalds struct hci_dev *hdev; 11591da177e4SLinus Torvalds struct sk_buff *skb; 11601da177e4SLinus Torvalds int err; 11611da177e4SLinus Torvalds 11621da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 11631da177e4SLinus Torvalds 11641da177e4SLinus Torvalds if (msg->msg_flags & MSG_OOB) 11651da177e4SLinus Torvalds return -EOPNOTSUPP; 11661da177e4SLinus Torvalds 11671da177e4SLinus Torvalds if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 11681da177e4SLinus Torvalds return -EINVAL; 11691da177e4SLinus Torvalds 11701da177e4SLinus Torvalds if (len < 4 || len > HCI_MAX_FRAME_SIZE) 11711da177e4SLinus Torvalds return -EINVAL; 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds lock_sock(sk); 11741da177e4SLinus Torvalds 11750381101fSJohan Hedberg switch (hci_pi(sk)->channel) { 11760381101fSJohan Hedberg case HCI_CHANNEL_RAW: 117723500189SMarcel Holtmann case HCI_CHANNEL_USER: 11780381101fSJohan Hedberg break; 1179cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 1180cd82e61cSMarcel Holtmann err = -EOPNOTSUPP; 1181cd82e61cSMarcel Holtmann goto done; 11820381101fSJohan Hedberg default: 1183801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 1184801c1e8dSJohan Hedberg chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); 1185801c1e8dSJohan Hedberg if (chan) 1186fa4335d7SJohan Hedberg err = hci_mgmt_cmd(chan, sk, msg, len); 1187801c1e8dSJohan Hedberg else 11880381101fSJohan Hedberg err = -EINVAL; 1189801c1e8dSJohan Hedberg 1190801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 11910381101fSJohan Hedberg goto done; 11920381101fSJohan Hedberg } 11930381101fSJohan Hedberg 119470f23020SAndrei Emeltchenko hdev = hci_pi(sk)->hdev; 119570f23020SAndrei Emeltchenko if (!hdev) { 11961da177e4SLinus Torvalds err = -EBADFD; 11971da177e4SLinus Torvalds goto done; 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds 12007e21addcSMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) { 12017e21addcSMarcel Holtmann err = -ENETDOWN; 12027e21addcSMarcel Holtmann goto done; 12037e21addcSMarcel Holtmann } 12047e21addcSMarcel Holtmann 120570f23020SAndrei Emeltchenko skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 120670f23020SAndrei Emeltchenko if (!skb) 12071da177e4SLinus Torvalds goto done; 12081da177e4SLinus Torvalds 12096ce8e9ceSAl Viro if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 12101da177e4SLinus Torvalds err = -EFAULT; 12111da177e4SLinus Torvalds goto drop; 12121da177e4SLinus Torvalds } 12131da177e4SLinus Torvalds 1214d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = *((unsigned char *) skb->data); 12151da177e4SLinus Torvalds skb_pull(skb, 1); 12161da177e4SLinus Torvalds 12171bc5ad16SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 12181bc5ad16SMarcel Holtmann /* No permission check is needed for user channel 12191bc5ad16SMarcel Holtmann * since that gets enforced when binding the socket. 12201bc5ad16SMarcel Holtmann * 12211bc5ad16SMarcel Holtmann * However check that the packet type is valid. 12221bc5ad16SMarcel Holtmann */ 1223d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && 1224d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 1225d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { 12261bc5ad16SMarcel Holtmann err = -EINVAL; 12271bc5ad16SMarcel Holtmann goto drop; 12281bc5ad16SMarcel Holtmann } 12291bc5ad16SMarcel Holtmann 12301bc5ad16SMarcel Holtmann skb_queue_tail(&hdev->raw_q, skb); 12311bc5ad16SMarcel Holtmann queue_work(hdev->workqueue, &hdev->tx_work); 1232d79f34e3SMarcel Holtmann } else if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) { 123383985319SHarvey Harrison u16 opcode = get_unaligned_le16(skb->data); 12341da177e4SLinus Torvalds u16 ogf = hci_opcode_ogf(opcode); 12351da177e4SLinus Torvalds u16 ocf = hci_opcode_ocf(opcode); 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds if (((ogf > HCI_SFLT_MAX_OGF) || 12383bb3c755SGustavo Padovan !hci_test_bit(ocf & HCI_FLT_OCF_BITS, 12393bb3c755SGustavo Padovan &hci_sec_filter.ocf_mask[ogf])) && 12401da177e4SLinus Torvalds !capable(CAP_NET_RAW)) { 12411da177e4SLinus Torvalds err = -EPERM; 12421da177e4SLinus Torvalds goto drop; 12431da177e4SLinus Torvalds } 12441da177e4SLinus Torvalds 1245*1982162bSMarcel Holtmann /* Since the opcode has already been extracted here, store 1246*1982162bSMarcel Holtmann * a copy of the value for later use by the drivers. 1247*1982162bSMarcel Holtmann */ 1248*1982162bSMarcel Holtmann hci_skb_opcode(skb) = opcode; 1249*1982162bSMarcel Holtmann 1250fee746b0SMarcel Holtmann if (ogf == 0x3f) { 12511da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 12523eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 12531da177e4SLinus Torvalds } else { 125449c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as 125511714b3dSJohan Hedberg * single-command requests. 125611714b3dSJohan Hedberg */ 125744d27137SJohan Hedberg bt_cb(skb)->hci.req_flags |= HCI_REQ_START; 125811714b3dSJohan Hedberg 12591da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb); 1260c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 12611da177e4SLinus Torvalds } 12621da177e4SLinus Torvalds } else { 12631da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 12641da177e4SLinus Torvalds err = -EPERM; 12651da177e4SLinus Torvalds goto drop; 12661da177e4SLinus Torvalds } 12671da177e4SLinus Torvalds 1268d79f34e3SMarcel Holtmann if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 1269d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { 1270bb77543eSMarcel Holtmann err = -EINVAL; 1271bb77543eSMarcel Holtmann goto drop; 1272bb77543eSMarcel Holtmann } 1273bb77543eSMarcel Holtmann 12741da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 12753eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 12761da177e4SLinus Torvalds } 12771da177e4SLinus Torvalds 12781da177e4SLinus Torvalds err = len; 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds done: 12811da177e4SLinus Torvalds release_sock(sk); 12821da177e4SLinus Torvalds return err; 12831da177e4SLinus Torvalds 12841da177e4SLinus Torvalds drop: 12851da177e4SLinus Torvalds kfree_skb(skb); 12861da177e4SLinus Torvalds goto done; 12871da177e4SLinus Torvalds } 12881da177e4SLinus Torvalds 12898fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname, 12908fc9ced3SGustavo Padovan char __user *optval, unsigned int len) 12911da177e4SLinus Torvalds { 12921da177e4SLinus Torvalds struct hci_ufilter uf = { .opcode = 0 }; 12931da177e4SLinus Torvalds struct sock *sk = sock->sk; 12941da177e4SLinus Torvalds int err = 0, opt = 0; 12951da177e4SLinus Torvalds 12961da177e4SLinus Torvalds BT_DBG("sk %p, opt %d", sk, optname); 12971da177e4SLinus Torvalds 12981da177e4SLinus Torvalds lock_sock(sk); 12991da177e4SLinus Torvalds 13002f39cdb7SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1301c2371e80SMarcel Holtmann err = -EBADFD; 13022f39cdb7SMarcel Holtmann goto done; 13032f39cdb7SMarcel Holtmann } 13042f39cdb7SMarcel Holtmann 13051da177e4SLinus Torvalds switch (optname) { 13061da177e4SLinus Torvalds case HCI_DATA_DIR: 13071da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 13081da177e4SLinus Torvalds err = -EFAULT; 13091da177e4SLinus Torvalds break; 13101da177e4SLinus Torvalds } 13111da177e4SLinus Torvalds 13121da177e4SLinus Torvalds if (opt) 13131da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 13141da177e4SLinus Torvalds else 13151da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 13161da177e4SLinus Torvalds break; 13171da177e4SLinus Torvalds 13181da177e4SLinus Torvalds case HCI_TIME_STAMP: 13191da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 13201da177e4SLinus Torvalds err = -EFAULT; 13211da177e4SLinus Torvalds break; 13221da177e4SLinus Torvalds } 13231da177e4SLinus Torvalds 13241da177e4SLinus Torvalds if (opt) 13251da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 13261da177e4SLinus Torvalds else 13271da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 13281da177e4SLinus Torvalds break; 13291da177e4SLinus Torvalds 13301da177e4SLinus Torvalds case HCI_FILTER: 13310878b666SMarcel Holtmann { 13320878b666SMarcel Holtmann struct hci_filter *f = &hci_pi(sk)->filter; 13330878b666SMarcel Holtmann 13340878b666SMarcel Holtmann uf.type_mask = f->type_mask; 13350878b666SMarcel Holtmann uf.opcode = f->opcode; 13360878b666SMarcel Holtmann uf.event_mask[0] = *((u32 *) f->event_mask + 0); 13370878b666SMarcel Holtmann uf.event_mask[1] = *((u32 *) f->event_mask + 1); 13380878b666SMarcel Holtmann } 13390878b666SMarcel Holtmann 13401da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 13411da177e4SLinus Torvalds if (copy_from_user(&uf, optval, len)) { 13421da177e4SLinus Torvalds err = -EFAULT; 13431da177e4SLinus Torvalds break; 13441da177e4SLinus Torvalds } 13451da177e4SLinus Torvalds 13461da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 13471da177e4SLinus Torvalds uf.type_mask &= hci_sec_filter.type_mask; 13481da177e4SLinus Torvalds uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 13491da177e4SLinus Torvalds uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 13501da177e4SLinus Torvalds } 13511da177e4SLinus Torvalds 13521da177e4SLinus Torvalds { 13531da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds f->type_mask = uf.type_mask; 13561da177e4SLinus Torvalds f->opcode = uf.opcode; 13571da177e4SLinus Torvalds *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 13581da177e4SLinus Torvalds *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 13591da177e4SLinus Torvalds } 13601da177e4SLinus Torvalds break; 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds default: 13631da177e4SLinus Torvalds err = -ENOPROTOOPT; 13641da177e4SLinus Torvalds break; 13651da177e4SLinus Torvalds } 13661da177e4SLinus Torvalds 13672f39cdb7SMarcel Holtmann done: 13681da177e4SLinus Torvalds release_sock(sk); 13691da177e4SLinus Torvalds return err; 13701da177e4SLinus Torvalds } 13711da177e4SLinus Torvalds 13728fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname, 13738fc9ced3SGustavo Padovan char __user *optval, int __user *optlen) 13741da177e4SLinus Torvalds { 13751da177e4SLinus Torvalds struct hci_ufilter uf; 13761da177e4SLinus Torvalds struct sock *sk = sock->sk; 1377cedc5469SMarcel Holtmann int len, opt, err = 0; 1378cedc5469SMarcel Holtmann 1379cedc5469SMarcel Holtmann BT_DBG("sk %p, opt %d", sk, optname); 13801da177e4SLinus Torvalds 13811da177e4SLinus Torvalds if (get_user(len, optlen)) 13821da177e4SLinus Torvalds return -EFAULT; 13831da177e4SLinus Torvalds 1384cedc5469SMarcel Holtmann lock_sock(sk); 1385cedc5469SMarcel Holtmann 1386cedc5469SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1387c2371e80SMarcel Holtmann err = -EBADFD; 1388cedc5469SMarcel Holtmann goto done; 1389cedc5469SMarcel Holtmann } 1390cedc5469SMarcel Holtmann 13911da177e4SLinus Torvalds switch (optname) { 13921da177e4SLinus Torvalds case HCI_DATA_DIR: 13931da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 13941da177e4SLinus Torvalds opt = 1; 13951da177e4SLinus Torvalds else 13961da177e4SLinus Torvalds opt = 0; 13971da177e4SLinus Torvalds 13981da177e4SLinus Torvalds if (put_user(opt, optval)) 1399cedc5469SMarcel Holtmann err = -EFAULT; 14001da177e4SLinus Torvalds break; 14011da177e4SLinus Torvalds 14021da177e4SLinus Torvalds case HCI_TIME_STAMP: 14031da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 14041da177e4SLinus Torvalds opt = 1; 14051da177e4SLinus Torvalds else 14061da177e4SLinus Torvalds opt = 0; 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds if (put_user(opt, optval)) 1409cedc5469SMarcel Holtmann err = -EFAULT; 14101da177e4SLinus Torvalds break; 14111da177e4SLinus Torvalds 14121da177e4SLinus Torvalds case HCI_FILTER: 14131da177e4SLinus Torvalds { 14141da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 14151da177e4SLinus Torvalds 1416e15ca9a0SMathias Krause memset(&uf, 0, sizeof(uf)); 14171da177e4SLinus Torvalds uf.type_mask = f->type_mask; 14181da177e4SLinus Torvalds uf.opcode = f->opcode; 14191da177e4SLinus Torvalds uf.event_mask[0] = *((u32 *) f->event_mask + 0); 14201da177e4SLinus Torvalds uf.event_mask[1] = *((u32 *) f->event_mask + 1); 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 14241da177e4SLinus Torvalds if (copy_to_user(optval, &uf, len)) 1425cedc5469SMarcel Holtmann err = -EFAULT; 14261da177e4SLinus Torvalds break; 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds default: 1429cedc5469SMarcel Holtmann err = -ENOPROTOOPT; 14301da177e4SLinus Torvalds break; 14311da177e4SLinus Torvalds } 14321da177e4SLinus Torvalds 1433cedc5469SMarcel Holtmann done: 1434cedc5469SMarcel Holtmann release_sock(sk); 1435cedc5469SMarcel Holtmann return err; 14361da177e4SLinus Torvalds } 14371da177e4SLinus Torvalds 143890ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = { 14391da177e4SLinus Torvalds .family = PF_BLUETOOTH, 14401da177e4SLinus Torvalds .owner = THIS_MODULE, 14411da177e4SLinus Torvalds .release = hci_sock_release, 14421da177e4SLinus Torvalds .bind = hci_sock_bind, 14431da177e4SLinus Torvalds .getname = hci_sock_getname, 14441da177e4SLinus Torvalds .sendmsg = hci_sock_sendmsg, 14451da177e4SLinus Torvalds .recvmsg = hci_sock_recvmsg, 14461da177e4SLinus Torvalds .ioctl = hci_sock_ioctl, 14471da177e4SLinus Torvalds .poll = datagram_poll, 14481da177e4SLinus Torvalds .listen = sock_no_listen, 14491da177e4SLinus Torvalds .shutdown = sock_no_shutdown, 14501da177e4SLinus Torvalds .setsockopt = hci_sock_setsockopt, 14511da177e4SLinus Torvalds .getsockopt = hci_sock_getsockopt, 14521da177e4SLinus Torvalds .connect = sock_no_connect, 14531da177e4SLinus Torvalds .socketpair = sock_no_socketpair, 14541da177e4SLinus Torvalds .accept = sock_no_accept, 14551da177e4SLinus Torvalds .mmap = sock_no_mmap 14561da177e4SLinus Torvalds }; 14571da177e4SLinus Torvalds 14581da177e4SLinus Torvalds static struct proto hci_sk_proto = { 14591da177e4SLinus Torvalds .name = "HCI", 14601da177e4SLinus Torvalds .owner = THIS_MODULE, 14611da177e4SLinus Torvalds .obj_size = sizeof(struct hci_pinfo) 14621da177e4SLinus Torvalds }; 14631da177e4SLinus Torvalds 14643f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 14653f378b68SEric Paris int kern) 14661da177e4SLinus Torvalds { 14671da177e4SLinus Torvalds struct sock *sk; 14681da177e4SLinus Torvalds 14691da177e4SLinus Torvalds BT_DBG("sock %p", sock); 14701da177e4SLinus Torvalds 14711da177e4SLinus Torvalds if (sock->type != SOCK_RAW) 14721da177e4SLinus Torvalds return -ESOCKTNOSUPPORT; 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds sock->ops = &hci_sock_ops; 14751da177e4SLinus Torvalds 147611aa9c28SEric W. Biederman sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern); 14771da177e4SLinus Torvalds if (!sk) 14781da177e4SLinus Torvalds return -ENOMEM; 14791da177e4SLinus Torvalds 14801da177e4SLinus Torvalds sock_init_data(sock, sk); 14811da177e4SLinus Torvalds 14821da177e4SLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 14831da177e4SLinus Torvalds 14841da177e4SLinus Torvalds sk->sk_protocol = protocol; 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds sock->state = SS_UNCONNECTED; 14871da177e4SLinus Torvalds sk->sk_state = BT_OPEN; 14881da177e4SLinus Torvalds 14891da177e4SLinus Torvalds bt_sock_link(&hci_sk_list, sk); 14901da177e4SLinus Torvalds return 0; 14911da177e4SLinus Torvalds } 14921da177e4SLinus Torvalds 1493ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = { 14941da177e4SLinus Torvalds .family = PF_BLUETOOTH, 14951da177e4SLinus Torvalds .owner = THIS_MODULE, 14961da177e4SLinus Torvalds .create = hci_sock_create, 14971da177e4SLinus Torvalds }; 14981da177e4SLinus Torvalds 14991da177e4SLinus Torvalds int __init hci_sock_init(void) 15001da177e4SLinus Torvalds { 15011da177e4SLinus Torvalds int err; 15021da177e4SLinus Torvalds 1503b0a8e282SMarcel Holtmann BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr)); 1504b0a8e282SMarcel Holtmann 15051da177e4SLinus Torvalds err = proto_register(&hci_sk_proto, 0); 15061da177e4SLinus Torvalds if (err < 0) 15071da177e4SLinus Torvalds return err; 15081da177e4SLinus Torvalds 15091da177e4SLinus Torvalds err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 1510f7c86637SMasatake YAMATO if (err < 0) { 1511f7c86637SMasatake YAMATO BT_ERR("HCI socket registration failed"); 15121da177e4SLinus Torvalds goto error; 1513f7c86637SMasatake YAMATO } 1514f7c86637SMasatake YAMATO 1515b0316615SAl Viro err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL); 1516f7c86637SMasatake YAMATO if (err < 0) { 1517f7c86637SMasatake YAMATO BT_ERR("Failed to create HCI proc file"); 1518f7c86637SMasatake YAMATO bt_sock_unregister(BTPROTO_HCI); 1519f7c86637SMasatake YAMATO goto error; 1520f7c86637SMasatake YAMATO } 15211da177e4SLinus Torvalds 15221da177e4SLinus Torvalds BT_INFO("HCI socket layer initialized"); 15231da177e4SLinus Torvalds 15241da177e4SLinus Torvalds return 0; 15251da177e4SLinus Torvalds 15261da177e4SLinus Torvalds error: 15271da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 15281da177e4SLinus Torvalds return err; 15291da177e4SLinus Torvalds } 15301da177e4SLinus Torvalds 1531b7440a14SAnand Gadiyar void hci_sock_cleanup(void) 15321da177e4SLinus Torvalds { 1533f7c86637SMasatake YAMATO bt_procfs_cleanup(&init_net, "hci"); 15345e9d7f86SDavid Herrmann bt_sock_unregister(BTPROTO_HCI); 15351da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 15361da177e4SLinus Torvalds } 1537