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