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 7981195fbb8SMarcel Holtmann /* Users with CAP_NET_ADMIN capabilities are allowed 7991195fbb8SMarcel Holtmann * access to all management commands and events. For 8001195fbb8SMarcel Holtmann * untrusted users the interface is restricted and 8011195fbb8SMarcel Holtmann * also only untrusted events are sent. 80250ebc055SMarcel Holtmann */ 8031195fbb8SMarcel 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. 811*f6b7712eSMarcel Holtmann * 812*f6b7712eSMarcel Holtmann * This also enables generic events that are safe to be 813*f6b7712eSMarcel Holtmann * received by untrusted users. Example for such events 814*f6b7712eSMarcel Holtmann * are changes to settings, class of device, name etc. 815f9207338SMarcel Holtmann */ 816f9207338SMarcel Holtmann if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { 817f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); 818f9207338SMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); 819*f6b7712eSMarcel Holtmann hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS); 820f9207338SMarcel Holtmann } 821801c1e8dSJohan Hedberg break; 822801c1e8dSJohan Hedberg } 823801c1e8dSJohan Hedberg 8247cc2ade2SMarcel Holtmann 8257cc2ade2SMarcel Holtmann hci_pi(sk)->channel = haddr.hci_channel; 8261da177e4SLinus Torvalds sk->sk_state = BT_BOUND; 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds done: 8291da177e4SLinus Torvalds release_sock(sk); 8301da177e4SLinus Torvalds return err; 8311da177e4SLinus Torvalds } 8321da177e4SLinus Torvalds 8338fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, 8348fc9ced3SGustavo Padovan int *addr_len, int peer) 8351da177e4SLinus Torvalds { 8361da177e4SLinus Torvalds struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 8371da177e4SLinus Torvalds struct sock *sk = sock->sk; 8389d4b68b2SMarcel Holtmann struct hci_dev *hdev; 8399d4b68b2SMarcel Holtmann int err = 0; 8401da177e4SLinus Torvalds 8411da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 8421da177e4SLinus Torvalds 84306f43cbcSMarcel Holtmann if (peer) 84406f43cbcSMarcel Holtmann return -EOPNOTSUPP; 84506f43cbcSMarcel Holtmann 8461da177e4SLinus Torvalds lock_sock(sk); 8471da177e4SLinus Torvalds 8489d4b68b2SMarcel Holtmann hdev = hci_pi(sk)->hdev; 8499d4b68b2SMarcel Holtmann if (!hdev) { 8509d4b68b2SMarcel Holtmann err = -EBADFD; 8519d4b68b2SMarcel Holtmann goto done; 8529d4b68b2SMarcel Holtmann } 8539d4b68b2SMarcel Holtmann 8541da177e4SLinus Torvalds *addr_len = sizeof(*haddr); 8551da177e4SLinus Torvalds haddr->hci_family = AF_BLUETOOTH; 8567b005bd3SMarcel Holtmann haddr->hci_dev = hdev->id; 8579d4b68b2SMarcel Holtmann haddr->hci_channel= hci_pi(sk)->channel; 8581da177e4SLinus Torvalds 8599d4b68b2SMarcel Holtmann done: 8601da177e4SLinus Torvalds release_sock(sk); 8619d4b68b2SMarcel Holtmann return err; 8621da177e4SLinus Torvalds } 8631da177e4SLinus Torvalds 8646039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, 8656039aa73SGustavo Padovan struct sk_buff *skb) 8661da177e4SLinus Torvalds { 8671da177e4SLinus Torvalds __u32 mask = hci_pi(sk)->cmsg_mask; 8681da177e4SLinus Torvalds 8690d48d939SMarcel Holtmann if (mask & HCI_CMSG_DIR) { 8700d48d939SMarcel Holtmann int incoming = bt_cb(skb)->incoming; 8718fc9ced3SGustavo Padovan put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), 8728fc9ced3SGustavo Padovan &incoming); 8730d48d939SMarcel Holtmann } 8741da177e4SLinus Torvalds 875a61bbcf2SPatrick McHardy if (mask & HCI_CMSG_TSTAMP) { 876f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT 877f6e623a6SJohann Felix Soden struct compat_timeval ctv; 878f6e623a6SJohann Felix Soden #endif 879a61bbcf2SPatrick McHardy struct timeval tv; 880767c5eb5SMarcel Holtmann void *data; 881767c5eb5SMarcel Holtmann int len; 882a61bbcf2SPatrick McHardy 883a61bbcf2SPatrick McHardy skb_get_timestamp(skb, &tv); 884767c5eb5SMarcel Holtmann 8851da97f83SDavid S. Miller data = &tv; 8861da97f83SDavid S. Miller len = sizeof(tv); 8871da97f83SDavid S. Miller #ifdef CONFIG_COMPAT 888da88cea1SH. J. Lu if (!COMPAT_USE_64BIT_TIME && 889da88cea1SH. J. Lu (msg->msg_flags & MSG_CMSG_COMPAT)) { 890767c5eb5SMarcel Holtmann ctv.tv_sec = tv.tv_sec; 891767c5eb5SMarcel Holtmann ctv.tv_usec = tv.tv_usec; 892767c5eb5SMarcel Holtmann data = &ctv; 893767c5eb5SMarcel Holtmann len = sizeof(ctv); 894767c5eb5SMarcel Holtmann } 8951da97f83SDavid S. Miller #endif 896767c5eb5SMarcel Holtmann 897767c5eb5SMarcel Holtmann put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 898a61bbcf2SPatrick McHardy } 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds 9011b784140SYing Xue static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 9021b784140SYing Xue int flags) 9031da177e4SLinus Torvalds { 9041da177e4SLinus Torvalds int noblock = flags & MSG_DONTWAIT; 9051da177e4SLinus Torvalds struct sock *sk = sock->sk; 9061da177e4SLinus Torvalds struct sk_buff *skb; 9071da177e4SLinus Torvalds int copied, err; 9081da177e4SLinus Torvalds 9091da177e4SLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 9101da177e4SLinus Torvalds 9111da177e4SLinus Torvalds if (flags & (MSG_OOB)) 9121da177e4SLinus Torvalds return -EOPNOTSUPP; 9131da177e4SLinus Torvalds 9141da177e4SLinus Torvalds if (sk->sk_state == BT_CLOSED) 9151da177e4SLinus Torvalds return 0; 9161da177e4SLinus Torvalds 91770f23020SAndrei Emeltchenko skb = skb_recv_datagram(sk, flags, noblock, &err); 91870f23020SAndrei Emeltchenko if (!skb) 9191da177e4SLinus Torvalds return err; 9201da177e4SLinus Torvalds 9211da177e4SLinus Torvalds copied = skb->len; 9221da177e4SLinus Torvalds if (len < copied) { 9231da177e4SLinus Torvalds msg->msg_flags |= MSG_TRUNC; 9241da177e4SLinus Torvalds copied = len; 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds 927badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb); 92851f3d02bSDavid S. Miller err = skb_copy_datagram_msg(skb, 0, msg, copied); 9291da177e4SLinus Torvalds 9303a208627SMarcel Holtmann switch (hci_pi(sk)->channel) { 9313a208627SMarcel Holtmann case HCI_CHANNEL_RAW: 9321da177e4SLinus Torvalds hci_sock_cmsg(sk, msg, skb); 9333a208627SMarcel Holtmann break; 93423500189SMarcel Holtmann case HCI_CHANNEL_USER: 935cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 936cd82e61cSMarcel Holtmann sock_recv_timestamp(msg, sk, skb); 937cd82e61cSMarcel Holtmann break; 938801c1e8dSJohan Hedberg default: 939801c1e8dSJohan Hedberg if (hci_mgmt_chan_find(hci_pi(sk)->channel)) 940801c1e8dSJohan Hedberg sock_recv_timestamp(msg, sk, skb); 941801c1e8dSJohan Hedberg break; 9423a208627SMarcel Holtmann } 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds skb_free_datagram(sk, skb); 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds return err ? : copied; 9471da177e4SLinus Torvalds } 9481da177e4SLinus Torvalds 9491b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, 9501b784140SYing Xue size_t len) 9511da177e4SLinus Torvalds { 9521da177e4SLinus Torvalds struct sock *sk = sock->sk; 953801c1e8dSJohan Hedberg struct hci_mgmt_chan *chan; 9541da177e4SLinus Torvalds struct hci_dev *hdev; 9551da177e4SLinus Torvalds struct sk_buff *skb; 9561da177e4SLinus Torvalds int err; 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds if (msg->msg_flags & MSG_OOB) 9611da177e4SLinus Torvalds return -EOPNOTSUPP; 9621da177e4SLinus Torvalds 9631da177e4SLinus Torvalds if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 9641da177e4SLinus Torvalds return -EINVAL; 9651da177e4SLinus Torvalds 9661da177e4SLinus Torvalds if (len < 4 || len > HCI_MAX_FRAME_SIZE) 9671da177e4SLinus Torvalds return -EINVAL; 9681da177e4SLinus Torvalds 9691da177e4SLinus Torvalds lock_sock(sk); 9701da177e4SLinus Torvalds 9710381101fSJohan Hedberg switch (hci_pi(sk)->channel) { 9720381101fSJohan Hedberg case HCI_CHANNEL_RAW: 97323500189SMarcel Holtmann case HCI_CHANNEL_USER: 9740381101fSJohan Hedberg break; 975cd82e61cSMarcel Holtmann case HCI_CHANNEL_MONITOR: 976cd82e61cSMarcel Holtmann err = -EOPNOTSUPP; 977cd82e61cSMarcel Holtmann goto done; 9780381101fSJohan Hedberg default: 979801c1e8dSJohan Hedberg mutex_lock(&mgmt_chan_list_lock); 980801c1e8dSJohan Hedberg chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); 981801c1e8dSJohan Hedberg if (chan) 9826d785aa3SJohan Hedberg err = mgmt_control(chan, sk, msg, len); 983801c1e8dSJohan Hedberg else 9840381101fSJohan Hedberg err = -EINVAL; 985801c1e8dSJohan Hedberg 986801c1e8dSJohan Hedberg mutex_unlock(&mgmt_chan_list_lock); 9870381101fSJohan Hedberg goto done; 9880381101fSJohan Hedberg } 9890381101fSJohan Hedberg 99070f23020SAndrei Emeltchenko hdev = hci_pi(sk)->hdev; 99170f23020SAndrei Emeltchenko if (!hdev) { 9921da177e4SLinus Torvalds err = -EBADFD; 9931da177e4SLinus Torvalds goto done; 9941da177e4SLinus Torvalds } 9951da177e4SLinus Torvalds 9967e21addcSMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) { 9977e21addcSMarcel Holtmann err = -ENETDOWN; 9987e21addcSMarcel Holtmann goto done; 9997e21addcSMarcel Holtmann } 10007e21addcSMarcel Holtmann 100170f23020SAndrei Emeltchenko skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); 100270f23020SAndrei Emeltchenko if (!skb) 10031da177e4SLinus Torvalds goto done; 10041da177e4SLinus Torvalds 10056ce8e9ceSAl Viro if (memcpy_from_msg(skb_put(skb, len), msg, len)) { 10061da177e4SLinus Torvalds err = -EFAULT; 10071da177e4SLinus Torvalds goto drop; 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds 10100d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); 10111da177e4SLinus Torvalds skb_pull(skb, 1); 10121da177e4SLinus Torvalds 10131bc5ad16SMarcel Holtmann if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { 10141bc5ad16SMarcel Holtmann /* No permission check is needed for user channel 10151bc5ad16SMarcel Holtmann * since that gets enforced when binding the socket. 10161bc5ad16SMarcel Holtmann * 10171bc5ad16SMarcel Holtmann * However check that the packet type is valid. 10181bc5ad16SMarcel Holtmann */ 10191bc5ad16SMarcel Holtmann if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT && 10201bc5ad16SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && 10211bc5ad16SMarcel Holtmann bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { 10221bc5ad16SMarcel Holtmann err = -EINVAL; 10231bc5ad16SMarcel Holtmann goto drop; 10241bc5ad16SMarcel Holtmann } 10251bc5ad16SMarcel Holtmann 10261bc5ad16SMarcel Holtmann skb_queue_tail(&hdev->raw_q, skb); 10271bc5ad16SMarcel Holtmann queue_work(hdev->workqueue, &hdev->tx_work); 10281bc5ad16SMarcel Holtmann } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { 102983985319SHarvey Harrison u16 opcode = get_unaligned_le16(skb->data); 10301da177e4SLinus Torvalds u16 ogf = hci_opcode_ogf(opcode); 10311da177e4SLinus Torvalds u16 ocf = hci_opcode_ocf(opcode); 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds if (((ogf > HCI_SFLT_MAX_OGF) || 10343bb3c755SGustavo Padovan !hci_test_bit(ocf & HCI_FLT_OCF_BITS, 10353bb3c755SGustavo Padovan &hci_sec_filter.ocf_mask[ogf])) && 10361da177e4SLinus Torvalds !capable(CAP_NET_RAW)) { 10371da177e4SLinus Torvalds err = -EPERM; 10381da177e4SLinus Torvalds goto drop; 10391da177e4SLinus Torvalds } 10401da177e4SLinus Torvalds 1041fee746b0SMarcel Holtmann if (ogf == 0x3f) { 10421da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 10433eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 10441da177e4SLinus Torvalds } else { 104549c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as 104611714b3dSJohan Hedberg * single-command requests. 104711714b3dSJohan Hedberg */ 10486368c235SEyal Birger bt_cb(skb)->req_start = 1; 104911714b3dSJohan Hedberg 10501da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb); 1051c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 10521da177e4SLinus Torvalds } 10531da177e4SLinus Torvalds } else { 10541da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 10551da177e4SLinus Torvalds err = -EPERM; 10561da177e4SLinus Torvalds goto drop; 10571da177e4SLinus Torvalds } 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds skb_queue_tail(&hdev->raw_q, skb); 10603eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 10611da177e4SLinus Torvalds } 10621da177e4SLinus Torvalds 10631da177e4SLinus Torvalds err = len; 10641da177e4SLinus Torvalds 10651da177e4SLinus Torvalds done: 10661da177e4SLinus Torvalds release_sock(sk); 10671da177e4SLinus Torvalds return err; 10681da177e4SLinus Torvalds 10691da177e4SLinus Torvalds drop: 10701da177e4SLinus Torvalds kfree_skb(skb); 10711da177e4SLinus Torvalds goto done; 10721da177e4SLinus Torvalds } 10731da177e4SLinus Torvalds 10748fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname, 10758fc9ced3SGustavo Padovan char __user *optval, unsigned int len) 10761da177e4SLinus Torvalds { 10771da177e4SLinus Torvalds struct hci_ufilter uf = { .opcode = 0 }; 10781da177e4SLinus Torvalds struct sock *sk = sock->sk; 10791da177e4SLinus Torvalds int err = 0, opt = 0; 10801da177e4SLinus Torvalds 10811da177e4SLinus Torvalds BT_DBG("sk %p, opt %d", sk, optname); 10821da177e4SLinus Torvalds 10831da177e4SLinus Torvalds lock_sock(sk); 10841da177e4SLinus Torvalds 10852f39cdb7SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1086c2371e80SMarcel Holtmann err = -EBADFD; 10872f39cdb7SMarcel Holtmann goto done; 10882f39cdb7SMarcel Holtmann } 10892f39cdb7SMarcel Holtmann 10901da177e4SLinus Torvalds switch (optname) { 10911da177e4SLinus Torvalds case HCI_DATA_DIR: 10921da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 10931da177e4SLinus Torvalds err = -EFAULT; 10941da177e4SLinus Torvalds break; 10951da177e4SLinus Torvalds } 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds if (opt) 10981da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 10991da177e4SLinus Torvalds else 11001da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 11011da177e4SLinus Torvalds break; 11021da177e4SLinus Torvalds 11031da177e4SLinus Torvalds case HCI_TIME_STAMP: 11041da177e4SLinus Torvalds if (get_user(opt, (int __user *)optval)) { 11051da177e4SLinus Torvalds err = -EFAULT; 11061da177e4SLinus Torvalds break; 11071da177e4SLinus Torvalds } 11081da177e4SLinus Torvalds 11091da177e4SLinus Torvalds if (opt) 11101da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 11111da177e4SLinus Torvalds else 11121da177e4SLinus Torvalds hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 11131da177e4SLinus Torvalds break; 11141da177e4SLinus Torvalds 11151da177e4SLinus Torvalds case HCI_FILTER: 11160878b666SMarcel Holtmann { 11170878b666SMarcel Holtmann struct hci_filter *f = &hci_pi(sk)->filter; 11180878b666SMarcel Holtmann 11190878b666SMarcel Holtmann uf.type_mask = f->type_mask; 11200878b666SMarcel Holtmann uf.opcode = f->opcode; 11210878b666SMarcel Holtmann uf.event_mask[0] = *((u32 *) f->event_mask + 0); 11220878b666SMarcel Holtmann uf.event_mask[1] = *((u32 *) f->event_mask + 1); 11230878b666SMarcel Holtmann } 11240878b666SMarcel Holtmann 11251da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 11261da177e4SLinus Torvalds if (copy_from_user(&uf, optval, len)) { 11271da177e4SLinus Torvalds err = -EFAULT; 11281da177e4SLinus Torvalds break; 11291da177e4SLinus Torvalds } 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds if (!capable(CAP_NET_RAW)) { 11321da177e4SLinus Torvalds uf.type_mask &= hci_sec_filter.type_mask; 11331da177e4SLinus Torvalds uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 11341da177e4SLinus Torvalds uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 11351da177e4SLinus Torvalds } 11361da177e4SLinus Torvalds 11371da177e4SLinus Torvalds { 11381da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds f->type_mask = uf.type_mask; 11411da177e4SLinus Torvalds f->opcode = uf.opcode; 11421da177e4SLinus Torvalds *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 11431da177e4SLinus Torvalds *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 11441da177e4SLinus Torvalds } 11451da177e4SLinus Torvalds break; 11461da177e4SLinus Torvalds 11471da177e4SLinus Torvalds default: 11481da177e4SLinus Torvalds err = -ENOPROTOOPT; 11491da177e4SLinus Torvalds break; 11501da177e4SLinus Torvalds } 11511da177e4SLinus Torvalds 11522f39cdb7SMarcel Holtmann done: 11531da177e4SLinus Torvalds release_sock(sk); 11541da177e4SLinus Torvalds return err; 11551da177e4SLinus Torvalds } 11561da177e4SLinus Torvalds 11578fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname, 11588fc9ced3SGustavo Padovan char __user *optval, int __user *optlen) 11591da177e4SLinus Torvalds { 11601da177e4SLinus Torvalds struct hci_ufilter uf; 11611da177e4SLinus Torvalds struct sock *sk = sock->sk; 1162cedc5469SMarcel Holtmann int len, opt, err = 0; 1163cedc5469SMarcel Holtmann 1164cedc5469SMarcel Holtmann BT_DBG("sk %p, opt %d", sk, optname); 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds if (get_user(len, optlen)) 11671da177e4SLinus Torvalds return -EFAULT; 11681da177e4SLinus Torvalds 1169cedc5469SMarcel Holtmann lock_sock(sk); 1170cedc5469SMarcel Holtmann 1171cedc5469SMarcel Holtmann if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { 1172c2371e80SMarcel Holtmann err = -EBADFD; 1173cedc5469SMarcel Holtmann goto done; 1174cedc5469SMarcel Holtmann } 1175cedc5469SMarcel Holtmann 11761da177e4SLinus Torvalds switch (optname) { 11771da177e4SLinus Torvalds case HCI_DATA_DIR: 11781da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 11791da177e4SLinus Torvalds opt = 1; 11801da177e4SLinus Torvalds else 11811da177e4SLinus Torvalds opt = 0; 11821da177e4SLinus Torvalds 11831da177e4SLinus Torvalds if (put_user(opt, optval)) 1184cedc5469SMarcel Holtmann err = -EFAULT; 11851da177e4SLinus Torvalds break; 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds case HCI_TIME_STAMP: 11881da177e4SLinus Torvalds if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 11891da177e4SLinus Torvalds opt = 1; 11901da177e4SLinus Torvalds else 11911da177e4SLinus Torvalds opt = 0; 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds if (put_user(opt, optval)) 1194cedc5469SMarcel Holtmann err = -EFAULT; 11951da177e4SLinus Torvalds break; 11961da177e4SLinus Torvalds 11971da177e4SLinus Torvalds case HCI_FILTER: 11981da177e4SLinus Torvalds { 11991da177e4SLinus Torvalds struct hci_filter *f = &hci_pi(sk)->filter; 12001da177e4SLinus Torvalds 1201e15ca9a0SMathias Krause memset(&uf, 0, sizeof(uf)); 12021da177e4SLinus Torvalds uf.type_mask = f->type_mask; 12031da177e4SLinus Torvalds uf.opcode = f->opcode; 12041da177e4SLinus Torvalds uf.event_mask[0] = *((u32 *) f->event_mask + 0); 12051da177e4SLinus Torvalds uf.event_mask[1] = *((u32 *) f->event_mask + 1); 12061da177e4SLinus Torvalds } 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds len = min_t(unsigned int, len, sizeof(uf)); 12091da177e4SLinus Torvalds if (copy_to_user(optval, &uf, len)) 1210cedc5469SMarcel Holtmann err = -EFAULT; 12111da177e4SLinus Torvalds break; 12121da177e4SLinus Torvalds 12131da177e4SLinus Torvalds default: 1214cedc5469SMarcel Holtmann err = -ENOPROTOOPT; 12151da177e4SLinus Torvalds break; 12161da177e4SLinus Torvalds } 12171da177e4SLinus Torvalds 1218cedc5469SMarcel Holtmann done: 1219cedc5469SMarcel Holtmann release_sock(sk); 1220cedc5469SMarcel Holtmann return err; 12211da177e4SLinus Torvalds } 12221da177e4SLinus Torvalds 122390ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = { 12241da177e4SLinus Torvalds .family = PF_BLUETOOTH, 12251da177e4SLinus Torvalds .owner = THIS_MODULE, 12261da177e4SLinus Torvalds .release = hci_sock_release, 12271da177e4SLinus Torvalds .bind = hci_sock_bind, 12281da177e4SLinus Torvalds .getname = hci_sock_getname, 12291da177e4SLinus Torvalds .sendmsg = hci_sock_sendmsg, 12301da177e4SLinus Torvalds .recvmsg = hci_sock_recvmsg, 12311da177e4SLinus Torvalds .ioctl = hci_sock_ioctl, 12321da177e4SLinus Torvalds .poll = datagram_poll, 12331da177e4SLinus Torvalds .listen = sock_no_listen, 12341da177e4SLinus Torvalds .shutdown = sock_no_shutdown, 12351da177e4SLinus Torvalds .setsockopt = hci_sock_setsockopt, 12361da177e4SLinus Torvalds .getsockopt = hci_sock_getsockopt, 12371da177e4SLinus Torvalds .connect = sock_no_connect, 12381da177e4SLinus Torvalds .socketpair = sock_no_socketpair, 12391da177e4SLinus Torvalds .accept = sock_no_accept, 12401da177e4SLinus Torvalds .mmap = sock_no_mmap 12411da177e4SLinus Torvalds }; 12421da177e4SLinus Torvalds 12431da177e4SLinus Torvalds static struct proto hci_sk_proto = { 12441da177e4SLinus Torvalds .name = "HCI", 12451da177e4SLinus Torvalds .owner = THIS_MODULE, 12461da177e4SLinus Torvalds .obj_size = sizeof(struct hci_pinfo) 12471da177e4SLinus Torvalds }; 12481da177e4SLinus Torvalds 12493f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 12503f378b68SEric Paris int kern) 12511da177e4SLinus Torvalds { 12521da177e4SLinus Torvalds struct sock *sk; 12531da177e4SLinus Torvalds 12541da177e4SLinus Torvalds BT_DBG("sock %p", sock); 12551da177e4SLinus Torvalds 12561da177e4SLinus Torvalds if (sock->type != SOCK_RAW) 12571da177e4SLinus Torvalds return -ESOCKTNOSUPPORT; 12581da177e4SLinus Torvalds 12591da177e4SLinus Torvalds sock->ops = &hci_sock_ops; 12601da177e4SLinus Torvalds 12616257ff21SPavel Emelyanov sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto); 12621da177e4SLinus Torvalds if (!sk) 12631da177e4SLinus Torvalds return -ENOMEM; 12641da177e4SLinus Torvalds 12651da177e4SLinus Torvalds sock_init_data(sock, sk); 12661da177e4SLinus Torvalds 12671da177e4SLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds sk->sk_protocol = protocol; 12701da177e4SLinus Torvalds 12711da177e4SLinus Torvalds sock->state = SS_UNCONNECTED; 12721da177e4SLinus Torvalds sk->sk_state = BT_OPEN; 12731da177e4SLinus Torvalds 12741da177e4SLinus Torvalds bt_sock_link(&hci_sk_list, sk); 12751da177e4SLinus Torvalds return 0; 12761da177e4SLinus Torvalds } 12771da177e4SLinus Torvalds 1278ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = { 12791da177e4SLinus Torvalds .family = PF_BLUETOOTH, 12801da177e4SLinus Torvalds .owner = THIS_MODULE, 12811da177e4SLinus Torvalds .create = hci_sock_create, 12821da177e4SLinus Torvalds }; 12831da177e4SLinus Torvalds 12841da177e4SLinus Torvalds int __init hci_sock_init(void) 12851da177e4SLinus Torvalds { 12861da177e4SLinus Torvalds int err; 12871da177e4SLinus Torvalds 1288b0a8e282SMarcel Holtmann BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr)); 1289b0a8e282SMarcel Holtmann 12901da177e4SLinus Torvalds err = proto_register(&hci_sk_proto, 0); 12911da177e4SLinus Torvalds if (err < 0) 12921da177e4SLinus Torvalds return err; 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 1295f7c86637SMasatake YAMATO if (err < 0) { 1296f7c86637SMasatake YAMATO BT_ERR("HCI socket registration failed"); 12971da177e4SLinus Torvalds goto error; 1298f7c86637SMasatake YAMATO } 1299f7c86637SMasatake YAMATO 1300b0316615SAl Viro err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL); 1301f7c86637SMasatake YAMATO if (err < 0) { 1302f7c86637SMasatake YAMATO BT_ERR("Failed to create HCI proc file"); 1303f7c86637SMasatake YAMATO bt_sock_unregister(BTPROTO_HCI); 1304f7c86637SMasatake YAMATO goto error; 1305f7c86637SMasatake YAMATO } 13061da177e4SLinus Torvalds 13071da177e4SLinus Torvalds BT_INFO("HCI socket layer initialized"); 13081da177e4SLinus Torvalds 13091da177e4SLinus Torvalds return 0; 13101da177e4SLinus Torvalds 13111da177e4SLinus Torvalds error: 13121da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 13131da177e4SLinus Torvalds return err; 13141da177e4SLinus Torvalds } 13151da177e4SLinus Torvalds 1316b7440a14SAnand Gadiyar void hci_sock_cleanup(void) 13171da177e4SLinus Torvalds { 1318f7c86637SMasatake YAMATO bt_procfs_cleanup(&init_net, "hci"); 13195e9d7f86SDavid Herrmann bt_sock_unregister(BTPROTO_HCI); 13201da177e4SLinus Torvalds proto_unregister(&hci_sk_proto); 13211da177e4SLinus Torvalds } 1322