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> 331da177e4SLinus Torvalds 34801c1e8dSJohan Hedberg static LIST_HEAD(mgmt_chan_list); 35801c1e8dSJohan Hedberg static DEFINE_MUTEX(mgmt_chan_list_lock); 36801c1e8dSJohan Hedberg 37cd82e61cSMarcel Holtmann static atomic_t monitor_promisc = ATOMIC_INIT(0); 38cd82e61cSMarcel Holtmann 391da177e4SLinus Torvalds /* ----- HCI socket interface ----- */ 401da177e4SLinus Torvalds 41863def58SMarcel Holtmann /* Socket info */ 42863def58SMarcel Holtmann #define hci_pi(sk) ((struct hci_pinfo *) sk) 43863def58SMarcel Holtmann 44863def58SMarcel Holtmann struct hci_pinfo { 45863def58SMarcel Holtmann struct bt_sock bt; 46863def58SMarcel Holtmann struct hci_dev *hdev; 47863def58SMarcel Holtmann struct hci_filter filter; 48863def58SMarcel Holtmann __u32 cmsg_mask; 49863def58SMarcel Holtmann unsigned short channel; 506befc644SMarcel Holtmann unsigned long flags; 51863def58SMarcel Holtmann }; 52863def58SMarcel Holtmann 536befc644SMarcel Holtmann void hci_sock_set_flag(struct sock *sk, int nr) 546befc644SMarcel Holtmann { 556befc644SMarcel Holtmann set_bit(nr, &hci_pi(sk)->flags); 566befc644SMarcel Holtmann } 576befc644SMarcel Holtmann 586befc644SMarcel Holtmann void hci_sock_clear_flag(struct sock *sk, int nr) 596befc644SMarcel Holtmann { 606befc644SMarcel Holtmann clear_bit(nr, &hci_pi(sk)->flags); 616befc644SMarcel Holtmann } 626befc644SMarcel Holtmann 63c85be545SMarcel Holtmann int hci_sock_test_flag(struct sock *sk, int nr) 64c85be545SMarcel Holtmann { 65c85be545SMarcel Holtmann return test_bit(nr, &hci_pi(sk)->flags); 66c85be545SMarcel Holtmann } 67c85be545SMarcel Holtmann 689391976aSJiri Slaby static inline int hci_test_bit(int nr, const void *addr) 691da177e4SLinus Torvalds { 709391976aSJiri Slaby return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds /* Security filter */ 743ad254f7SMarcel Holtmann #define HCI_SFLT_MAX_OGF 5 753ad254f7SMarcel Holtmann 763ad254f7SMarcel Holtmann struct hci_sec_filter { 773ad254f7SMarcel Holtmann __u32 type_mask; 783ad254f7SMarcel Holtmann __u32 event_mask[2]; 793ad254f7SMarcel Holtmann __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; 803ad254f7SMarcel Holtmann }; 813ad254f7SMarcel Holtmann 827e67c112SMarcel Holtmann static const struct hci_sec_filter hci_sec_filter = { 831da177e4SLinus Torvalds /* Packet types */ 841da177e4SLinus Torvalds 0x10, 851da177e4SLinus Torvalds /* Events */ 86dd7f5527SMarcel Holtmann { 0x1000d9fe, 0x0000b00c }, 871da177e4SLinus Torvalds /* Commands */ 881da177e4SLinus Torvalds { 891da177e4SLinus Torvalds { 0x0 }, 901da177e4SLinus Torvalds /* OGF_LINK_CTL */ 917c631a67SMarcel Holtmann { 0xbe000006, 0x00000001, 0x00000000, 0x00 }, 921da177e4SLinus Torvalds /* OGF_LINK_POLICY */ 937c631a67SMarcel Holtmann { 0x00005200, 0x00000000, 0x00000000, 0x00 }, 941da177e4SLinus Torvalds /* OGF_HOST_CTL */ 957c631a67SMarcel Holtmann { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 }, 961da177e4SLinus Torvalds /* OGF_INFO_PARAM */ 977c631a67SMarcel Holtmann { 0x000002be, 0x00000000, 0x00000000, 0x00 }, 981da177e4SLinus Torvalds /* OGF_STATUS_PARAM */ 997c631a67SMarcel Holtmann { 0x000000ea, 0x00000000, 0x00000000, 0x00 } 1001da177e4SLinus Torvalds } 1011da177e4SLinus Torvalds }; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds static struct bt_sock_list hci_sk_list = { 104d5fb2962SRobert P. J. Day .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) 1051da177e4SLinus Torvalds }; 1061da177e4SLinus Torvalds 107f81fe64fSMarcel Holtmann static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb) 108f81fe64fSMarcel Holtmann { 109f81fe64fSMarcel Holtmann struct hci_filter *flt; 110f81fe64fSMarcel Holtmann int flt_type, flt_event; 111f81fe64fSMarcel Holtmann 112f81fe64fSMarcel Holtmann /* Apply filter */ 113f81fe64fSMarcel Holtmann flt = &hci_pi(sk)->filter; 114f81fe64fSMarcel Holtmann 115f81fe64fSMarcel Holtmann if (bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) 116f81fe64fSMarcel Holtmann flt_type = 0; 117f81fe64fSMarcel Holtmann else 118f81fe64fSMarcel Holtmann flt_type = bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS; 119f81fe64fSMarcel Holtmann 120f81fe64fSMarcel Holtmann if (!test_bit(flt_type, &flt->type_mask)) 121f81fe64fSMarcel Holtmann return true; 122f81fe64fSMarcel Holtmann 123f81fe64fSMarcel Holtmann /* Extra filter for event packets only */ 124f81fe64fSMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT) 125f81fe64fSMarcel Holtmann return false; 126f81fe64fSMarcel Holtmann 127f81fe64fSMarcel Holtmann flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); 128f81fe64fSMarcel Holtmann 129f81fe64fSMarcel Holtmann if (!hci_test_bit(flt_event, &flt->event_mask)) 130f81fe64fSMarcel Holtmann return true; 131f81fe64fSMarcel Holtmann 132f81fe64fSMarcel Holtmann /* Check filter only when opcode is set */ 133f81fe64fSMarcel Holtmann if (!flt->opcode) 134f81fe64fSMarcel Holtmann return false; 135f81fe64fSMarcel Holtmann 136f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_COMPLETE && 137f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 3))) 138f81fe64fSMarcel Holtmann return true; 139f81fe64fSMarcel Holtmann 140f81fe64fSMarcel Holtmann if (flt_event == HCI_EV_CMD_STATUS && 141f81fe64fSMarcel Holtmann flt->opcode != get_unaligned((__le16 *)(skb->data + 4))) 142f81fe64fSMarcel Holtmann return true; 143f81fe64fSMarcel Holtmann 144f81fe64fSMarcel Holtmann return false; 145f81fe64fSMarcel Holtmann } 146f81fe64fSMarcel Holtmann 1471da177e4SLinus Torvalds /* Send frame to RAW socket */ 148470fe1b5SMarcel Holtmann void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) 1491da177e4SLinus Torvalds { 1501da177e4SLinus Torvalds struct sock *sk; 151e0edf373SMarcel Holtmann struct sk_buff *skb_copy = NULL; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds BT_DBG("hdev %p len %d", hdev, skb->len); 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds read_lock(&hci_sk_list.lock); 156470fe1b5SMarcel Holtmann 157b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 1581da177e4SLinus Torvalds struct sk_buff *nskb; 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 1611da177e4SLinus Torvalds continue; 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds /* Don't send frame to the socket it came from */ 1641da177e4SLinus Torvalds if (skb->sk == sk) 1651da177e4SLinus Torvalds continue; 1661da177e4SLinus Torvalds 16723500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { 168f81fe64fSMarcel Holtmann if (is_filtered_packet(sk, skb)) 1691da177e4SLinus Torvalds continue; 17023500189SMarcel Holtmann } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 17123500189SMarcel Holtmann if (!bt_cb(skb)->incoming) 17223500189SMarcel Holtmann continue; 17323500189SMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT && 17423500189SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && 17523500189SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) 17623500189SMarcel Holtmann continue; 17723500189SMarcel Holtmann } else { 17823500189SMarcel Holtmann /* Don't send frame to other channel types */ 17923500189SMarcel Holtmann continue; 18023500189SMarcel Holtmann } 1811da177e4SLinus Torvalds 182e0edf373SMarcel Holtmann if (!skb_copy) { 183e0edf373SMarcel Holtmann /* Create a private copy with headroom */ 184bad93e9dSOctavian Purdila skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true); 185e0edf373SMarcel Holtmann if (!skb_copy) 1861da177e4SLinus Torvalds continue; 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds /* Put type byte before the data */ 189e0edf373SMarcel Holtmann memcpy(skb_push(skb_copy, 1), &bt_cb(skb)->pkt_type, 1); 190e0edf373SMarcel Holtmann } 191e0edf373SMarcel Holtmann 192e0edf373SMarcel Holtmann nskb = skb_clone(skb_copy, GFP_ATOMIC); 193e0edf373SMarcel Holtmann if (!nskb) 194e0edf373SMarcel Holtmann continue; 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds if (sock_queue_rcv_skb(sk, nskb)) 1971da177e4SLinus Torvalds kfree_skb(nskb); 1981da177e4SLinus Torvalds } 199470fe1b5SMarcel Holtmann 200470fe1b5SMarcel Holtmann read_unlock(&hci_sk_list.lock); 201e0edf373SMarcel Holtmann 202e0edf373SMarcel Holtmann kfree_skb(skb_copy); 203470fe1b5SMarcel Holtmann } 204470fe1b5SMarcel Holtmann 2057129069eSJohan Hedberg /* Send frame to sockets with specific channel */ 2067129069eSJohan Hedberg void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, 207c08b1a1dSMarcel Holtmann int flag, struct sock *skip_sk) 208470fe1b5SMarcel Holtmann { 209470fe1b5SMarcel Holtmann struct sock *sk; 210470fe1b5SMarcel Holtmann 2117129069eSJohan Hedberg BT_DBG("channel %u len %d", channel, skb->len); 212470fe1b5SMarcel Holtmann 213470fe1b5SMarcel Holtmann read_lock(&hci_sk_list.lock); 214470fe1b5SMarcel Holtmann 215b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 216470fe1b5SMarcel Holtmann struct sk_buff *nskb; 217470fe1b5SMarcel Holtmann 218c08b1a1dSMarcel Holtmann /* Ignore socket without the flag set */ 219c85be545SMarcel Holtmann if (!hci_sock_test_flag(sk, flag)) 220c08b1a1dSMarcel Holtmann continue; 221c08b1a1dSMarcel Holtmann 222470fe1b5SMarcel Holtmann /* Skip the original socket */ 223470fe1b5SMarcel Holtmann if (sk == skip_sk) 224470fe1b5SMarcel Holtmann continue; 225470fe1b5SMarcel Holtmann 226470fe1b5SMarcel Holtmann if (sk->sk_state != BT_BOUND) 227470fe1b5SMarcel Holtmann continue; 228470fe1b5SMarcel Holtmann 2297129069eSJohan Hedberg if (hci_pi(sk)->channel != channel) 230d7f72f61SMarcel Holtmann continue; 231d7f72f61SMarcel Holtmann 232d7f72f61SMarcel Holtmann nskb = skb_clone(skb, GFP_ATOMIC); 233d7f72f61SMarcel Holtmann if (!nskb) 234d7f72f61SMarcel Holtmann continue; 235d7f72f61SMarcel Holtmann 236d7f72f61SMarcel Holtmann if (sock_queue_rcv_skb(sk, nskb)) 237d7f72f61SMarcel Holtmann kfree_skb(nskb); 238d7f72f61SMarcel Holtmann } 239d7f72f61SMarcel Holtmann 240d7f72f61SMarcel Holtmann read_unlock(&hci_sk_list.lock); 241d7f72f61SMarcel Holtmann } 242d7f72f61SMarcel Holtmann 243cd82e61cSMarcel Holtmann /* Send frame to monitor socket */ 244cd82e61cSMarcel Holtmann void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) 245cd82e61cSMarcel Holtmann { 246cd82e61cSMarcel Holtmann struct sk_buff *skb_copy = NULL; 2472b531294SMarcel Holtmann struct hci_mon_hdr *hdr; 248cd82e61cSMarcel Holtmann __le16 opcode; 249cd82e61cSMarcel Holtmann 250cd82e61cSMarcel Holtmann if (!atomic_read(&monitor_promisc)) 251cd82e61cSMarcel Holtmann return; 252cd82e61cSMarcel Holtmann 253cd82e61cSMarcel Holtmann BT_DBG("hdev %p len %d", hdev, skb->len); 254cd82e61cSMarcel Holtmann 255cd82e61cSMarcel Holtmann switch (bt_cb(skb)->pkt_type) { 256cd82e61cSMarcel Holtmann case HCI_COMMAND_PKT: 257dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); 258cd82e61cSMarcel Holtmann break; 259cd82e61cSMarcel Holtmann case HCI_EVENT_PKT: 260dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_EVENT_PKT); 261cd82e61cSMarcel Holtmann break; 262cd82e61cSMarcel Holtmann case HCI_ACLDATA_PKT: 263cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 264dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); 265cd82e61cSMarcel Holtmann else 266dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); 267cd82e61cSMarcel Holtmann break; 268cd82e61cSMarcel Holtmann case HCI_SCODATA_PKT: 269cd82e61cSMarcel Holtmann if (bt_cb(skb)->incoming) 270dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); 271cd82e61cSMarcel Holtmann else 272dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); 273cd82e61cSMarcel Holtmann break; 274cd82e61cSMarcel Holtmann default: 275cd82e61cSMarcel Holtmann return; 276cd82e61cSMarcel Holtmann } 277cd82e61cSMarcel Holtmann 2782b531294SMarcel Holtmann /* Create a private copy with headroom */ 2792b531294SMarcel Holtmann skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true); 2802b531294SMarcel Holtmann if (!skb_copy) 2812b531294SMarcel Holtmann return; 2822b531294SMarcel Holtmann 2832b531294SMarcel Holtmann /* Put header before the data */ 2842b531294SMarcel Holtmann hdr = (void *) skb_push(skb_copy, HCI_MON_HDR_SIZE); 2852b531294SMarcel Holtmann hdr->opcode = opcode; 2862b531294SMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 2872b531294SMarcel Holtmann hdr->len = cpu_to_le16(skb->len); 2882b531294SMarcel Holtmann 289c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, 290c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 291cd82e61cSMarcel Holtmann kfree_skb(skb_copy); 292cd82e61cSMarcel Holtmann } 293cd82e61cSMarcel Holtmann 294cd82e61cSMarcel Holtmann static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) 295cd82e61cSMarcel Holtmann { 296cd82e61cSMarcel Holtmann struct hci_mon_hdr *hdr; 297cd82e61cSMarcel Holtmann struct hci_mon_new_index *ni; 298cd82e61cSMarcel Holtmann struct sk_buff *skb; 299cd82e61cSMarcel Holtmann __le16 opcode; 300cd82e61cSMarcel Holtmann 301cd82e61cSMarcel Holtmann switch (event) { 302cd82e61cSMarcel Holtmann case HCI_DEV_REG: 303cd82e61cSMarcel Holtmann skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC); 304cd82e61cSMarcel Holtmann if (!skb) 305cd82e61cSMarcel Holtmann return NULL; 306cd82e61cSMarcel Holtmann 307cd82e61cSMarcel Holtmann ni = (void *) skb_put(skb, HCI_MON_NEW_INDEX_SIZE); 308cd82e61cSMarcel Holtmann ni->type = hdev->dev_type; 309cd82e61cSMarcel Holtmann ni->bus = hdev->bus; 310cd82e61cSMarcel Holtmann bacpy(&ni->bdaddr, &hdev->bdaddr); 311cd82e61cSMarcel Holtmann memcpy(ni->name, hdev->name, 8); 312cd82e61cSMarcel Holtmann 313dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_NEW_INDEX); 314cd82e61cSMarcel Holtmann break; 315cd82e61cSMarcel Holtmann 316cd82e61cSMarcel Holtmann case HCI_DEV_UNREG: 317cd82e61cSMarcel Holtmann skb = bt_skb_alloc(0, GFP_ATOMIC); 318cd82e61cSMarcel Holtmann if (!skb) 319cd82e61cSMarcel Holtmann return NULL; 320cd82e61cSMarcel Holtmann 321dcf4adbfSJoe Perches opcode = cpu_to_le16(HCI_MON_DEL_INDEX); 322cd82e61cSMarcel Holtmann break; 323cd82e61cSMarcel Holtmann 324cd82e61cSMarcel Holtmann default: 325cd82e61cSMarcel Holtmann return NULL; 326cd82e61cSMarcel Holtmann } 327cd82e61cSMarcel Holtmann 328cd82e61cSMarcel Holtmann __net_timestamp(skb); 329cd82e61cSMarcel Holtmann 330cd82e61cSMarcel Holtmann hdr = (void *) skb_push(skb, HCI_MON_HDR_SIZE); 331cd82e61cSMarcel Holtmann hdr->opcode = opcode; 332cd82e61cSMarcel Holtmann hdr->index = cpu_to_le16(hdev->id); 333cd82e61cSMarcel Holtmann hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); 334cd82e61cSMarcel Holtmann 335cd82e61cSMarcel Holtmann return skb; 336cd82e61cSMarcel Holtmann } 337cd82e61cSMarcel Holtmann 338cd82e61cSMarcel Holtmann static void send_monitor_replay(struct sock *sk) 339cd82e61cSMarcel Holtmann { 340cd82e61cSMarcel Holtmann struct hci_dev *hdev; 341cd82e61cSMarcel Holtmann 342cd82e61cSMarcel Holtmann read_lock(&hci_dev_list_lock); 343cd82e61cSMarcel Holtmann 344cd82e61cSMarcel Holtmann list_for_each_entry(hdev, &hci_dev_list, list) { 345cd82e61cSMarcel Holtmann struct sk_buff *skb; 346cd82e61cSMarcel Holtmann 347cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, HCI_DEV_REG); 348cd82e61cSMarcel Holtmann if (!skb) 349cd82e61cSMarcel Holtmann continue; 350cd82e61cSMarcel Holtmann 351cd82e61cSMarcel Holtmann if (sock_queue_rcv_skb(sk, skb)) 352cd82e61cSMarcel Holtmann kfree_skb(skb); 353cd82e61cSMarcel Holtmann } 354cd82e61cSMarcel Holtmann 355cd82e61cSMarcel Holtmann read_unlock(&hci_dev_list_lock); 356cd82e61cSMarcel Holtmann } 357cd82e61cSMarcel Holtmann 358040030efSMarcel Holtmann /* Generate internal stack event */ 359040030efSMarcel Holtmann static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 360040030efSMarcel Holtmann { 361040030efSMarcel Holtmann struct hci_event_hdr *hdr; 362040030efSMarcel Holtmann struct hci_ev_stack_internal *ev; 363040030efSMarcel Holtmann struct sk_buff *skb; 364040030efSMarcel Holtmann 365040030efSMarcel Holtmann skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 366040030efSMarcel Holtmann if (!skb) 367040030efSMarcel Holtmann return; 368040030efSMarcel Holtmann 369040030efSMarcel Holtmann hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 370040030efSMarcel Holtmann hdr->evt = HCI_EV_STACK_INTERNAL; 371040030efSMarcel Holtmann hdr->plen = sizeof(*ev) + dlen; 372040030efSMarcel Holtmann 373040030efSMarcel Holtmann ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 374040030efSMarcel Holtmann ev->type = type; 375040030efSMarcel Holtmann memcpy(ev->data, data, dlen); 376040030efSMarcel Holtmann 377040030efSMarcel Holtmann bt_cb(skb)->incoming = 1; 378040030efSMarcel Holtmann __net_timestamp(skb); 379040030efSMarcel Holtmann 380040030efSMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 381040030efSMarcel Holtmann hci_send_to_sock(hdev, skb); 382040030efSMarcel Holtmann kfree_skb(skb); 383040030efSMarcel Holtmann } 384040030efSMarcel Holtmann 385040030efSMarcel Holtmann void hci_sock_dev_event(struct hci_dev *hdev, int event) 386040030efSMarcel Holtmann { 387040030efSMarcel Holtmann struct hci_ev_si_device ev; 388040030efSMarcel Holtmann 389040030efSMarcel Holtmann BT_DBG("hdev %s event %d", hdev->name, event); 390040030efSMarcel Holtmann 391cd82e61cSMarcel Holtmann /* Send event to monitor */ 392cd82e61cSMarcel Holtmann if (atomic_read(&monitor_promisc)) { 393cd82e61cSMarcel Holtmann struct sk_buff *skb; 394cd82e61cSMarcel Holtmann 395cd82e61cSMarcel Holtmann skb = create_monitor_event(hdev, event); 396cd82e61cSMarcel Holtmann if (skb) { 397c08b1a1dSMarcel Holtmann hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, 398c08b1a1dSMarcel Holtmann HCI_SOCK_TRUSTED, NULL); 399cd82e61cSMarcel Holtmann kfree_skb(skb); 400cd82e61cSMarcel Holtmann } 401cd82e61cSMarcel Holtmann } 402cd82e61cSMarcel Holtmann 403040030efSMarcel Holtmann /* Send event to sockets */ 404040030efSMarcel Holtmann ev.event = event; 405040030efSMarcel Holtmann ev.dev_id = hdev->id; 406040030efSMarcel Holtmann hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); 407040030efSMarcel Holtmann 408040030efSMarcel Holtmann if (event == HCI_DEV_UNREG) { 409040030efSMarcel Holtmann struct sock *sk; 410040030efSMarcel Holtmann 411040030efSMarcel Holtmann /* Detach sockets from device */ 412040030efSMarcel Holtmann read_lock(&hci_sk_list.lock); 413b67bfe0dSSasha Levin sk_for_each(sk, &hci_sk_list.head) { 414040030efSMarcel Holtmann bh_lock_sock_nested(sk); 415040030efSMarcel Holtmann if (hci_pi(sk)->hdev == hdev) { 416040030efSMarcel Holtmann hci_pi(sk)->hdev = NULL; 417040030efSMarcel Holtmann sk->sk_err = EPIPE; 418040030efSMarcel Holtmann sk->sk_state = BT_OPEN; 419040030efSMarcel Holtmann sk->sk_state_change(sk); 420040030efSMarcel Holtmann 421040030efSMarcel Holtmann hci_dev_put(hdev); 422040030efSMarcel Holtmann } 423040030efSMarcel Holtmann bh_unlock_sock(sk); 424040030efSMarcel Holtmann } 425040030efSMarcel Holtmann read_unlock(&hci_sk_list.lock); 426040030efSMarcel Holtmann } 427040030efSMarcel Holtmann } 428040030efSMarcel Holtmann 429801c1e8dSJohan Hedberg static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel) 430801c1e8dSJohan Hedberg { 431801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 432801c1e8dSJohan Hedberg 433801c1e8dSJohan Hedberg list_for_each_entry(c, &mgmt_chan_list, list) { 434801c1e8dSJohan Hedberg if (c->channel == channel) 435801c1e8dSJohan Hedberg return c; 436801c1e8dSJohan Hedberg } 437801c1e8dSJohan Hedberg 438801c1e8dSJohan Hedberg return NULL; 439801c1e8dSJohan Hedberg } 440801c1e8dSJohan Hedberg 441801c1e8dSJohan Hedberg static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel) 442801c1e8dSJohan Hedberg { 443801c1e8dSJohan Hedberg struct hci_mgmt_chan *c; 444801c1e8dSJohan Hedberg 445801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 446801c1e8dSJohan Hedberg c = __hci_mgmt_chan_find(channel); 447801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 448801c1e8dSJohan Hedberg 449801c1e8dSJohan Hedberg return c; 450801c1e8dSJohan Hedberg } 451801c1e8dSJohan Hedberg 452801c1e8dSJohan Hedberg int hci_mgmt_chan_register(struct hci_mgmt_chan *c) 453801c1e8dSJohan Hedberg { 454801c1e8dSJohan Hedberg if (c->channel < HCI_CHANNEL_CONTROL) 455801c1e8dSJohan Hedberg return -EINVAL; 456801c1e8dSJohan Hedberg 457801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 458801c1e8dSJohan Hedberg if (__hci_mgmt_chan_find(c->channel)) { 459801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 460801c1e8dSJohan Hedberg return -EALREADY; 461801c1e8dSJohan Hedberg } 462801c1e8dSJohan Hedberg 463801c1e8dSJohan Hedberg list_add_tail(&c->list, &mgmt_chan_list); 464801c1e8dSJohan Hedberg 465801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 466801c1e8dSJohan Hedberg 467801c1e8dSJohan Hedberg return 0; 468801c1e8dSJohan Hedberg } 469801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_register); 470801c1e8dSJohan Hedberg 471801c1e8dSJohan Hedberg void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c) 472801c1e8dSJohan Hedberg { 473801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 474801c1e8dSJohan Hedberg list_del(&c->list); 475801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 476801c1e8dSJohan Hedberg } 477801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_unregister); 478801c1e8dSJohan Hedberg 4791da177e4SLinus Torvalds static int hci_sock_release(struct socket *sock) 4801da177e4SLinus Torvalds { 4811da177e4SLinus Torvalds struct sock *sk = sock->sk; 4827b005bd3SMarcel Holtmann struct hci_dev *hdev; 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds if (!sk) 4871da177e4SLinus Torvalds return 0; 4881da177e4SLinus Torvalds 4897b005bd3SMarcel Holtmann hdev = hci_pi(sk)->hdev; 4907b005bd3SMarcel Holtmann 491cd82e61cSMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_MONITOR) 492cd82e61cSMarcel Holtmann atomic_dec(&monitor_promisc); 493cd82e61cSMarcel Holtmann 4941da177e4SLinus Torvalds bt_sock_unlink(&hci_sk_list, sk); 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds if (hdev) { 49723500189SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 49823500189SMarcel Holtmann mgmt_index_added(hdev); 499a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 50023500189SMarcel Holtmann hci_dev_close(hdev->id); 50123500189SMarcel Holtmann } 50223500189SMarcel Holtmann 5031da177e4SLinus Torvalds atomic_dec(&hdev->promisc); 5041da177e4SLinus Torvalds hci_dev_put(hdev); 5051da177e4SLinus Torvalds } 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds sock_orphan(sk); 5081da177e4SLinus Torvalds 5091da177e4SLinus Torvalds skb_queue_purge(&sk->sk_receive_queue); 5101da177e4SLinus Torvalds skb_queue_purge(&sk->sk_write_queue); 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds sock_put(sk); 5131da177e4SLinus Torvalds return 0; 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds 516b2a66aadSAntti Julku static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) 517f0358568SJohan Hedberg { 518f0358568SJohan Hedberg bdaddr_t bdaddr; 5195e762444SAntti Julku int err; 520f0358568SJohan Hedberg 521f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 522f0358568SJohan Hedberg return -EFAULT; 523f0358568SJohan Hedberg 52409fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 5255e762444SAntti Julku 526dcc36c16SJohan Hedberg err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 5275e762444SAntti Julku 52809fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 5295e762444SAntti Julku 5305e762444SAntti Julku return err; 531f0358568SJohan Hedberg } 532f0358568SJohan Hedberg 533b2a66aadSAntti Julku static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) 534f0358568SJohan Hedberg { 535f0358568SJohan Hedberg bdaddr_t bdaddr; 5365e762444SAntti Julku int err; 537f0358568SJohan Hedberg 538f0358568SJohan Hedberg if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 539f0358568SJohan Hedberg return -EFAULT; 540f0358568SJohan Hedberg 54109fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 5425e762444SAntti Julku 543dcc36c16SJohan Hedberg err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR); 5445e762444SAntti Julku 54509fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 5465e762444SAntti Julku 5475e762444SAntti Julku return err; 548f0358568SJohan Hedberg } 549f0358568SJohan Hedberg 5501da177e4SLinus Torvalds /* Ioctls that require bound socket */ 5516039aa73SGustavo Padovan static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, 5526039aa73SGustavo Padovan unsigned long arg) 5531da177e4SLinus Torvalds { 5541da177e4SLinus Torvalds struct hci_dev *hdev = hci_pi(sk)->hdev; 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds if (!hdev) 5571da177e4SLinus Torvalds return -EBADFD; 5581da177e4SLinus Torvalds 559d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) 5600736cfa8SMarcel Holtmann return -EBUSY; 5610736cfa8SMarcel Holtmann 562d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 563fee746b0SMarcel Holtmann return -EOPNOTSUPP; 564fee746b0SMarcel Holtmann 5655b69bef5SMarcel Holtmann if (hdev->dev_type != HCI_BREDR) 5665b69bef5SMarcel Holtmann return -EOPNOTSUPP; 5675b69bef5SMarcel Holtmann 5681da177e4SLinus Torvalds switch (cmd) { 5691da177e4SLinus Torvalds case HCISETRAW: 5701da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 571bf5b30b8SZhao Hongjiang return -EPERM; 572db596681SMarcel Holtmann return -EOPNOTSUPP; 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds case HCIGETCONNINFO: 5751da177e4SLinus Torvalds return hci_get_conn_info(hdev, (void __user *) arg); 5761da177e4SLinus Torvalds 57740be492fSMarcel Holtmann case HCIGETAUTHINFO: 57840be492fSMarcel Holtmann return hci_get_auth_info(hdev, (void __user *) arg); 57940be492fSMarcel Holtmann 580f0358568SJohan Hedberg case HCIBLOCKADDR: 581f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 582bf5b30b8SZhao Hongjiang return -EPERM; 583b2a66aadSAntti Julku return hci_sock_blacklist_add(hdev, (void __user *) arg); 584f0358568SJohan Hedberg 585f0358568SJohan Hedberg case HCIUNBLOCKADDR: 586f0358568SJohan Hedberg if (!capable(CAP_NET_ADMIN)) 587bf5b30b8SZhao Hongjiang return -EPERM; 588b2a66aadSAntti Julku return hci_sock_blacklist_del(hdev, (void __user *) arg); 5890736cfa8SMarcel Holtmann } 590f0358568SJohan Hedberg 591324d36edSMarcel Holtmann return -ENOIOCTLCMD; 5921da177e4SLinus Torvalds } 5931da177e4SLinus Torvalds 5948fc9ced3SGustavo Padovan static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, 5958fc9ced3SGustavo Padovan unsigned long arg) 5961da177e4SLinus Torvalds { 5971da177e4SLinus Torvalds void __user *argp = (void __user *) arg; 5980736cfa8SMarcel Holtmann struct sock *sk = sock->sk; 5991da177e4SLinus Torvalds int err; 6001da177e4SLinus Torvalds 6011da177e4SLinus Torvalds BT_DBG("cmd %x arg %lx", cmd, arg); 6021da177e4SLinus Torvalds 603c1c4f956SMarcel Holtmann lock_sock(sk); 604c1c4f956SMarcel Holtmann 605c1c4f956SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 606c1c4f956SMarcel Holtmann err = -EBADFD; 607c1c4f956SMarcel Holtmann goto done; 608c1c4f956SMarcel Holtmann } 609c1c4f956SMarcel Holtmann 610c1c4f956SMarcel Holtmann release_sock(sk); 611c1c4f956SMarcel Holtmann 6121da177e4SLinus Torvalds switch (cmd) { 6131da177e4SLinus Torvalds case HCIGETDEVLIST: 6141da177e4SLinus Torvalds return hci_get_dev_list(argp); 6151da177e4SLinus Torvalds 6161da177e4SLinus Torvalds case HCIGETDEVINFO: 6171da177e4SLinus Torvalds return hci_get_dev_info(argp); 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds case HCIGETCONNLIST: 6201da177e4SLinus Torvalds return hci_get_conn_list(argp); 6211da177e4SLinus Torvalds 6221da177e4SLinus Torvalds case HCIDEVUP: 6231da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 624bf5b30b8SZhao Hongjiang return -EPERM; 6251da177e4SLinus Torvalds return hci_dev_open(arg); 6261da177e4SLinus Torvalds 6271da177e4SLinus Torvalds case HCIDEVDOWN: 6281da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 629bf5b30b8SZhao Hongjiang return -EPERM; 6301da177e4SLinus Torvalds return hci_dev_close(arg); 6311da177e4SLinus Torvalds 6321da177e4SLinus Torvalds case HCIDEVRESET: 6331da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 634bf5b30b8SZhao Hongjiang return -EPERM; 6351da177e4SLinus Torvalds return hci_dev_reset(arg); 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds case HCIDEVRESTAT: 6381da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 639bf5b30b8SZhao Hongjiang return -EPERM; 6401da177e4SLinus Torvalds return hci_dev_reset_stat(arg); 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds case HCISETSCAN: 6431da177e4SLinus Torvalds case HCISETAUTH: 6441da177e4SLinus Torvalds case HCISETENCRYPT: 6451da177e4SLinus Torvalds case HCISETPTYPE: 6461da177e4SLinus Torvalds case HCISETLINKPOL: 6471da177e4SLinus Torvalds case HCISETLINKMODE: 6481da177e4SLinus Torvalds case HCISETACLMTU: 6491da177e4SLinus Torvalds case HCISETSCOMTU: 6501da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 651bf5b30b8SZhao Hongjiang return -EPERM; 6521da177e4SLinus Torvalds return hci_dev_cmd(cmd, argp); 6531da177e4SLinus Torvalds 6541da177e4SLinus Torvalds case HCIINQUIRY: 6551da177e4SLinus Torvalds return hci_inquiry(argp); 656c1c4f956SMarcel Holtmann } 6571da177e4SLinus Torvalds 6581da177e4SLinus Torvalds lock_sock(sk); 659c1c4f956SMarcel Holtmann 6601da177e4SLinus Torvalds err = hci_sock_bound_ioctl(sk, cmd, arg); 661c1c4f956SMarcel Holtmann 662c1c4f956SMarcel Holtmann done: 6631da177e4SLinus Torvalds release_sock(sk); 6641da177e4SLinus Torvalds return err; 6651da177e4SLinus Torvalds } 6661da177e4SLinus Torvalds 6678fc9ced3SGustavo Padovan static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, 6688fc9ced3SGustavo Padovan int addr_len) 6691da177e4SLinus Torvalds { 6700381101fSJohan Hedberg struct sockaddr_hci haddr; 6711da177e4SLinus Torvalds struct sock *sk = sock->sk; 6721da177e4SLinus Torvalds struct hci_dev *hdev = NULL; 6730381101fSJohan Hedberg int len, err = 0; 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 6761da177e4SLinus Torvalds 6770381101fSJohan Hedberg if (!addr) 6780381101fSJohan Hedberg return -EINVAL; 6790381101fSJohan Hedberg 6800381101fSJohan Hedberg memset(&haddr, 0, sizeof(haddr)); 6810381101fSJohan Hedberg len = min_t(unsigned int, sizeof(haddr), addr_len); 6820381101fSJohan Hedberg memcpy(&haddr, addr, len); 6830381101fSJohan Hedberg 6840381101fSJohan Hedberg if (haddr.hci_family != AF_BLUETOOTH) 6850381101fSJohan Hedberg return -EINVAL; 6860381101fSJohan Hedberg 6871da177e4SLinus Torvalds lock_sock(sk); 6881da177e4SLinus Torvalds 6897cc2ade2SMarcel Holtmann if (sk->sk_state == BT_BOUND) { 6907cc2ade2SMarcel Holtmann err = -EALREADY; 6917cc2ade2SMarcel Holtmann goto done; 6927cc2ade2SMarcel Holtmann } 6937cc2ade2SMarcel Holtmann 6947cc2ade2SMarcel Holtmann switch (haddr.hci_channel) { 6957cc2ade2SMarcel Holtmann case HCI_CHANNEL_RAW: 6967cc2ade2SMarcel Holtmann if (hci_pi(sk)->hdev) { 6971da177e4SLinus Torvalds err = -EALREADY; 6981da177e4SLinus Torvalds goto done; 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds 7010381101fSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 7020381101fSJohan Hedberg hdev = hci_dev_get(haddr.hci_dev); 70370f23020SAndrei Emeltchenko if (!hdev) { 7041da177e4SLinus Torvalds err = -ENODEV; 7051da177e4SLinus Torvalds goto done; 7061da177e4SLinus Torvalds } 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds atomic_inc(&hdev->promisc); 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds hci_pi(sk)->hdev = hdev; 7127cc2ade2SMarcel Holtmann break; 7137cc2ade2SMarcel Holtmann 71423500189SMarcel Holtmann case HCI_CHANNEL_USER: 71523500189SMarcel Holtmann if (hci_pi(sk)->hdev) { 71623500189SMarcel Holtmann err = -EALREADY; 71723500189SMarcel Holtmann goto done; 71823500189SMarcel Holtmann } 71923500189SMarcel Holtmann 72023500189SMarcel Holtmann if (haddr.hci_dev == HCI_DEV_NONE) { 72123500189SMarcel Holtmann err = -EINVAL; 72223500189SMarcel Holtmann goto done; 72323500189SMarcel Holtmann } 72423500189SMarcel Holtmann 72510a8b86fSMarcel Holtmann if (!capable(CAP_NET_ADMIN)) { 72623500189SMarcel Holtmann err = -EPERM; 72723500189SMarcel Holtmann goto done; 72823500189SMarcel Holtmann } 72923500189SMarcel Holtmann 73023500189SMarcel Holtmann hdev = hci_dev_get(haddr.hci_dev); 73123500189SMarcel Holtmann if (!hdev) { 73223500189SMarcel Holtmann err = -ENODEV; 73323500189SMarcel Holtmann goto done; 73423500189SMarcel Holtmann } 73523500189SMarcel Holtmann 73623500189SMarcel Holtmann if (test_bit(HCI_UP, &hdev->flags) || 73723500189SMarcel Holtmann test_bit(HCI_INIT, &hdev->flags) || 738d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_SETUP) || 739d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG)) { 74023500189SMarcel Holtmann err = -EBUSY; 74123500189SMarcel Holtmann hci_dev_put(hdev); 74223500189SMarcel Holtmann goto done; 74323500189SMarcel Holtmann } 74423500189SMarcel Holtmann 745238be788SMarcel Holtmann if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) { 74623500189SMarcel Holtmann err = -EUSERS; 74723500189SMarcel Holtmann hci_dev_put(hdev); 74823500189SMarcel Holtmann goto done; 74923500189SMarcel Holtmann } 75023500189SMarcel Holtmann 75123500189SMarcel Holtmann mgmt_index_removed(hdev); 75223500189SMarcel Holtmann 75323500189SMarcel Holtmann err = hci_dev_open(hdev->id); 75423500189SMarcel Holtmann if (err) { 755a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); 756c6521401SMarcel Holtmann mgmt_index_added(hdev); 75723500189SMarcel Holtmann hci_dev_put(hdev); 75823500189SMarcel Holtmann goto done; 75923500189SMarcel Holtmann } 76023500189SMarcel Holtmann 76123500189SMarcel Holtmann atomic_inc(&hdev->promisc); 76223500189SMarcel Holtmann 76323500189SMarcel Holtmann hci_pi(sk)->hdev = hdev; 76423500189SMarcel Holtmann break; 76523500189SMarcel Holtmann 766cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 767cd82e61cSMarcel Holtmann if (haddr.hci_dev != HCI_DEV_NONE) { 768cd82e61cSMarcel Holtmann err = -EINVAL; 769cd82e61cSMarcel Holtmann goto done; 770cd82e61cSMarcel Holtmann } 771cd82e61cSMarcel Holtmann 772cd82e61cSMarcel Holtmann if (!capable(CAP_NET_RAW)) { 773cd82e61cSMarcel Holtmann err = -EPERM; 774cd82e61cSMarcel Holtmann goto done; 775cd82e61cSMarcel Holtmann } 776cd82e61cSMarcel Holtmann 77750ebc055SMarcel Holtmann /* The monitor interface is restricted to CAP_NET_RAW 77850ebc055SMarcel Holtmann * capabilities and with that implicitly trusted. 77950ebc055SMarcel Holtmann */ 78050ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 78150ebc055SMarcel Holtmann 782cd82e61cSMarcel Holtmann send_monitor_replay(sk); 783cd82e61cSMarcel Holtmann 784cd82e61cSMarcel Holtmann atomic_inc(&monitor_promisc); 785cd82e61cSMarcel Holtmann break; 786cd82e61cSMarcel Holtmann 7877cc2ade2SMarcel Holtmann default: 788801c1e8dSJohan Hedberg if (!hci_mgmt_chan_find(haddr.hci_channel)) { 7897cc2ade2SMarcel Holtmann err = -EINVAL; 7907cc2ade2SMarcel Holtmann goto done; 7917cc2ade2SMarcel Holtmann } 7927cc2ade2SMarcel Holtmann 793801c1e8dSJohan Hedberg if (haddr.hci_dev != HCI_DEV_NONE) { 794801c1e8dSJohan Hedberg err = -EINVAL; 795801c1e8dSJohan Hedberg goto done; 796801c1e8dSJohan Hedberg } 797801c1e8dSJohan Hedberg 798*1195fbb8SMarcel Holtmann /* Users with CAP_NET_ADMIN capabilities are allowed 799*1195fbb8SMarcel Holtmann * access to all management commands and events. For 800*1195fbb8SMarcel Holtmann * untrusted users the interface is restricted and 801*1195fbb8SMarcel Holtmann * also only untrusted events are sent. 80250ebc055SMarcel Holtmann */ 803*1195fbb8SMarcel Holtmann if (capable(CAP_NET_ADMIN)) 80450ebc055SMarcel Holtmann hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); 80550ebc055SMarcel Holtmann 806f9207338SMarcel Holtmann /* At the moment the index and unconfigured index events 807f9207338SMarcel Holtmann * are enabled unconditionally. Setting them on each 808f9207338SMarcel Holtmann * socket when binding keeps this functionality. They 809f9207338SMarcel Holtmann * however might be cleared later and then sending of these 810f9207338SMarcel Holtmann * events will be disabled, but that is then intentional. 811f9207338SMarcel Holtmann */ 812f9207338SMarcel Holtmann if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { 813f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); 814f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); 815f9207338SMarcel Holtmann } 816801c1e8dSJohan Hedberg break; 817801c1e8dSJohan Hedberg } 818801c1e8dSJohan Hedberg 8197cc2ade2SMarcel Holtmann 8207cc2ade2SMarcel Holtmann hci_pi(sk)->channel = haddr.hci_channel; 8211da177e4SLinus Torvalds sk->sk_state = BT_BOUND; 8221da177e4SLinus Torvalds 8231da177e4SLinus Torvalds done: 8241da177e4SLinus Torvalds release_sock(sk); 8251da177e4SLinus Torvalds return err; 8261da177e4SLinus Torvalds } 8271da177e4SLinus Torvalds 8288fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, 8298fc9ced3SGustavo Padovan int *addr_len, int peer) 8301da177e4SLinus Torvalds { 8311da177e4SLinus Torvalds struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 8321da177e4SLinus Torvalds struct sock *sk = sock->sk; 8339d4b68b2SMarcel Holtmann struct hci_dev *hdev; 8349d4b68b2SMarcel Holtmann int err = 0; 8351da177e4SLinus Torvalds 8361da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 8371da177e4SLinus Torvalds 83806f43cbcSMarcel Holtmann if (peer) 83906f43cbcSMarcel Holtmann return -EOPNOTSUPP; 84006f43cbcSMarcel Holtmann 8411da177e4SLinus Torvalds lock_sock(sk); 8421da177e4SLinus Torvalds 8439d4b68b2SMarcel Holtmann hdev = hci_pi(sk)->hdev; 8449d4b68b2SMarcel Holtmann if (!hdev) { 8459d4b68b2SMarcel Holtmann err = -EBADFD; 8469d4b68b2SMarcel Holtmann goto done; 8479d4b68b2SMarcel Holtmann } 8489d4b68b2SMarcel Holtmann 8491da177e4SLinus Torvalds *addr_len = sizeof(*haddr); 8501da177e4SLinus Torvalds haddr->hci_family = AF_BLUETOOTH; 8517b005bd3SMarcel Holtmann haddr->hci_dev = hdev->id; 8529d4b68b2SMarcel Holtmann haddr->hci_channel= hci_pi(sk)->channel; 8531da177e4SLinus Torvalds 8549d4b68b2SMarcel Holtmann done: 8551da177e4SLinus Torvalds release_sock(sk); 8569d4b68b2SMarcel Holtmann return err; 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds 8596039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, 8606039aa73SGustavo Padovan struct sk_buff *skb) 8611da177e4SLinus Torvalds { 8621da177e4SLinus Torvalds __u32 mask = hci_pi(sk)->cmsg_mask; 8631da177e4SLinus Torvalds 8640d48d939SMarcel Holtmann if (mask & HCI_CMSG_DIR) { 8650d48d939SMarcel Holtmann int incoming = bt_cb(skb)->incoming; 8668fc9ced3SGustavo Padovan put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), 8678fc9ced3SGustavo Padovan &incoming); 8680d48d939SMarcel Holtmann } 8691da177e4SLinus Torvalds 870a61bbcf2SPatrick McHardy if (mask & HCI_CMSG_TSTAMP) { 871f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT 872f6e623a6SJohann Felix Soden struct compat_timeval ctv; 873f6e623a6SJohann Felix Soden #endif 874a61bbcf2SPatrick McHardy struct timeval tv; 875767c5eb5SMarcel Holtmann void *data; 876767c5eb5SMarcel Holtmann int len; 877a61bbcf2SPatrick McHardy 878a61bbcf2SPatrick McHardy skb_get_timestamp(skb, &tv); 879767c5eb5SMarcel Holtmann 8801da97f83SDavid S. Miller data = &tv; 8811da97f83SDavid S. Miller len = sizeof(tv); 8821da97f83SDavid S. Miller #ifdef CONFIG_COMPAT 883da88cea1SH. J. Lu if (!COMPAT_USE_64BIT_TIME && 884da88cea1SH. J. Lu (msg->msg_flags & MSG_CMSG_COMPAT)) { 885767c5eb5SMarcel Holtmann ctv.tv_sec = tv.tv_sec; 886767c5eb5SMarcel Holtmann ctv.tv_usec = tv.tv_usec; 887767c5eb5SMarcel Holtmann data = &ctv; 888767c5eb5SMarcel Holtmann len = sizeof(ctv); 889767c5eb5SMarcel Holtmann } 8901da97f83SDavid S. Miller #endif 891767c5eb5SMarcel Holtmann 892767c5eb5SMarcel Holtmann put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 893a61bbcf2SPatrick McHardy } 8941da177e4SLinus Torvalds } 8951da177e4SLinus Torvalds 8961b784140SYing Xue static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 8971b784140SYing Xue int flags) 8981da177e4SLinus Torvalds { 8991da177e4SLinus Torvalds int noblock = flags & MSG_DONTWAIT; 9001da177e4SLinus Torvalds struct sock *sk = sock->sk; 9011da177e4SLinus Torvalds struct sk_buff *skb; 9021da177e4SLinus Torvalds int copied, err; 9031da177e4SLinus Torvalds 9041da177e4SLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds if (flags & (MSG_OOB)) 9071da177e4SLinus Torvalds return -EOPNOTSUPP; 9081da177e4SLinus Torvalds 9091da177e4SLinus Torvalds if (sk->sk_state == BT_CLOSED) 9101da177e4SLinus Torvalds return 0; 9111da177e4SLinus Torvalds 91270f23020SAndrei Emeltchenko skb = skb_recv_datagram(sk, flags, noblock, &err); 91370f23020SAndrei Emeltchenko if (!skb) 9141da177e4SLinus Torvalds return err; 9151da177e4SLinus Torvalds 9161da177e4SLinus Torvalds copied = skb->len; 9171da177e4SLinus Torvalds if (len < copied) { 9181da177e4SLinus Torvalds msg->msg_flags |= MSG_TRUNC; 9191da177e4SLinus Torvalds copied = len; 9201da177e4SLinus Torvalds } 9211da177e4SLinus Torvalds 922badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb); 92351f3d02bSDavid S. Miller err = skb_copy_datagram_msg(skb, 0, msg, copied); 9241da177e4SLinus Torvalds 9253a208627SMarcel Holtmann switch (hci_pi(sk)->channel) { 9263a208627SMarcel Holtmann case HCI_CHANNEL_RAW: 9271da177e4SLinus Torvalds hci_sock_cmsg(sk, msg, skb); 9283a208627SMarcel Holtmann break; 92923500189SMarcel Holtmann case HCI_CHANNEL_USER: 930cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 931cd82e61cSMarcel Holtmann sock_recv_timestamp(msg, sk, skb); 932cd82e61cSMarcel Holtmann break; 933801c1e8dSJohan Hedberg default: 934801c1e8dSJohan Hedberg if (hci_mgmt_chan_find(hci_pi(sk)->channel)) 935801c1e8dSJohan Hedberg sock_recv_timestamp(msg, sk, skb); 936801c1e8dSJohan Hedberg break; 9373a208627SMarcel Holtmann } 9381da177e4SLinus Torvalds 9391da177e4SLinus Torvalds skb_free_datagram(sk, skb); 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds return err ? : copied; 9421da177e4SLinus Torvalds } 9431da177e4SLinus Torvalds 9441b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, 9451b784140SYing Xue size_t len) 9461da177e4SLinus Torvalds { 9471da177e4SLinus Torvalds struct sock *sk = sock->sk; 948801c1e8dSJohan Hedberg struct hci_mgmt_chan *chan; 9491da177e4SLinus Torvalds struct hci_dev *hdev; 9501da177e4SLinus Torvalds struct sk_buff *skb; 9511da177e4SLinus Torvalds int err; 9521da177e4SLinus Torvalds 9531da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 9541da177e4SLinus Torvalds 9551da177e4SLinus Torvalds if (msg->msg_flags & MSG_OOB) 9561da177e4SLinus Torvalds return -EOPNOTSUPP; 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 9591da177e4SLinus Torvalds return -EINVAL; 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds if (len < 4 || len > HCI_MAX_FRAME_SIZE) 9621da177e4SLinus Torvalds return -EINVAL; 9631da177e4SLinus Torvalds 9641da177e4SLinus Torvalds lock_sock(sk); 9651da177e4SLinus Torvalds 9660381101fSJohan Hedberg switch (hci_pi(sk)->channel) { 9670381101fSJohan Hedberg case HCI_CHANNEL_RAW: 96823500189SMarcel Holtmann case HCI_CHANNEL_USER: 9690381101fSJohan Hedberg break; 970cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 971cd82e61cSMarcel Holtmann err = -EOPNOTSUPP; 972cd82e61cSMarcel Holtmann goto done; 9730381101fSJohan Hedberg default: 974801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 975801c1e8dSJohan Hedberg chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); 976801c1e8dSJohan Hedberg if (chan) 9776d785aa3SJohan Hedberg err = mgmt_control(chan, sk, msg, len); 978801c1e8dSJohan Hedberg else 9790381101fSJohan Hedberg err = -EINVAL; 980801c1e8dSJohan Hedberg 981801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 9820381101fSJohan Hedberg goto done; 9830381101fSJohan Hedberg } 9840381101fSJohan Hedberg 98570f23020SAndrei Emeltchenko hdev = hci_pi(sk)->hdev; 98670f23020SAndrei Emeltchenko if (!hdev) { 9871da177e4SLinus Torvalds err = -EBADFD; 9881da177e4SLinus Torvalds goto done; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds 9917e21addcSMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) { 9927e21addcSMarcel Holtmann err = -ENETDOWN; 9937e21addcSMarcel Holtmann goto done; 9947e21addcSMarcel Holtmann } 9957e21addcSMarcel Holtmann 99670f23020SAndrei Emeltchenko skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 99770f23020SAndrei Emeltchenko if (!skb) 9981da177e4SLinus Torvalds goto done; 9991da177e4SLinus Torvalds 10006ce8e9ceSAl Viro if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 10011da177e4SLinus Torvalds err = -EFAULT; 10021da177e4SLinus Torvalds goto drop; 10031da177e4SLinus Torvalds } 10041da177e4SLinus Torvalds 10050d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); 10061da177e4SLinus Torvalds skb_pull(skb, 1); 10071da177e4SLinus Torvalds 10081bc5ad16SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 10091bc5ad16SMarcel Holtmann /* No permission check is needed for user channel 10101bc5ad16SMarcel Holtmann * since that gets enforced when binding the socket. 10111bc5ad16SMarcel Holtmann * 10121bc5ad16SMarcel Holtmann * However check that the packet type is valid. 10131bc5ad16SMarcel Holtmann */ 10141bc5ad16SMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT && 10151bc5ad16SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && 10161bc5ad16SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { 10171bc5ad16SMarcel Holtmann err = -EINVAL; 10181bc5ad16SMarcel Holtmann goto drop; 10191bc5ad16SMarcel Holtmann } 10201bc5ad16SMarcel Holtmann 10211bc5ad16SMarcel Holtmann skb_queue_tail(&hdev->raw_q, skb); 10221bc5ad16SMarcel Holtmann queue_work(hdev->workqueue, &hdev->tx_work); 10231bc5ad16SMarcel Holtmann } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { 102483985319SHarvey Harrison u16 opcode = get_unaligned_le16(skb->data); 10251da177e4SLinus Torvalds u16 ogf = hci_opcode_ogf(opcode); 10261da177e4SLinus Torvalds u16 ocf = hci_opcode_ocf(opcode); 10271da177e4SLinus Torvalds 10281da177e4SLinus Torvalds if (((ogf > HCI_SFLT_MAX_OGF) || 10293bb3c755SGustavo Padovan !hci_test_bit(ocf & HCI_FLT_OCF_BITS, 10303bb3c755SGustavo Padovan &hci_sec_filter.ocf_mask[ogf])) && 10311da177e4SLinus Torvalds !capable(CAP_NET_RAW)) { 10321da177e4SLinus Torvalds err = -EPERM; 10331da177e4SLinus Torvalds goto drop; 10341da177e4SLinus Torvalds } 10351da177e4SLinus Torvalds 1036fee746b0SMarcel Holtmann if (ogf == 0x3f) { 10371da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 10383eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 10391da177e4SLinus Torvalds } else { 104049c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as 104111714b3dSJohan Hedberg * single-command requests. 104211714b3dSJohan Hedberg */ 10436368c235SEyal Birger bt_cb(skb)->req_start = 1; 104411714b3dSJohan Hedberg 10451da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb); 1046c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 10471da177e4SLinus Torvalds } 10481da177e4SLinus Torvalds } else { 10491da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 10501da177e4SLinus Torvalds err = -EPERM; 10511da177e4SLinus Torvalds goto drop; 10521da177e4SLinus Torvalds } 10531da177e4SLinus Torvalds 10541da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 10553eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 10561da177e4SLinus Torvalds } 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds err = len; 10591da177e4SLinus Torvalds 10601da177e4SLinus Torvalds done: 10611da177e4SLinus Torvalds release_sock(sk); 10621da177e4SLinus Torvalds return err; 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds drop: 10651da177e4SLinus Torvalds kfree_skb(skb); 10661da177e4SLinus Torvalds goto done; 10671da177e4SLinus Torvalds } 10681da177e4SLinus Torvalds 10698fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname, 10708fc9ced3SGustavo Padovan char __user *optval, unsigned int len) 10711da177e4SLinus Torvalds { 10721da177e4SLinus Torvalds struct hci_ufilter uf = { .opcode = 0 }; 10731da177e4SLinus Torvalds struct sock *sk = sock->sk; 10741da177e4SLinus Torvalds int err = 0, opt = 0; 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds BT_DBG("sk %p, opt %d", sk, optname); 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds lock_sock(sk); 10791da177e4SLinus Torvalds 10802f39cdb7SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1081c2371e80SMarcel Holtmann err = -EBADFD; 10822f39cdb7SMarcel Holtmann goto done; 10832f39cdb7SMarcel Holtmann } 10842f39cdb7SMarcel Holtmann 10851da177e4SLinus Torvalds switch (optname) { 10861da177e4SLinus Torvalds case HCI_DATA_DIR: 10871da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 10881da177e4SLinus Torvalds err = -EFAULT; 10891da177e4SLinus Torvalds break; 10901da177e4SLinus Torvalds } 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds if (opt) 10931da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 10941da177e4SLinus Torvalds else 10951da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 10961da177e4SLinus Torvalds break; 10971da177e4SLinus Torvalds 10981da177e4SLinus Torvalds case HCI_TIME_STAMP: 10991da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 11001da177e4SLinus Torvalds err = -EFAULT; 11011da177e4SLinus Torvalds break; 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds if (opt) 11051da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 11061da177e4SLinus Torvalds else 11071da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 11081da177e4SLinus Torvalds break; 11091da177e4SLinus Torvalds 11101da177e4SLinus Torvalds case HCI_FILTER: 11110878b666SMarcel Holtmann { 11120878b666SMarcel Holtmann struct hci_filter *f = &hci_pi(sk)->filter; 11130878b666SMarcel Holtmann 11140878b666SMarcel Holtmann uf.type_mask = f->type_mask; 11150878b666SMarcel Holtmann uf.opcode = f->opcode; 11160878b666SMarcel Holtmann uf.event_mask[0] = *((u32 *) f->event_mask + 0); 11170878b666SMarcel Holtmann uf.event_mask[1] = *((u32 *) f->event_mask + 1); 11180878b666SMarcel Holtmann } 11190878b666SMarcel Holtmann 11201da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 11211da177e4SLinus Torvalds if (copy_from_user(&uf, optval, len)) { 11221da177e4SLinus Torvalds err = -EFAULT; 11231da177e4SLinus Torvalds break; 11241da177e4SLinus Torvalds } 11251da177e4SLinus Torvalds 11261da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 11271da177e4SLinus Torvalds uf.type_mask &= hci_sec_filter.type_mask; 11281da177e4SLinus Torvalds uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 11291da177e4SLinus Torvalds uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 11301da177e4SLinus Torvalds } 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds { 11331da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds f->type_mask = uf.type_mask; 11361da177e4SLinus Torvalds f->opcode = uf.opcode; 11371da177e4SLinus Torvalds *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 11381da177e4SLinus Torvalds *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 11391da177e4SLinus Torvalds } 11401da177e4SLinus Torvalds break; 11411da177e4SLinus Torvalds 11421da177e4SLinus Torvalds default: 11431da177e4SLinus Torvalds err = -ENOPROTOOPT; 11441da177e4SLinus Torvalds break; 11451da177e4SLinus Torvalds } 11461da177e4SLinus Torvalds 11472f39cdb7SMarcel Holtmann done: 11481da177e4SLinus Torvalds release_sock(sk); 11491da177e4SLinus Torvalds return err; 11501da177e4SLinus Torvalds } 11511da177e4SLinus Torvalds 11528fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname, 11538fc9ced3SGustavo Padovan char __user *optval, int __user *optlen) 11541da177e4SLinus Torvalds { 11551da177e4SLinus Torvalds struct hci_ufilter uf; 11561da177e4SLinus Torvalds struct sock *sk = sock->sk; 1157cedc5469SMarcel Holtmann int len, opt, err = 0; 1158cedc5469SMarcel Holtmann 1159cedc5469SMarcel Holtmann BT_DBG("sk %p, opt %d", sk, optname); 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds if (get_user(len, optlen)) 11621da177e4SLinus Torvalds return -EFAULT; 11631da177e4SLinus Torvalds 1164cedc5469SMarcel Holtmann lock_sock(sk); 1165cedc5469SMarcel Holtmann 1166cedc5469SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1167c2371e80SMarcel Holtmann err = -EBADFD; 1168cedc5469SMarcel Holtmann goto done; 1169cedc5469SMarcel Holtmann } 1170cedc5469SMarcel Holtmann 11711da177e4SLinus Torvalds switch (optname) { 11721da177e4SLinus Torvalds case HCI_DATA_DIR: 11731da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 11741da177e4SLinus Torvalds opt = 1; 11751da177e4SLinus Torvalds else 11761da177e4SLinus Torvalds opt = 0; 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds if (put_user(opt, optval)) 1179cedc5469SMarcel Holtmann err = -EFAULT; 11801da177e4SLinus Torvalds break; 11811da177e4SLinus Torvalds 11821da177e4SLinus Torvalds case HCI_TIME_STAMP: 11831da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 11841da177e4SLinus Torvalds opt = 1; 11851da177e4SLinus Torvalds else 11861da177e4SLinus Torvalds opt = 0; 11871da177e4SLinus Torvalds 11881da177e4SLinus Torvalds if (put_user(opt, optval)) 1189cedc5469SMarcel Holtmann err = -EFAULT; 11901da177e4SLinus Torvalds break; 11911da177e4SLinus Torvalds 11921da177e4SLinus Torvalds case HCI_FILTER: 11931da177e4SLinus Torvalds { 11941da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 11951da177e4SLinus Torvalds 1196e15ca9a0SMathias Krause memset(&uf, 0, sizeof(uf)); 11971da177e4SLinus Torvalds uf.type_mask = f->type_mask; 11981da177e4SLinus Torvalds uf.opcode = f->opcode; 11991da177e4SLinus Torvalds uf.event_mask[0] = *((u32 *) f->event_mask + 0); 12001da177e4SLinus Torvalds uf.event_mask[1] = *((u32 *) f->event_mask + 1); 12011da177e4SLinus Torvalds } 12021da177e4SLinus Torvalds 12031da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 12041da177e4SLinus Torvalds if (copy_to_user(optval, &uf, len)) 1205cedc5469SMarcel Holtmann err = -EFAULT; 12061da177e4SLinus Torvalds break; 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds default: 1209cedc5469SMarcel Holtmann err = -ENOPROTOOPT; 12101da177e4SLinus Torvalds break; 12111da177e4SLinus Torvalds } 12121da177e4SLinus Torvalds 1213cedc5469SMarcel Holtmann done: 1214cedc5469SMarcel Holtmann release_sock(sk); 1215cedc5469SMarcel Holtmann return err; 12161da177e4SLinus Torvalds } 12171da177e4SLinus Torvalds 121890ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = { 12191da177e4SLinus Torvalds .family = PF_BLUETOOTH, 12201da177e4SLinus Torvalds .owner = THIS_MODULE, 12211da177e4SLinus Torvalds .release = hci_sock_release, 12221da177e4SLinus Torvalds .bind = hci_sock_bind, 12231da177e4SLinus Torvalds .getname = hci_sock_getname, 12241da177e4SLinus Torvalds .sendmsg = hci_sock_sendmsg, 12251da177e4SLinus Torvalds .recvmsg = hci_sock_recvmsg, 12261da177e4SLinus Torvalds .ioctl = hci_sock_ioctl, 12271da177e4SLinus Torvalds .poll = datagram_poll, 12281da177e4SLinus Torvalds .listen = sock_no_listen, 12291da177e4SLinus Torvalds .shutdown = sock_no_shutdown, 12301da177e4SLinus Torvalds .setsockopt = hci_sock_setsockopt, 12311da177e4SLinus Torvalds .getsockopt = hci_sock_getsockopt, 12321da177e4SLinus Torvalds .connect = sock_no_connect, 12331da177e4SLinus Torvalds .socketpair = sock_no_socketpair, 12341da177e4SLinus Torvalds .accept = sock_no_accept, 12351da177e4SLinus Torvalds .mmap = sock_no_mmap 12361da177e4SLinus Torvalds }; 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds static struct proto hci_sk_proto = { 12391da177e4SLinus Torvalds .name = "HCI", 12401da177e4SLinus Torvalds .owner = THIS_MODULE, 12411da177e4SLinus Torvalds .obj_size = sizeof(struct hci_pinfo) 12421da177e4SLinus Torvalds }; 12431da177e4SLinus Torvalds 12443f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 12453f378b68SEric Paris int kern) 12461da177e4SLinus Torvalds { 12471da177e4SLinus Torvalds struct sock *sk; 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds BT_DBG("sock %p", sock); 12501da177e4SLinus Torvalds 12511da177e4SLinus Torvalds if (sock->type != SOCK_RAW) 12521da177e4SLinus Torvalds return -ESOCKTNOSUPPORT; 12531da177e4SLinus Torvalds 12541da177e4SLinus Torvalds sock->ops = &hci_sock_ops; 12551da177e4SLinus Torvalds 12566257ff21SPavel Emelyanov sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto); 12571da177e4SLinus Torvalds if (!sk) 12581da177e4SLinus Torvalds return -ENOMEM; 12591da177e4SLinus Torvalds 12601da177e4SLinus Torvalds sock_init_data(sock, sk); 12611da177e4SLinus Torvalds 12621da177e4SLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds sk->sk_protocol = protocol; 12651da177e4SLinus Torvalds 12661da177e4SLinus Torvalds sock->state = SS_UNCONNECTED; 12671da177e4SLinus Torvalds sk->sk_state = BT_OPEN; 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds bt_sock_link(&hci_sk_list, sk); 12701da177e4SLinus Torvalds return 0; 12711da177e4SLinus Torvalds } 12721da177e4SLinus Torvalds 1273ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = { 12741da177e4SLinus Torvalds .family = PF_BLUETOOTH, 12751da177e4SLinus Torvalds .owner = THIS_MODULE, 12761da177e4SLinus Torvalds .create = hci_sock_create, 12771da177e4SLinus Torvalds }; 12781da177e4SLinus Torvalds 12791da177e4SLinus Torvalds int __init hci_sock_init(void) 12801da177e4SLinus Torvalds { 12811da177e4SLinus Torvalds int err; 12821da177e4SLinus Torvalds 1283b0a8e282SMarcel Holtmann BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr)); 1284b0a8e282SMarcel Holtmann 12851da177e4SLinus Torvalds err = proto_register(&hci_sk_proto, 0); 12861da177e4SLinus Torvalds if (err < 0) 12871da177e4SLinus Torvalds return err; 12881da177e4SLinus Torvalds 12891da177e4SLinus Torvalds err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 1290f7c86637SMasatake YAMATO if (err < 0) { 1291f7c86637SMasatake YAMATO BT_ERR("HCI socket registration failed"); 12921da177e4SLinus Torvalds goto error; 1293f7c86637SMasatake YAMATO } 1294f7c86637SMasatake YAMATO 1295b0316615SAl Viro err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL); 1296f7c86637SMasatake YAMATO if (err < 0) { 1297f7c86637SMasatake YAMATO BT_ERR("Failed to create HCI proc file"); 1298f7c86637SMasatake YAMATO bt_sock_unregister(BTPROTO_HCI); 1299f7c86637SMasatake YAMATO goto error; 1300f7c86637SMasatake YAMATO } 13011da177e4SLinus Torvalds 13021da177e4SLinus Torvalds BT_INFO("HCI socket layer initialized"); 13031da177e4SLinus Torvalds 13041da177e4SLinus Torvalds return 0; 13051da177e4SLinus Torvalds 13061da177e4SLinus Torvalds error: 13071da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 13081da177e4SLinus Torvalds return err; 13091da177e4SLinus Torvalds } 13101da177e4SLinus Torvalds 1311b7440a14SAnand Gadiyar void hci_sock_cleanup(void) 13121da177e4SLinus Torvalds { 1313f7c86637SMasatake YAMATO bt_procfs_cleanup(&init_net, "hci"); 13145e9d7f86SDavid Herrmann bt_sock_unregister(BTPROTO_HCI); 13151da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 13161da177e4SLinus Torvalds } 1317