xref: /openbmc/linux/net/bluetooth/hci_sock.c (revision 249fa1699f8642c73eb43e61b321969f0549ab2c)
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>
28787b306cSJohannes Berg #include <linux/utsname.h>
2970ecce91SMarcel Holtmann #include <linux/sched.h>
301da177e4SLinus Torvalds #include <asm/unaligned.h>
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
331da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
34cd82e61cSMarcel Holtmann #include <net/bluetooth/hci_mon.h>
35fa4335d7SJohan Hedberg #include <net/bluetooth/mgmt.h>
36fa4335d7SJohan Hedberg 
37fa4335d7SJohan Hedberg #include "mgmt_util.h"
381da177e4SLinus Torvalds 
39801c1e8dSJohan Hedberg static LIST_HEAD(mgmt_chan_list);
40801c1e8dSJohan Hedberg static DEFINE_MUTEX(mgmt_chan_list_lock);
41801c1e8dSJohan Hedberg 
4270ecce91SMarcel Holtmann static DEFINE_IDA(sock_cookie_ida);
4370ecce91SMarcel Holtmann 
44cd82e61cSMarcel Holtmann static atomic_t monitor_promisc = ATOMIC_INIT(0);
45cd82e61cSMarcel Holtmann 
461da177e4SLinus Torvalds /* ----- HCI socket interface ----- */
471da177e4SLinus Torvalds 
48863def58SMarcel Holtmann /* Socket info */
49863def58SMarcel Holtmann #define hci_pi(sk) ((struct hci_pinfo *) sk)
50863def58SMarcel Holtmann 
51863def58SMarcel Holtmann struct hci_pinfo {
52863def58SMarcel Holtmann 	struct bt_sock    bt;
53863def58SMarcel Holtmann 	struct hci_dev    *hdev;
54863def58SMarcel Holtmann 	struct hci_filter filter;
55863def58SMarcel Holtmann 	__u32             cmsg_mask;
56863def58SMarcel Holtmann 	unsigned short    channel;
576befc644SMarcel Holtmann 	unsigned long     flags;
5870ecce91SMarcel Holtmann 	__u32             cookie;
5970ecce91SMarcel Holtmann 	char              comm[TASK_COMM_LEN];
60863def58SMarcel Holtmann };
61863def58SMarcel Holtmann 
626befc644SMarcel Holtmann void hci_sock_set_flag(struct sock *sk, int nr)
636befc644SMarcel Holtmann {
646befc644SMarcel Holtmann 	set_bit(nr, &hci_pi(sk)->flags);
656befc644SMarcel Holtmann }
666befc644SMarcel Holtmann 
676befc644SMarcel Holtmann void hci_sock_clear_flag(struct sock *sk, int nr)
686befc644SMarcel Holtmann {
696befc644SMarcel Holtmann 	clear_bit(nr, &hci_pi(sk)->flags);
706befc644SMarcel Holtmann }
716befc644SMarcel Holtmann 
72c85be545SMarcel Holtmann int hci_sock_test_flag(struct sock *sk, int nr)
73c85be545SMarcel Holtmann {
74c85be545SMarcel Holtmann 	return test_bit(nr, &hci_pi(sk)->flags);
75c85be545SMarcel Holtmann }
76c85be545SMarcel Holtmann 
77d0f172b1SJohan Hedberg unsigned short hci_sock_get_channel(struct sock *sk)
78d0f172b1SJohan Hedberg {
79d0f172b1SJohan Hedberg 	return hci_pi(sk)->channel;
80d0f172b1SJohan Hedberg }
81d0f172b1SJohan Hedberg 
8270ecce91SMarcel Holtmann u32 hci_sock_get_cookie(struct sock *sk)
8370ecce91SMarcel Holtmann {
8470ecce91SMarcel Holtmann 	return hci_pi(sk)->cookie;
8570ecce91SMarcel Holtmann }
8670ecce91SMarcel Holtmann 
879391976aSJiri Slaby static inline int hci_test_bit(int nr, const void *addr)
881da177e4SLinus Torvalds {
899391976aSJiri Slaby 	return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
901da177e4SLinus Torvalds }
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds /* Security filter */
933ad254f7SMarcel Holtmann #define HCI_SFLT_MAX_OGF  5
943ad254f7SMarcel Holtmann 
953ad254f7SMarcel Holtmann struct hci_sec_filter {
963ad254f7SMarcel Holtmann 	__u32 type_mask;
973ad254f7SMarcel Holtmann 	__u32 event_mask[2];
983ad254f7SMarcel Holtmann 	__u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
993ad254f7SMarcel Holtmann };
1003ad254f7SMarcel Holtmann 
1017e67c112SMarcel Holtmann static const struct hci_sec_filter hci_sec_filter = {
1021da177e4SLinus Torvalds 	/* Packet types */
1031da177e4SLinus Torvalds 	0x10,
1041da177e4SLinus Torvalds 	/* Events */
105dd7f5527SMarcel Holtmann 	{ 0x1000d9fe, 0x0000b00c },
1061da177e4SLinus Torvalds 	/* Commands */
1071da177e4SLinus Torvalds 	{
1081da177e4SLinus Torvalds 		{ 0x0 },
1091da177e4SLinus Torvalds 		/* OGF_LINK_CTL */
1107c631a67SMarcel Holtmann 		{ 0xbe000006, 0x00000001, 0x00000000, 0x00 },
1111da177e4SLinus Torvalds 		/* OGF_LINK_POLICY */
1127c631a67SMarcel Holtmann 		{ 0x00005200, 0x00000000, 0x00000000, 0x00 },
1131da177e4SLinus Torvalds 		/* OGF_HOST_CTL */
1147c631a67SMarcel Holtmann 		{ 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
1151da177e4SLinus Torvalds 		/* OGF_INFO_PARAM */
1167c631a67SMarcel Holtmann 		{ 0x000002be, 0x00000000, 0x00000000, 0x00 },
1171da177e4SLinus Torvalds 		/* OGF_STATUS_PARAM */
1187c631a67SMarcel Holtmann 		{ 0x000000ea, 0x00000000, 0x00000000, 0x00 }
1191da177e4SLinus Torvalds 	}
1201da177e4SLinus Torvalds };
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds static struct bt_sock_list hci_sk_list = {
123d5fb2962SRobert P. J. Day 	.lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
1241da177e4SLinus Torvalds };
1251da177e4SLinus Torvalds 
126f81fe64fSMarcel Holtmann static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb)
127f81fe64fSMarcel Holtmann {
128f81fe64fSMarcel Holtmann 	struct hci_filter *flt;
129f81fe64fSMarcel Holtmann 	int flt_type, flt_event;
130f81fe64fSMarcel Holtmann 
131f81fe64fSMarcel Holtmann 	/* Apply filter */
132f81fe64fSMarcel Holtmann 	flt = &hci_pi(sk)->filter;
133f81fe64fSMarcel Holtmann 
134d79f34e3SMarcel Holtmann 	flt_type = hci_skb_pkt_type(skb) & HCI_FLT_TYPE_BITS;
135f81fe64fSMarcel Holtmann 
136f81fe64fSMarcel Holtmann 	if (!test_bit(flt_type, &flt->type_mask))
137f81fe64fSMarcel Holtmann 		return true;
138f81fe64fSMarcel Holtmann 
139f81fe64fSMarcel Holtmann 	/* Extra filter for event packets only */
140d79f34e3SMarcel Holtmann 	if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT)
141f81fe64fSMarcel Holtmann 		return false;
142f81fe64fSMarcel Holtmann 
143f81fe64fSMarcel Holtmann 	flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
144f81fe64fSMarcel Holtmann 
145f81fe64fSMarcel Holtmann 	if (!hci_test_bit(flt_event, &flt->event_mask))
146f81fe64fSMarcel Holtmann 		return true;
147f81fe64fSMarcel Holtmann 
148f81fe64fSMarcel Holtmann 	/* Check filter only when opcode is set */
149f81fe64fSMarcel Holtmann 	if (!flt->opcode)
150f81fe64fSMarcel Holtmann 		return false;
151f81fe64fSMarcel Holtmann 
152f81fe64fSMarcel Holtmann 	if (flt_event == HCI_EV_CMD_COMPLETE &&
153f81fe64fSMarcel Holtmann 	    flt->opcode != get_unaligned((__le16 *)(skb->data + 3)))
154f81fe64fSMarcel Holtmann 		return true;
155f81fe64fSMarcel Holtmann 
156f81fe64fSMarcel Holtmann 	if (flt_event == HCI_EV_CMD_STATUS &&
157f81fe64fSMarcel Holtmann 	    flt->opcode != get_unaligned((__le16 *)(skb->data + 4)))
158f81fe64fSMarcel Holtmann 		return true;
159f81fe64fSMarcel Holtmann 
160f81fe64fSMarcel Holtmann 	return false;
161f81fe64fSMarcel Holtmann }
162f81fe64fSMarcel Holtmann 
1631da177e4SLinus Torvalds /* Send frame to RAW socket */
164470fe1b5SMarcel Holtmann void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
1651da177e4SLinus Torvalds {
1661da177e4SLinus Torvalds 	struct sock *sk;
167e0edf373SMarcel Holtmann 	struct sk_buff *skb_copy = NULL;
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds 	BT_DBG("hdev %p len %d", hdev, skb->len);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 	read_lock(&hci_sk_list.lock);
172470fe1b5SMarcel Holtmann 
173b67bfe0dSSasha Levin 	sk_for_each(sk, &hci_sk_list.head) {
1741da177e4SLinus Torvalds 		struct sk_buff *nskb;
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 		if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
1771da177e4SLinus Torvalds 			continue;
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds 		/* Don't send frame to the socket it came from */
1801da177e4SLinus Torvalds 		if (skb->sk == sk)
1811da177e4SLinus Torvalds 			continue;
1821da177e4SLinus Torvalds 
18323500189SMarcel Holtmann 		if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) {
184d79f34e3SMarcel Holtmann 			if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT &&
185d79f34e3SMarcel Holtmann 			    hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
186d79f34e3SMarcel Holtmann 			    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
187d79f34e3SMarcel Holtmann 			    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT)
188bb77543eSMarcel Holtmann 				continue;
189f81fe64fSMarcel Holtmann 			if (is_filtered_packet(sk, skb))
1901da177e4SLinus Torvalds 				continue;
19123500189SMarcel Holtmann 		} else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
19223500189SMarcel Holtmann 			if (!bt_cb(skb)->incoming)
19323500189SMarcel Holtmann 				continue;
194d79f34e3SMarcel Holtmann 			if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
195d79f34e3SMarcel Holtmann 			    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
196d79f34e3SMarcel Holtmann 			    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT)
19723500189SMarcel Holtmann 				continue;
19823500189SMarcel Holtmann 		} else {
19923500189SMarcel Holtmann 			/* Don't send frame to other channel types */
20023500189SMarcel Holtmann 			continue;
20123500189SMarcel Holtmann 		}
2021da177e4SLinus Torvalds 
203e0edf373SMarcel Holtmann 		if (!skb_copy) {
204e0edf373SMarcel Holtmann 			/* Create a private copy with headroom */
205bad93e9dSOctavian Purdila 			skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true);
206e0edf373SMarcel Holtmann 			if (!skb_copy)
2071da177e4SLinus Torvalds 				continue;
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds 			/* Put type byte before the data */
210d79f34e3SMarcel Holtmann 			memcpy(skb_push(skb_copy, 1), &hci_skb_pkt_type(skb), 1);
211e0edf373SMarcel Holtmann 		}
212e0edf373SMarcel Holtmann 
213e0edf373SMarcel Holtmann 		nskb = skb_clone(skb_copy, GFP_ATOMIC);
214e0edf373SMarcel Holtmann 		if (!nskb)
215e0edf373SMarcel Holtmann 			continue;
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 		if (sock_queue_rcv_skb(sk, nskb))
2181da177e4SLinus Torvalds 			kfree_skb(nskb);
2191da177e4SLinus Torvalds 	}
220470fe1b5SMarcel Holtmann 
221470fe1b5SMarcel Holtmann 	read_unlock(&hci_sk_list.lock);
222e0edf373SMarcel Holtmann 
223e0edf373SMarcel Holtmann 	kfree_skb(skb_copy);
224470fe1b5SMarcel Holtmann }
225470fe1b5SMarcel Holtmann 
2267129069eSJohan Hedberg /* Send frame to sockets with specific channel */
2277129069eSJohan Hedberg void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
228c08b1a1dSMarcel Holtmann 			 int flag, struct sock *skip_sk)
229470fe1b5SMarcel Holtmann {
230470fe1b5SMarcel Holtmann 	struct sock *sk;
231470fe1b5SMarcel Holtmann 
2327129069eSJohan Hedberg 	BT_DBG("channel %u len %d", channel, skb->len);
233470fe1b5SMarcel Holtmann 
234470fe1b5SMarcel Holtmann 	read_lock(&hci_sk_list.lock);
235470fe1b5SMarcel Holtmann 
236b67bfe0dSSasha Levin 	sk_for_each(sk, &hci_sk_list.head) {
237470fe1b5SMarcel Holtmann 		struct sk_buff *nskb;
238470fe1b5SMarcel Holtmann 
239c08b1a1dSMarcel Holtmann 		/* Ignore socket without the flag set */
240c85be545SMarcel Holtmann 		if (!hci_sock_test_flag(sk, flag))
241c08b1a1dSMarcel Holtmann 			continue;
242c08b1a1dSMarcel Holtmann 
243470fe1b5SMarcel Holtmann 		/* Skip the original socket */
244470fe1b5SMarcel Holtmann 		if (sk == skip_sk)
245470fe1b5SMarcel Holtmann 			continue;
246470fe1b5SMarcel Holtmann 
247470fe1b5SMarcel Holtmann 		if (sk->sk_state != BT_BOUND)
248470fe1b5SMarcel Holtmann 			continue;
249470fe1b5SMarcel Holtmann 
2507129069eSJohan Hedberg 		if (hci_pi(sk)->channel != channel)
251d7f72f61SMarcel Holtmann 			continue;
252d7f72f61SMarcel Holtmann 
253d7f72f61SMarcel Holtmann 		nskb = skb_clone(skb, GFP_ATOMIC);
254d7f72f61SMarcel Holtmann 		if (!nskb)
255d7f72f61SMarcel Holtmann 			continue;
256d7f72f61SMarcel Holtmann 
257d7f72f61SMarcel Holtmann 		if (sock_queue_rcv_skb(sk, nskb))
258d7f72f61SMarcel Holtmann 			kfree_skb(nskb);
259d7f72f61SMarcel Holtmann 	}
260d7f72f61SMarcel Holtmann 
261d7f72f61SMarcel Holtmann 	read_unlock(&hci_sk_list.lock);
262d7f72f61SMarcel Holtmann }
263d7f72f61SMarcel Holtmann 
264cd82e61cSMarcel Holtmann /* Send frame to monitor socket */
265cd82e61cSMarcel Holtmann void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
266cd82e61cSMarcel Holtmann {
267cd82e61cSMarcel Holtmann 	struct sk_buff *skb_copy = NULL;
2682b531294SMarcel Holtmann 	struct hci_mon_hdr *hdr;
269cd82e61cSMarcel Holtmann 	__le16 opcode;
270cd82e61cSMarcel Holtmann 
271cd82e61cSMarcel Holtmann 	if (!atomic_read(&monitor_promisc))
272cd82e61cSMarcel Holtmann 		return;
273cd82e61cSMarcel Holtmann 
274cd82e61cSMarcel Holtmann 	BT_DBG("hdev %p len %d", hdev, skb->len);
275cd82e61cSMarcel Holtmann 
276d79f34e3SMarcel Holtmann 	switch (hci_skb_pkt_type(skb)) {
277cd82e61cSMarcel Holtmann 	case HCI_COMMAND_PKT:
278dcf4adbfSJoe Perches 		opcode = cpu_to_le16(HCI_MON_COMMAND_PKT);
279cd82e61cSMarcel Holtmann 		break;
280cd82e61cSMarcel Holtmann 	case HCI_EVENT_PKT:
281dcf4adbfSJoe Perches 		opcode = cpu_to_le16(HCI_MON_EVENT_PKT);
282cd82e61cSMarcel Holtmann 		break;
283cd82e61cSMarcel Holtmann 	case HCI_ACLDATA_PKT:
284cd82e61cSMarcel Holtmann 		if (bt_cb(skb)->incoming)
285dcf4adbfSJoe Perches 			opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT);
286cd82e61cSMarcel Holtmann 		else
287dcf4adbfSJoe Perches 			opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT);
288cd82e61cSMarcel Holtmann 		break;
289cd82e61cSMarcel Holtmann 	case HCI_SCODATA_PKT:
290cd82e61cSMarcel Holtmann 		if (bt_cb(skb)->incoming)
291dcf4adbfSJoe Perches 			opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT);
292cd82e61cSMarcel Holtmann 		else
293dcf4adbfSJoe Perches 			opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT);
294cd82e61cSMarcel Holtmann 		break;
295e875ff84SMarcel Holtmann 	case HCI_DIAG_PKT:
296e875ff84SMarcel Holtmann 		opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG);
297e875ff84SMarcel Holtmann 		break;
298cd82e61cSMarcel Holtmann 	default:
299cd82e61cSMarcel Holtmann 		return;
300cd82e61cSMarcel Holtmann 	}
301cd82e61cSMarcel Holtmann 
3022b531294SMarcel Holtmann 	/* Create a private copy with headroom */
3032b531294SMarcel Holtmann 	skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true);
3042b531294SMarcel Holtmann 	if (!skb_copy)
3052b531294SMarcel Holtmann 		return;
3062b531294SMarcel Holtmann 
3072b531294SMarcel Holtmann 	/* Put header before the data */
3082b531294SMarcel Holtmann 	hdr = (void *)skb_push(skb_copy, HCI_MON_HDR_SIZE);
3092b531294SMarcel Holtmann 	hdr->opcode = opcode;
3102b531294SMarcel Holtmann 	hdr->index = cpu_to_le16(hdev->id);
3112b531294SMarcel Holtmann 	hdr->len = cpu_to_le16(skb->len);
3122b531294SMarcel Holtmann 
313c08b1a1dSMarcel Holtmann 	hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy,
314c08b1a1dSMarcel Holtmann 			    HCI_SOCK_TRUSTED, NULL);
315cd82e61cSMarcel Holtmann 	kfree_skb(skb_copy);
316cd82e61cSMarcel Holtmann }
317cd82e61cSMarcel Holtmann 
318cd82e61cSMarcel Holtmann static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
319cd82e61cSMarcel Holtmann {
320cd82e61cSMarcel Holtmann 	struct hci_mon_hdr *hdr;
321cd82e61cSMarcel Holtmann 	struct hci_mon_new_index *ni;
3226c566dd5SMarcel Holtmann 	struct hci_mon_index_info *ii;
323cd82e61cSMarcel Holtmann 	struct sk_buff *skb;
324cd82e61cSMarcel Holtmann 	__le16 opcode;
325cd82e61cSMarcel Holtmann 
326cd82e61cSMarcel Holtmann 	switch (event) {
327cd82e61cSMarcel Holtmann 	case HCI_DEV_REG:
328cd82e61cSMarcel Holtmann 		skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC);
329cd82e61cSMarcel Holtmann 		if (!skb)
330cd82e61cSMarcel Holtmann 			return NULL;
331cd82e61cSMarcel Holtmann 
332cd82e61cSMarcel Holtmann 		ni = (void *)skb_put(skb, HCI_MON_NEW_INDEX_SIZE);
333cd82e61cSMarcel Holtmann 		ni->type = hdev->dev_type;
334cd82e61cSMarcel Holtmann 		ni->bus = hdev->bus;
335cd82e61cSMarcel Holtmann 		bacpy(&ni->bdaddr, &hdev->bdaddr);
336cd82e61cSMarcel Holtmann 		memcpy(ni->name, hdev->name, 8);
337cd82e61cSMarcel Holtmann 
338dcf4adbfSJoe Perches 		opcode = cpu_to_le16(HCI_MON_NEW_INDEX);
339cd82e61cSMarcel Holtmann 		break;
340cd82e61cSMarcel Holtmann 
341cd82e61cSMarcel Holtmann 	case HCI_DEV_UNREG:
342cd82e61cSMarcel Holtmann 		skb = bt_skb_alloc(0, GFP_ATOMIC);
343cd82e61cSMarcel Holtmann 		if (!skb)
344cd82e61cSMarcel Holtmann 			return NULL;
345cd82e61cSMarcel Holtmann 
346dcf4adbfSJoe Perches 		opcode = cpu_to_le16(HCI_MON_DEL_INDEX);
347cd82e61cSMarcel Holtmann 		break;
348cd82e61cSMarcel Holtmann 
349e131d74aSMarcel Holtmann 	case HCI_DEV_SETUP:
350e131d74aSMarcel Holtmann 		if (hdev->manufacturer == 0xffff)
351e131d74aSMarcel Holtmann 			return NULL;
352e131d74aSMarcel Holtmann 
353e131d74aSMarcel Holtmann 		/* fall through */
354e131d74aSMarcel Holtmann 
3556c566dd5SMarcel Holtmann 	case HCI_DEV_UP:
3566c566dd5SMarcel Holtmann 		skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC);
3576c566dd5SMarcel Holtmann 		if (!skb)
3586c566dd5SMarcel Holtmann 			return NULL;
3596c566dd5SMarcel Holtmann 
3606c566dd5SMarcel Holtmann 		ii = (void *)skb_put(skb, HCI_MON_INDEX_INFO_SIZE);
3616c566dd5SMarcel Holtmann 		bacpy(&ii->bdaddr, &hdev->bdaddr);
3626c566dd5SMarcel Holtmann 		ii->manufacturer = cpu_to_le16(hdev->manufacturer);
3636c566dd5SMarcel Holtmann 
3646c566dd5SMarcel Holtmann 		opcode = cpu_to_le16(HCI_MON_INDEX_INFO);
3656c566dd5SMarcel Holtmann 		break;
3666c566dd5SMarcel Holtmann 
36722db3cbcSMarcel Holtmann 	case HCI_DEV_OPEN:
36822db3cbcSMarcel Holtmann 		skb = bt_skb_alloc(0, GFP_ATOMIC);
36922db3cbcSMarcel Holtmann 		if (!skb)
37022db3cbcSMarcel Holtmann 			return NULL;
37122db3cbcSMarcel Holtmann 
37222db3cbcSMarcel Holtmann 		opcode = cpu_to_le16(HCI_MON_OPEN_INDEX);
37322db3cbcSMarcel Holtmann 		break;
37422db3cbcSMarcel Holtmann 
37522db3cbcSMarcel Holtmann 	case HCI_DEV_CLOSE:
37622db3cbcSMarcel Holtmann 		skb = bt_skb_alloc(0, GFP_ATOMIC);
37722db3cbcSMarcel Holtmann 		if (!skb)
37822db3cbcSMarcel Holtmann 			return NULL;
37922db3cbcSMarcel Holtmann 
38022db3cbcSMarcel Holtmann 		opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX);
38122db3cbcSMarcel Holtmann 		break;
38222db3cbcSMarcel Holtmann 
383cd82e61cSMarcel Holtmann 	default:
384cd82e61cSMarcel Holtmann 		return NULL;
385cd82e61cSMarcel Holtmann 	}
386cd82e61cSMarcel Holtmann 
387cd82e61cSMarcel Holtmann 	__net_timestamp(skb);
388cd82e61cSMarcel Holtmann 
389cd82e61cSMarcel Holtmann 	hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE);
390cd82e61cSMarcel Holtmann 	hdr->opcode = opcode;
391cd82e61cSMarcel Holtmann 	hdr->index = cpu_to_le16(hdev->id);
392cd82e61cSMarcel Holtmann 	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
393cd82e61cSMarcel Holtmann 
394cd82e61cSMarcel Holtmann 	return skb;
395cd82e61cSMarcel Holtmann }
396cd82e61cSMarcel Holtmann 
397*249fa169SMarcel Holtmann static struct sk_buff *create_monitor_ctrl_open(struct sock *sk)
398*249fa169SMarcel Holtmann {
399*249fa169SMarcel Holtmann 	struct hci_mon_hdr *hdr;
400*249fa169SMarcel Holtmann 	struct sk_buff *skb;
401*249fa169SMarcel Holtmann 	u16 format = 0x0002;
402*249fa169SMarcel Holtmann 	u8 ver[3];
403*249fa169SMarcel Holtmann 	u32 flags;
404*249fa169SMarcel Holtmann 
405*249fa169SMarcel Holtmann 	skb = bt_skb_alloc(14 + TASK_COMM_LEN , GFP_ATOMIC);
406*249fa169SMarcel Holtmann 	if (!skb)
407*249fa169SMarcel Holtmann 		return NULL;
408*249fa169SMarcel Holtmann 
409*249fa169SMarcel Holtmann 	mgmt_fill_version_info(ver);
410*249fa169SMarcel Holtmann 	flags = hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) ? 0x1 : 0x0;
411*249fa169SMarcel Holtmann 
412*249fa169SMarcel Holtmann 	put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
413*249fa169SMarcel Holtmann 	put_unaligned_le16(format, skb_put(skb, 2));
414*249fa169SMarcel Holtmann 	memcpy(skb_put(skb, sizeof(ver)), ver, sizeof(ver));
415*249fa169SMarcel Holtmann 	put_unaligned_le32(flags, skb_put(skb, 4));
416*249fa169SMarcel Holtmann 	*skb_put(skb, 1) = TASK_COMM_LEN;
417*249fa169SMarcel Holtmann 	memcpy(skb_put(skb, TASK_COMM_LEN), hci_pi(sk)->comm, TASK_COMM_LEN);
418*249fa169SMarcel Holtmann 
419*249fa169SMarcel Holtmann 	__net_timestamp(skb);
420*249fa169SMarcel Holtmann 
421*249fa169SMarcel Holtmann 	hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE);
422*249fa169SMarcel Holtmann 	hdr->opcode = cpu_to_le16(HCI_MON_CTRL_OPEN);
423*249fa169SMarcel Holtmann 	hdr->index = cpu_to_le16(HCI_DEV_NONE);
424*249fa169SMarcel Holtmann 	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
425*249fa169SMarcel Holtmann 
426*249fa169SMarcel Holtmann 	return skb;
427*249fa169SMarcel Holtmann }
428*249fa169SMarcel Holtmann 
429*249fa169SMarcel Holtmann static struct sk_buff *create_monitor_ctrl_close(struct sock *sk)
430*249fa169SMarcel Holtmann {
431*249fa169SMarcel Holtmann 	struct hci_mon_hdr *hdr;
432*249fa169SMarcel Holtmann 	struct sk_buff *skb;
433*249fa169SMarcel Holtmann 
434*249fa169SMarcel Holtmann 	skb = bt_skb_alloc(4, GFP_ATOMIC);
435*249fa169SMarcel Holtmann 	if (!skb)
436*249fa169SMarcel Holtmann 		return NULL;
437*249fa169SMarcel Holtmann 
438*249fa169SMarcel Holtmann 	put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
439*249fa169SMarcel Holtmann 
440*249fa169SMarcel Holtmann 	__net_timestamp(skb);
441*249fa169SMarcel Holtmann 
442*249fa169SMarcel Holtmann 	hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE);
443*249fa169SMarcel Holtmann 	hdr->opcode = cpu_to_le16(HCI_MON_CTRL_CLOSE);
444*249fa169SMarcel Holtmann 	hdr->index = cpu_to_le16(HCI_DEV_NONE);
445*249fa169SMarcel Holtmann 	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
446*249fa169SMarcel Holtmann 
447*249fa169SMarcel Holtmann 	return skb;
448*249fa169SMarcel Holtmann }
449*249fa169SMarcel Holtmann 
450787b306cSJohannes Berg static void __printf(2, 3)
451787b306cSJohannes Berg send_monitor_note(struct sock *sk, const char *fmt, ...)
452dd31506dSMarcel Holtmann {
453787b306cSJohannes Berg 	size_t len;
454dd31506dSMarcel Holtmann 	struct hci_mon_hdr *hdr;
455dd31506dSMarcel Holtmann 	struct sk_buff *skb;
456787b306cSJohannes Berg 	va_list args;
457787b306cSJohannes Berg 
458787b306cSJohannes Berg 	va_start(args, fmt);
459787b306cSJohannes Berg 	len = vsnprintf(NULL, 0, fmt, args);
460787b306cSJohannes Berg 	va_end(args);
461dd31506dSMarcel Holtmann 
462dd31506dSMarcel Holtmann 	skb = bt_skb_alloc(len + 1, GFP_ATOMIC);
463dd31506dSMarcel Holtmann 	if (!skb)
464dd31506dSMarcel Holtmann 		return;
465dd31506dSMarcel Holtmann 
466787b306cSJohannes Berg 	va_start(args, fmt);
467787b306cSJohannes Berg 	vsprintf(skb_put(skb, len), fmt, args);
468787b306cSJohannes Berg 	*skb_put(skb, 1) = 0;
469787b306cSJohannes Berg 	va_end(args);
470dd31506dSMarcel Holtmann 
471dd31506dSMarcel Holtmann 	__net_timestamp(skb);
472dd31506dSMarcel Holtmann 
473dd31506dSMarcel Holtmann 	hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE);
474dd31506dSMarcel Holtmann 	hdr->opcode = cpu_to_le16(HCI_MON_SYSTEM_NOTE);
475dd31506dSMarcel Holtmann 	hdr->index = cpu_to_le16(HCI_DEV_NONE);
476dd31506dSMarcel Holtmann 	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
477dd31506dSMarcel Holtmann 
478dd31506dSMarcel Holtmann 	if (sock_queue_rcv_skb(sk, skb))
479dd31506dSMarcel Holtmann 		kfree_skb(skb);
480dd31506dSMarcel Holtmann }
481dd31506dSMarcel Holtmann 
482cd82e61cSMarcel Holtmann static void send_monitor_replay(struct sock *sk)
483cd82e61cSMarcel Holtmann {
484cd82e61cSMarcel Holtmann 	struct hci_dev *hdev;
485cd82e61cSMarcel Holtmann 
486cd82e61cSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
487cd82e61cSMarcel Holtmann 
488cd82e61cSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
489cd82e61cSMarcel Holtmann 		struct sk_buff *skb;
490cd82e61cSMarcel Holtmann 
491cd82e61cSMarcel Holtmann 		skb = create_monitor_event(hdev, HCI_DEV_REG);
492cd82e61cSMarcel Holtmann 		if (!skb)
493cd82e61cSMarcel Holtmann 			continue;
494cd82e61cSMarcel Holtmann 
495cd82e61cSMarcel Holtmann 		if (sock_queue_rcv_skb(sk, skb))
496cd82e61cSMarcel Holtmann 			kfree_skb(skb);
49722db3cbcSMarcel Holtmann 
49822db3cbcSMarcel Holtmann 		if (!test_bit(HCI_RUNNING, &hdev->flags))
49922db3cbcSMarcel Holtmann 			continue;
50022db3cbcSMarcel Holtmann 
50122db3cbcSMarcel Holtmann 		skb = create_monitor_event(hdev, HCI_DEV_OPEN);
50222db3cbcSMarcel Holtmann 		if (!skb)
50322db3cbcSMarcel Holtmann 			continue;
50422db3cbcSMarcel Holtmann 
50522db3cbcSMarcel Holtmann 		if (sock_queue_rcv_skb(sk, skb))
50622db3cbcSMarcel Holtmann 			kfree_skb(skb);
5076c566dd5SMarcel Holtmann 
508e131d74aSMarcel Holtmann 		if (test_bit(HCI_UP, &hdev->flags))
5096c566dd5SMarcel Holtmann 			skb = create_monitor_event(hdev, HCI_DEV_UP);
510e131d74aSMarcel Holtmann 		else if (hci_dev_test_flag(hdev, HCI_SETUP))
511e131d74aSMarcel Holtmann 			skb = create_monitor_event(hdev, HCI_DEV_SETUP);
512e131d74aSMarcel Holtmann 		else
513e131d74aSMarcel Holtmann 			skb = NULL;
5146c566dd5SMarcel Holtmann 
515e131d74aSMarcel Holtmann 		if (skb) {
5166c566dd5SMarcel Holtmann 			if (sock_queue_rcv_skb(sk, skb))
5176c566dd5SMarcel Holtmann 				kfree_skb(skb);
518cd82e61cSMarcel Holtmann 		}
519e131d74aSMarcel Holtmann 	}
520cd82e61cSMarcel Holtmann 
521cd82e61cSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
522cd82e61cSMarcel Holtmann }
523cd82e61cSMarcel Holtmann 
524*249fa169SMarcel Holtmann static void send_monitor_control_replay(struct sock *mon_sk)
525*249fa169SMarcel Holtmann {
526*249fa169SMarcel Holtmann 	struct sock *sk;
527*249fa169SMarcel Holtmann 
528*249fa169SMarcel Holtmann 	read_lock(&hci_sk_list.lock);
529*249fa169SMarcel Holtmann 
530*249fa169SMarcel Holtmann 	sk_for_each(sk, &hci_sk_list.head) {
531*249fa169SMarcel Holtmann 		struct sk_buff *skb;
532*249fa169SMarcel Holtmann 
533*249fa169SMarcel Holtmann 		if (hci_pi(sk)->channel != HCI_CHANNEL_CONTROL)
534*249fa169SMarcel Holtmann 			continue;
535*249fa169SMarcel Holtmann 
536*249fa169SMarcel Holtmann 		skb = create_monitor_ctrl_open(sk);
537*249fa169SMarcel Holtmann 		if (!skb)
538*249fa169SMarcel Holtmann 			continue;
539*249fa169SMarcel Holtmann 
540*249fa169SMarcel Holtmann 		if (sock_queue_rcv_skb(mon_sk, skb))
541*249fa169SMarcel Holtmann 			kfree_skb(skb);
542*249fa169SMarcel Holtmann 	}
543*249fa169SMarcel Holtmann 
544*249fa169SMarcel Holtmann 	read_unlock(&hci_sk_list.lock);
545*249fa169SMarcel Holtmann }
546*249fa169SMarcel Holtmann 
547040030efSMarcel Holtmann /* Generate internal stack event */
548040030efSMarcel Holtmann static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
549040030efSMarcel Holtmann {
550040030efSMarcel Holtmann 	struct hci_event_hdr *hdr;
551040030efSMarcel Holtmann 	struct hci_ev_stack_internal *ev;
552040030efSMarcel Holtmann 	struct sk_buff *skb;
553040030efSMarcel Holtmann 
554040030efSMarcel Holtmann 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
555040030efSMarcel Holtmann 	if (!skb)
556040030efSMarcel Holtmann 		return;
557040030efSMarcel Holtmann 
558040030efSMarcel Holtmann 	hdr = (void *)skb_put(skb, HCI_EVENT_HDR_SIZE);
559040030efSMarcel Holtmann 	hdr->evt  = HCI_EV_STACK_INTERNAL;
560040030efSMarcel Holtmann 	hdr->plen = sizeof(*ev) + dlen;
561040030efSMarcel Holtmann 
562040030efSMarcel Holtmann 	ev  = (void *)skb_put(skb, sizeof(*ev) + dlen);
563040030efSMarcel Holtmann 	ev->type = type;
564040030efSMarcel Holtmann 	memcpy(ev->data, data, dlen);
565040030efSMarcel Holtmann 
566040030efSMarcel Holtmann 	bt_cb(skb)->incoming = 1;
567040030efSMarcel Holtmann 	__net_timestamp(skb);
568040030efSMarcel Holtmann 
569d79f34e3SMarcel Holtmann 	hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
570040030efSMarcel Holtmann 	hci_send_to_sock(hdev, skb);
571040030efSMarcel Holtmann 	kfree_skb(skb);
572040030efSMarcel Holtmann }
573040030efSMarcel Holtmann 
574040030efSMarcel Holtmann void hci_sock_dev_event(struct hci_dev *hdev, int event)
575040030efSMarcel Holtmann {
576040030efSMarcel Holtmann 	BT_DBG("hdev %s event %d", hdev->name, event);
577040030efSMarcel Holtmann 
578cd82e61cSMarcel Holtmann 	if (atomic_read(&monitor_promisc)) {
579cd82e61cSMarcel Holtmann 		struct sk_buff *skb;
580cd82e61cSMarcel Holtmann 
581ed1b28a4SMarcel Holtmann 		/* Send event to monitor */
582cd82e61cSMarcel Holtmann 		skb = create_monitor_event(hdev, event);
583cd82e61cSMarcel Holtmann 		if (skb) {
584c08b1a1dSMarcel Holtmann 			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
585c08b1a1dSMarcel Holtmann 					    HCI_SOCK_TRUSTED, NULL);
586cd82e61cSMarcel Holtmann 			kfree_skb(skb);
587cd82e61cSMarcel Holtmann 		}
588cd82e61cSMarcel Holtmann 	}
589cd82e61cSMarcel Holtmann 
590ed1b28a4SMarcel Holtmann 	if (event <= HCI_DEV_DOWN) {
591ed1b28a4SMarcel Holtmann 		struct hci_ev_si_device ev;
592ed1b28a4SMarcel Holtmann 
593040030efSMarcel Holtmann 		/* Send event to sockets */
594040030efSMarcel Holtmann 		ev.event  = event;
595040030efSMarcel Holtmann 		ev.dev_id = hdev->id;
596040030efSMarcel Holtmann 		hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
597ed1b28a4SMarcel Holtmann 	}
598040030efSMarcel Holtmann 
599040030efSMarcel Holtmann 	if (event == HCI_DEV_UNREG) {
600040030efSMarcel Holtmann 		struct sock *sk;
601040030efSMarcel Holtmann 
602040030efSMarcel Holtmann 		/* Detach sockets from device */
603040030efSMarcel Holtmann 		read_lock(&hci_sk_list.lock);
604b67bfe0dSSasha Levin 		sk_for_each(sk, &hci_sk_list.head) {
605040030efSMarcel Holtmann 			bh_lock_sock_nested(sk);
606040030efSMarcel Holtmann 			if (hci_pi(sk)->hdev == hdev) {
607040030efSMarcel Holtmann 				hci_pi(sk)->hdev = NULL;
608040030efSMarcel Holtmann 				sk->sk_err = EPIPE;
609040030efSMarcel Holtmann 				sk->sk_state = BT_OPEN;
610040030efSMarcel Holtmann 				sk->sk_state_change(sk);
611040030efSMarcel Holtmann 
612040030efSMarcel Holtmann 				hci_dev_put(hdev);
613040030efSMarcel Holtmann 			}
614040030efSMarcel Holtmann 			bh_unlock_sock(sk);
615040030efSMarcel Holtmann 		}
616040030efSMarcel Holtmann 		read_unlock(&hci_sk_list.lock);
617040030efSMarcel Holtmann 	}
618040030efSMarcel Holtmann }
619040030efSMarcel Holtmann 
620801c1e8dSJohan Hedberg static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel)
621801c1e8dSJohan Hedberg {
622801c1e8dSJohan Hedberg 	struct hci_mgmt_chan *c;
623801c1e8dSJohan Hedberg 
624801c1e8dSJohan Hedberg 	list_for_each_entry(c, &mgmt_chan_list, list) {
625801c1e8dSJohan Hedberg 		if (c->channel == channel)
626801c1e8dSJohan Hedberg 			return c;
627801c1e8dSJohan Hedberg 	}
628801c1e8dSJohan Hedberg 
629801c1e8dSJohan Hedberg 	return NULL;
630801c1e8dSJohan Hedberg }
631801c1e8dSJohan Hedberg 
632801c1e8dSJohan Hedberg static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel)
633801c1e8dSJohan Hedberg {
634801c1e8dSJohan Hedberg 	struct hci_mgmt_chan *c;
635801c1e8dSJohan Hedberg 
636801c1e8dSJohan Hedberg 	mutex_lock(&mgmt_chan_list_lock);
637801c1e8dSJohan Hedberg 	c = __hci_mgmt_chan_find(channel);
638801c1e8dSJohan Hedberg 	mutex_unlock(&mgmt_chan_list_lock);
639801c1e8dSJohan Hedberg 
640801c1e8dSJohan Hedberg 	return c;
641801c1e8dSJohan Hedberg }
642801c1e8dSJohan Hedberg 
643801c1e8dSJohan Hedberg int hci_mgmt_chan_register(struct hci_mgmt_chan *c)
644801c1e8dSJohan Hedberg {
645801c1e8dSJohan Hedberg 	if (c->channel < HCI_CHANNEL_CONTROL)
646801c1e8dSJohan Hedberg 		return -EINVAL;
647801c1e8dSJohan Hedberg 
648801c1e8dSJohan Hedberg 	mutex_lock(&mgmt_chan_list_lock);
649801c1e8dSJohan Hedberg 	if (__hci_mgmt_chan_find(c->channel)) {
650801c1e8dSJohan Hedberg 		mutex_unlock(&mgmt_chan_list_lock);
651801c1e8dSJohan Hedberg 		return -EALREADY;
652801c1e8dSJohan Hedberg 	}
653801c1e8dSJohan Hedberg 
654801c1e8dSJohan Hedberg 	list_add_tail(&c->list, &mgmt_chan_list);
655801c1e8dSJohan Hedberg 
656801c1e8dSJohan Hedberg 	mutex_unlock(&mgmt_chan_list_lock);
657801c1e8dSJohan Hedberg 
658801c1e8dSJohan Hedberg 	return 0;
659801c1e8dSJohan Hedberg }
660801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_register);
661801c1e8dSJohan Hedberg 
662801c1e8dSJohan Hedberg void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c)
663801c1e8dSJohan Hedberg {
664801c1e8dSJohan Hedberg 	mutex_lock(&mgmt_chan_list_lock);
665801c1e8dSJohan Hedberg 	list_del(&c->list);
666801c1e8dSJohan Hedberg 	mutex_unlock(&mgmt_chan_list_lock);
667801c1e8dSJohan Hedberg }
668801c1e8dSJohan Hedberg EXPORT_SYMBOL(hci_mgmt_chan_unregister);
669801c1e8dSJohan Hedberg 
6701da177e4SLinus Torvalds static int hci_sock_release(struct socket *sock)
6711da177e4SLinus Torvalds {
6721da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
6737b005bd3SMarcel Holtmann 	struct hci_dev *hdev;
674*249fa169SMarcel Holtmann 	struct sk_buff *skb;
67570ecce91SMarcel Holtmann 	int id;
6761da177e4SLinus Torvalds 
6771da177e4SLinus Torvalds 	BT_DBG("sock %p sk %p", sock, sk);
6781da177e4SLinus Torvalds 
6791da177e4SLinus Torvalds 	if (!sk)
6801da177e4SLinus Torvalds 		return 0;
6811da177e4SLinus Torvalds 
6827b005bd3SMarcel Holtmann 	hdev = hci_pi(sk)->hdev;
6837b005bd3SMarcel Holtmann 
68470ecce91SMarcel Holtmann 	switch (hci_pi(sk)->channel) {
68570ecce91SMarcel Holtmann 	case HCI_CHANNEL_MONITOR:
686cd82e61cSMarcel Holtmann 		atomic_dec(&monitor_promisc);
68770ecce91SMarcel Holtmann 		break;
68870ecce91SMarcel Holtmann 	case HCI_CHANNEL_CONTROL:
68970ecce91SMarcel Holtmann 		id = hci_pi(sk)->cookie;
69070ecce91SMarcel Holtmann 
691*249fa169SMarcel Holtmann 		/* Send event to monitor */
692*249fa169SMarcel Holtmann 		skb = create_monitor_ctrl_close(sk);
693*249fa169SMarcel Holtmann 		if (skb) {
694*249fa169SMarcel Holtmann 			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
695*249fa169SMarcel Holtmann 					    HCI_SOCK_TRUSTED, NULL);
696*249fa169SMarcel Holtmann 			kfree_skb(skb);
697*249fa169SMarcel Holtmann 		}
698*249fa169SMarcel Holtmann 
69970ecce91SMarcel Holtmann 		hci_pi(sk)->cookie = 0xffffffff;
70070ecce91SMarcel Holtmann 		ida_simple_remove(&sock_cookie_ida, id);
70170ecce91SMarcel Holtmann 		break;
70270ecce91SMarcel Holtmann 	}
703cd82e61cSMarcel Holtmann 
7041da177e4SLinus Torvalds 	bt_sock_unlink(&hci_sk_list, sk);
7051da177e4SLinus Torvalds 
7061da177e4SLinus Torvalds 	if (hdev) {
70723500189SMarcel Holtmann 		if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
7086b3cc1dbSSimon Fels 			/* When releasing an user channel exclusive access,
7096b3cc1dbSSimon Fels 			 * call hci_dev_do_close directly instead of calling
7106b3cc1dbSSimon Fels 			 * hci_dev_close to ensure the exclusive access will
7116b3cc1dbSSimon Fels 			 * be released and the controller brought back down.
7126b3cc1dbSSimon Fels 			 *
7136b3cc1dbSSimon Fels 			 * The checking of HCI_AUTO_OFF is not needed in this
7146b3cc1dbSSimon Fels 			 * case since it will have been cleared already when
7156b3cc1dbSSimon Fels 			 * opening the user channel.
7166b3cc1dbSSimon Fels 			 */
7176b3cc1dbSSimon Fels 			hci_dev_do_close(hdev);
7189380f9eaSLoic Poulain 			hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
7199380f9eaSLoic Poulain 			mgmt_index_added(hdev);
72023500189SMarcel Holtmann 		}
72123500189SMarcel Holtmann 
7221da177e4SLinus Torvalds 		atomic_dec(&hdev->promisc);
7231da177e4SLinus Torvalds 		hci_dev_put(hdev);
7241da177e4SLinus Torvalds 	}
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds 	sock_orphan(sk);
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds 	skb_queue_purge(&sk->sk_receive_queue);
7291da177e4SLinus Torvalds 	skb_queue_purge(&sk->sk_write_queue);
7301da177e4SLinus Torvalds 
7311da177e4SLinus Torvalds 	sock_put(sk);
7321da177e4SLinus Torvalds 	return 0;
7331da177e4SLinus Torvalds }
7341da177e4SLinus Torvalds 
735b2a66aadSAntti Julku static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
736f0358568SJohan Hedberg {
737f0358568SJohan Hedberg 	bdaddr_t bdaddr;
7385e762444SAntti Julku 	int err;
739f0358568SJohan Hedberg 
740f0358568SJohan Hedberg 	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
741f0358568SJohan Hedberg 		return -EFAULT;
742f0358568SJohan Hedberg 
74309fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
7445e762444SAntti Julku 
745dcc36c16SJohan Hedberg 	err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
7465e762444SAntti Julku 
74709fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
7485e762444SAntti Julku 
7495e762444SAntti Julku 	return err;
750f0358568SJohan Hedberg }
751f0358568SJohan Hedberg 
752b2a66aadSAntti Julku static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
753f0358568SJohan Hedberg {
754f0358568SJohan Hedberg 	bdaddr_t bdaddr;
7555e762444SAntti Julku 	int err;
756f0358568SJohan Hedberg 
757f0358568SJohan Hedberg 	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
758f0358568SJohan Hedberg 		return -EFAULT;
759f0358568SJohan Hedberg 
76009fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
7615e762444SAntti Julku 
762dcc36c16SJohan Hedberg 	err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
7635e762444SAntti Julku 
76409fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
7655e762444SAntti Julku 
7665e762444SAntti Julku 	return err;
767f0358568SJohan Hedberg }
768f0358568SJohan Hedberg 
7691da177e4SLinus Torvalds /* Ioctls that require bound socket */
7706039aa73SGustavo Padovan static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
7716039aa73SGustavo Padovan 				unsigned long arg)
7721da177e4SLinus Torvalds {
7731da177e4SLinus Torvalds 	struct hci_dev *hdev = hci_pi(sk)->hdev;
7741da177e4SLinus Torvalds 
7751da177e4SLinus Torvalds 	if (!hdev)
7761da177e4SLinus Torvalds 		return -EBADFD;
7771da177e4SLinus Torvalds 
778d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
7790736cfa8SMarcel Holtmann 		return -EBUSY;
7800736cfa8SMarcel Holtmann 
781d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
782fee746b0SMarcel Holtmann 		return -EOPNOTSUPP;
783fee746b0SMarcel Holtmann 
784ca8bee5dSMarcel Holtmann 	if (hdev->dev_type != HCI_PRIMARY)
7855b69bef5SMarcel Holtmann 		return -EOPNOTSUPP;
7865b69bef5SMarcel Holtmann 
7871da177e4SLinus Torvalds 	switch (cmd) {
7881da177e4SLinus Torvalds 	case HCISETRAW:
7891da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
790bf5b30b8SZhao Hongjiang 			return -EPERM;
791db596681SMarcel Holtmann 		return -EOPNOTSUPP;
7921da177e4SLinus Torvalds 
7931da177e4SLinus Torvalds 	case HCIGETCONNINFO:
7941da177e4SLinus Torvalds 		return hci_get_conn_info(hdev, (void __user *)arg);
7951da177e4SLinus Torvalds 
79640be492fSMarcel Holtmann 	case HCIGETAUTHINFO:
79740be492fSMarcel Holtmann 		return hci_get_auth_info(hdev, (void __user *)arg);
79840be492fSMarcel Holtmann 
799f0358568SJohan Hedberg 	case HCIBLOCKADDR:
800f0358568SJohan Hedberg 		if (!capable(CAP_NET_ADMIN))
801bf5b30b8SZhao Hongjiang 			return -EPERM;
802b2a66aadSAntti Julku 		return hci_sock_blacklist_add(hdev, (void __user *)arg);
803f0358568SJohan Hedberg 
804f0358568SJohan Hedberg 	case HCIUNBLOCKADDR:
805f0358568SJohan Hedberg 		if (!capable(CAP_NET_ADMIN))
806bf5b30b8SZhao Hongjiang 			return -EPERM;
807b2a66aadSAntti Julku 		return hci_sock_blacklist_del(hdev, (void __user *)arg);
8080736cfa8SMarcel Holtmann 	}
809f0358568SJohan Hedberg 
810324d36edSMarcel Holtmann 	return -ENOIOCTLCMD;
8111da177e4SLinus Torvalds }
8121da177e4SLinus Torvalds 
8138fc9ced3SGustavo Padovan static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
8148fc9ced3SGustavo Padovan 			  unsigned long arg)
8151da177e4SLinus Torvalds {
8161da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
8170736cfa8SMarcel Holtmann 	struct sock *sk = sock->sk;
8181da177e4SLinus Torvalds 	int err;
8191da177e4SLinus Torvalds 
8201da177e4SLinus Torvalds 	BT_DBG("cmd %x arg %lx", cmd, arg);
8211da177e4SLinus Torvalds 
822c1c4f956SMarcel Holtmann 	lock_sock(sk);
823c1c4f956SMarcel Holtmann 
824c1c4f956SMarcel Holtmann 	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
825c1c4f956SMarcel Holtmann 		err = -EBADFD;
826c1c4f956SMarcel Holtmann 		goto done;
827c1c4f956SMarcel Holtmann 	}
828c1c4f956SMarcel Holtmann 
829c1c4f956SMarcel Holtmann 	release_sock(sk);
830c1c4f956SMarcel Holtmann 
8311da177e4SLinus Torvalds 	switch (cmd) {
8321da177e4SLinus Torvalds 	case HCIGETDEVLIST:
8331da177e4SLinus Torvalds 		return hci_get_dev_list(argp);
8341da177e4SLinus Torvalds 
8351da177e4SLinus Torvalds 	case HCIGETDEVINFO:
8361da177e4SLinus Torvalds 		return hci_get_dev_info(argp);
8371da177e4SLinus Torvalds 
8381da177e4SLinus Torvalds 	case HCIGETCONNLIST:
8391da177e4SLinus Torvalds 		return hci_get_conn_list(argp);
8401da177e4SLinus Torvalds 
8411da177e4SLinus Torvalds 	case HCIDEVUP:
8421da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
843bf5b30b8SZhao Hongjiang 			return -EPERM;
8441da177e4SLinus Torvalds 		return hci_dev_open(arg);
8451da177e4SLinus Torvalds 
8461da177e4SLinus Torvalds 	case HCIDEVDOWN:
8471da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
848bf5b30b8SZhao Hongjiang 			return -EPERM;
8491da177e4SLinus Torvalds 		return hci_dev_close(arg);
8501da177e4SLinus Torvalds 
8511da177e4SLinus Torvalds 	case HCIDEVRESET:
8521da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
853bf5b30b8SZhao Hongjiang 			return -EPERM;
8541da177e4SLinus Torvalds 		return hci_dev_reset(arg);
8551da177e4SLinus Torvalds 
8561da177e4SLinus Torvalds 	case HCIDEVRESTAT:
8571da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
858bf5b30b8SZhao Hongjiang 			return -EPERM;
8591da177e4SLinus Torvalds 		return hci_dev_reset_stat(arg);
8601da177e4SLinus Torvalds 
8611da177e4SLinus Torvalds 	case HCISETSCAN:
8621da177e4SLinus Torvalds 	case HCISETAUTH:
8631da177e4SLinus Torvalds 	case HCISETENCRYPT:
8641da177e4SLinus Torvalds 	case HCISETPTYPE:
8651da177e4SLinus Torvalds 	case HCISETLINKPOL:
8661da177e4SLinus Torvalds 	case HCISETLINKMODE:
8671da177e4SLinus Torvalds 	case HCISETACLMTU:
8681da177e4SLinus Torvalds 	case HCISETSCOMTU:
8691da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
870bf5b30b8SZhao Hongjiang 			return -EPERM;
8711da177e4SLinus Torvalds 		return hci_dev_cmd(cmd, argp);
8721da177e4SLinus Torvalds 
8731da177e4SLinus Torvalds 	case HCIINQUIRY:
8741da177e4SLinus Torvalds 		return hci_inquiry(argp);
875c1c4f956SMarcel Holtmann 	}
8761da177e4SLinus Torvalds 
8771da177e4SLinus Torvalds 	lock_sock(sk);
878c1c4f956SMarcel Holtmann 
8791da177e4SLinus Torvalds 	err = hci_sock_bound_ioctl(sk, cmd, arg);
880c1c4f956SMarcel Holtmann 
881c1c4f956SMarcel Holtmann done:
8821da177e4SLinus Torvalds 	release_sock(sk);
8831da177e4SLinus Torvalds 	return err;
8841da177e4SLinus Torvalds }
8851da177e4SLinus Torvalds 
8868fc9ced3SGustavo Padovan static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
8878fc9ced3SGustavo Padovan 			 int addr_len)
8881da177e4SLinus Torvalds {
8890381101fSJohan Hedberg 	struct sockaddr_hci haddr;
8901da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
8911da177e4SLinus Torvalds 	struct hci_dev *hdev = NULL;
8920381101fSJohan Hedberg 	int len, err = 0;
8931da177e4SLinus Torvalds 
8941da177e4SLinus Torvalds 	BT_DBG("sock %p sk %p", sock, sk);
8951da177e4SLinus Torvalds 
8960381101fSJohan Hedberg 	if (!addr)
8970381101fSJohan Hedberg 		return -EINVAL;
8980381101fSJohan Hedberg 
8990381101fSJohan Hedberg 	memset(&haddr, 0, sizeof(haddr));
9000381101fSJohan Hedberg 	len = min_t(unsigned int, sizeof(haddr), addr_len);
9010381101fSJohan Hedberg 	memcpy(&haddr, addr, len);
9020381101fSJohan Hedberg 
9030381101fSJohan Hedberg 	if (haddr.hci_family != AF_BLUETOOTH)
9040381101fSJohan Hedberg 		return -EINVAL;
9050381101fSJohan Hedberg 
9061da177e4SLinus Torvalds 	lock_sock(sk);
9071da177e4SLinus Torvalds 
9087cc2ade2SMarcel Holtmann 	if (sk->sk_state == BT_BOUND) {
9097cc2ade2SMarcel Holtmann 		err = -EALREADY;
9107cc2ade2SMarcel Holtmann 		goto done;
9117cc2ade2SMarcel Holtmann 	}
9127cc2ade2SMarcel Holtmann 
9137cc2ade2SMarcel Holtmann 	switch (haddr.hci_channel) {
9147cc2ade2SMarcel Holtmann 	case HCI_CHANNEL_RAW:
9157cc2ade2SMarcel Holtmann 		if (hci_pi(sk)->hdev) {
9161da177e4SLinus Torvalds 			err = -EALREADY;
9171da177e4SLinus Torvalds 			goto done;
9181da177e4SLinus Torvalds 		}
9191da177e4SLinus Torvalds 
9200381101fSJohan Hedberg 		if (haddr.hci_dev != HCI_DEV_NONE) {
9210381101fSJohan Hedberg 			hdev = hci_dev_get(haddr.hci_dev);
92270f23020SAndrei Emeltchenko 			if (!hdev) {
9231da177e4SLinus Torvalds 				err = -ENODEV;
9241da177e4SLinus Torvalds 				goto done;
9251da177e4SLinus Torvalds 			}
9261da177e4SLinus Torvalds 
9271da177e4SLinus Torvalds 			atomic_inc(&hdev->promisc);
9281da177e4SLinus Torvalds 		}
9291da177e4SLinus Torvalds 
9301da177e4SLinus Torvalds 		hci_pi(sk)->hdev = hdev;
9317cc2ade2SMarcel Holtmann 		break;
9327cc2ade2SMarcel Holtmann 
93323500189SMarcel Holtmann 	case HCI_CHANNEL_USER:
93423500189SMarcel Holtmann 		if (hci_pi(sk)->hdev) {
93523500189SMarcel Holtmann 			err = -EALREADY;
93623500189SMarcel Holtmann 			goto done;
93723500189SMarcel Holtmann 		}
93823500189SMarcel Holtmann 
93923500189SMarcel Holtmann 		if (haddr.hci_dev == HCI_DEV_NONE) {
94023500189SMarcel Holtmann 			err = -EINVAL;
94123500189SMarcel Holtmann 			goto done;
94223500189SMarcel Holtmann 		}
94323500189SMarcel Holtmann 
94410a8b86fSMarcel Holtmann 		if (!capable(CAP_NET_ADMIN)) {
94523500189SMarcel Holtmann 			err = -EPERM;
94623500189SMarcel Holtmann 			goto done;
94723500189SMarcel Holtmann 		}
94823500189SMarcel Holtmann 
94923500189SMarcel Holtmann 		hdev = hci_dev_get(haddr.hci_dev);
95023500189SMarcel Holtmann 		if (!hdev) {
95123500189SMarcel Holtmann 			err = -ENODEV;
95223500189SMarcel Holtmann 			goto done;
95323500189SMarcel Holtmann 		}
95423500189SMarcel Holtmann 
955781f899fSMarcel Holtmann 		if (test_bit(HCI_INIT, &hdev->flags) ||
956d7a5a11dSMarcel Holtmann 		    hci_dev_test_flag(hdev, HCI_SETUP) ||
957781f899fSMarcel Holtmann 		    hci_dev_test_flag(hdev, HCI_CONFIG) ||
958781f899fSMarcel Holtmann 		    (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) &&
959781f899fSMarcel Holtmann 		     test_bit(HCI_UP, &hdev->flags))) {
96023500189SMarcel Holtmann 			err = -EBUSY;
96123500189SMarcel Holtmann 			hci_dev_put(hdev);
96223500189SMarcel Holtmann 			goto done;
96323500189SMarcel Holtmann 		}
96423500189SMarcel Holtmann 
965238be788SMarcel Holtmann 		if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) {
96623500189SMarcel Holtmann 			err = -EUSERS;
96723500189SMarcel Holtmann 			hci_dev_put(hdev);
96823500189SMarcel Holtmann 			goto done;
96923500189SMarcel Holtmann 		}
97023500189SMarcel Holtmann 
97123500189SMarcel Holtmann 		mgmt_index_removed(hdev);
97223500189SMarcel Holtmann 
97323500189SMarcel Holtmann 		err = hci_dev_open(hdev->id);
97423500189SMarcel Holtmann 		if (err) {
975781f899fSMarcel Holtmann 			if (err == -EALREADY) {
976781f899fSMarcel Holtmann 				/* In case the transport is already up and
977781f899fSMarcel Holtmann 				 * running, clear the error here.
978781f899fSMarcel Holtmann 				 *
979781f899fSMarcel Holtmann 				 * This can happen when opening an user
980781f899fSMarcel Holtmann 				 * channel and HCI_AUTO_OFF grace period
981781f899fSMarcel Holtmann 				 * is still active.
982781f899fSMarcel Holtmann 				 */
983781f899fSMarcel Holtmann 				err = 0;
984781f899fSMarcel Holtmann 			} else {
985a358dc11SMarcel Holtmann 				hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
986c6521401SMarcel Holtmann 				mgmt_index_added(hdev);
98723500189SMarcel Holtmann 				hci_dev_put(hdev);
98823500189SMarcel Holtmann 				goto done;
98923500189SMarcel Holtmann 			}
990781f899fSMarcel Holtmann 		}
99123500189SMarcel Holtmann 
99223500189SMarcel Holtmann 		atomic_inc(&hdev->promisc);
99323500189SMarcel Holtmann 
99423500189SMarcel Holtmann 		hci_pi(sk)->hdev = hdev;
99523500189SMarcel Holtmann 		break;
99623500189SMarcel Holtmann 
997cd82e61cSMarcel Holtmann 	case HCI_CHANNEL_MONITOR:
998cd82e61cSMarcel Holtmann 		if (haddr.hci_dev != HCI_DEV_NONE) {
999cd82e61cSMarcel Holtmann 			err = -EINVAL;
1000cd82e61cSMarcel Holtmann 			goto done;
1001cd82e61cSMarcel Holtmann 		}
1002cd82e61cSMarcel Holtmann 
1003cd82e61cSMarcel Holtmann 		if (!capable(CAP_NET_RAW)) {
1004cd82e61cSMarcel Holtmann 			err = -EPERM;
1005cd82e61cSMarcel Holtmann 			goto done;
1006cd82e61cSMarcel Holtmann 		}
1007cd82e61cSMarcel Holtmann 
100850ebc055SMarcel Holtmann 		/* The monitor interface is restricted to CAP_NET_RAW
100950ebc055SMarcel Holtmann 		 * capabilities and with that implicitly trusted.
101050ebc055SMarcel Holtmann 		 */
101150ebc055SMarcel Holtmann 		hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
101250ebc055SMarcel Holtmann 
1013787b306cSJohannes Berg 		send_monitor_note(sk, "Linux version %s (%s)",
1014787b306cSJohannes Berg 				  init_utsname()->release,
1015787b306cSJohannes Berg 				  init_utsname()->machine);
1016787b306cSJohannes Berg 		send_monitor_note(sk, "Bluetooth subsystem version %s",
1017dd31506dSMarcel Holtmann 				  BT_SUBSYS_VERSION);
1018cd82e61cSMarcel Holtmann 		send_monitor_replay(sk);
1019*249fa169SMarcel Holtmann 		send_monitor_control_replay(sk);
1020cd82e61cSMarcel Holtmann 
1021cd82e61cSMarcel Holtmann 		atomic_inc(&monitor_promisc);
1022cd82e61cSMarcel Holtmann 		break;
1023cd82e61cSMarcel Holtmann 
1024ac714949SMarcel Holtmann 	case HCI_CHANNEL_LOGGING:
1025ac714949SMarcel Holtmann 		if (haddr.hci_dev != HCI_DEV_NONE) {
1026ac714949SMarcel Holtmann 			err = -EINVAL;
1027ac714949SMarcel Holtmann 			goto done;
1028ac714949SMarcel Holtmann 		}
1029ac714949SMarcel Holtmann 
1030ac714949SMarcel Holtmann 		if (!capable(CAP_NET_ADMIN)) {
1031ac714949SMarcel Holtmann 			err = -EPERM;
1032ac714949SMarcel Holtmann 			goto done;
1033ac714949SMarcel Holtmann 		}
1034ac714949SMarcel Holtmann 		break;
1035ac714949SMarcel Holtmann 
10367cc2ade2SMarcel Holtmann 	default:
1037801c1e8dSJohan Hedberg 		if (!hci_mgmt_chan_find(haddr.hci_channel)) {
10387cc2ade2SMarcel Holtmann 			err = -EINVAL;
10397cc2ade2SMarcel Holtmann 			goto done;
10407cc2ade2SMarcel Holtmann 		}
10417cc2ade2SMarcel Holtmann 
1042801c1e8dSJohan Hedberg 		if (haddr.hci_dev != HCI_DEV_NONE) {
1043801c1e8dSJohan Hedberg 			err = -EINVAL;
1044801c1e8dSJohan Hedberg 			goto done;
1045801c1e8dSJohan Hedberg 		}
1046801c1e8dSJohan Hedberg 
10471195fbb8SMarcel Holtmann 		/* Users with CAP_NET_ADMIN capabilities are allowed
10481195fbb8SMarcel Holtmann 		 * access to all management commands and events. For
10491195fbb8SMarcel Holtmann 		 * untrusted users the interface is restricted and
10501195fbb8SMarcel Holtmann 		 * also only untrusted events are sent.
105150ebc055SMarcel Holtmann 		 */
10521195fbb8SMarcel Holtmann 		if (capable(CAP_NET_ADMIN))
105350ebc055SMarcel Holtmann 			hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
105450ebc055SMarcel Holtmann 
1055f9207338SMarcel Holtmann 		/* At the moment the index and unconfigured index events
1056f9207338SMarcel Holtmann 		 * are enabled unconditionally. Setting them on each
1057f9207338SMarcel Holtmann 		 * socket when binding keeps this functionality. They
1058f9207338SMarcel Holtmann 		 * however might be cleared later and then sending of these
1059f9207338SMarcel Holtmann 		 * events will be disabled, but that is then intentional.
1060f6b7712eSMarcel Holtmann 		 *
1061f6b7712eSMarcel Holtmann 		 * This also enables generic events that are safe to be
1062f6b7712eSMarcel Holtmann 		 * received by untrusted users. Example for such events
1063f6b7712eSMarcel Holtmann 		 * are changes to settings, class of device, name etc.
1064f9207338SMarcel Holtmann 		 */
1065f9207338SMarcel Holtmann 		if (haddr.hci_channel == HCI_CHANNEL_CONTROL) {
1066*249fa169SMarcel Holtmann 			struct sk_buff *skb;
106770ecce91SMarcel Holtmann 			int id;
106870ecce91SMarcel Holtmann 
106970ecce91SMarcel Holtmann 			id = ida_simple_get(&sock_cookie_ida, 1, 0, GFP_KERNEL);
107070ecce91SMarcel Holtmann 			if (id < 0)
107170ecce91SMarcel Holtmann 				id = 0xffffffff;
107270ecce91SMarcel Holtmann 
107370ecce91SMarcel Holtmann 			hci_pi(sk)->cookie = id;
107470ecce91SMarcel Holtmann 			get_task_comm(hci_pi(sk)->comm, current);
107570ecce91SMarcel Holtmann 
1076*249fa169SMarcel Holtmann 			/* Send event to monitor */
1077*249fa169SMarcel Holtmann 			skb = create_monitor_ctrl_open(sk);
1078*249fa169SMarcel Holtmann 			if (skb) {
1079*249fa169SMarcel Holtmann 				hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
1080*249fa169SMarcel Holtmann 						    HCI_SOCK_TRUSTED, NULL);
1081*249fa169SMarcel Holtmann 				kfree_skb(skb);
1082*249fa169SMarcel Holtmann 			}
1083*249fa169SMarcel Holtmann 
1084f9207338SMarcel Holtmann 			hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS);
1085f9207338SMarcel Holtmann 			hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
1086f6b7712eSMarcel Holtmann 			hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS);
1087f9207338SMarcel Holtmann 		}
1088801c1e8dSJohan Hedberg 		break;
1089801c1e8dSJohan Hedberg 	}
1090801c1e8dSJohan Hedberg 
10917cc2ade2SMarcel Holtmann 
10927cc2ade2SMarcel Holtmann 	hci_pi(sk)->channel = haddr.hci_channel;
10931da177e4SLinus Torvalds 	sk->sk_state = BT_BOUND;
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds done:
10961da177e4SLinus Torvalds 	release_sock(sk);
10971da177e4SLinus Torvalds 	return err;
10981da177e4SLinus Torvalds }
10991da177e4SLinus Torvalds 
11008fc9ced3SGustavo Padovan static int hci_sock_getname(struct socket *sock, struct sockaddr *addr,
11018fc9ced3SGustavo Padovan 			    int *addr_len, int peer)
11021da177e4SLinus Torvalds {
11031da177e4SLinus Torvalds 	struct sockaddr_hci *haddr = (struct sockaddr_hci *)addr;
11041da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
11059d4b68b2SMarcel Holtmann 	struct hci_dev *hdev;
11069d4b68b2SMarcel Holtmann 	int err = 0;
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	BT_DBG("sock %p sk %p", sock, sk);
11091da177e4SLinus Torvalds 
111006f43cbcSMarcel Holtmann 	if (peer)
111106f43cbcSMarcel Holtmann 		return -EOPNOTSUPP;
111206f43cbcSMarcel Holtmann 
11131da177e4SLinus Torvalds 	lock_sock(sk);
11141da177e4SLinus Torvalds 
11159d4b68b2SMarcel Holtmann 	hdev = hci_pi(sk)->hdev;
11169d4b68b2SMarcel Holtmann 	if (!hdev) {
11179d4b68b2SMarcel Holtmann 		err = -EBADFD;
11189d4b68b2SMarcel Holtmann 		goto done;
11199d4b68b2SMarcel Holtmann 	}
11209d4b68b2SMarcel Holtmann 
11211da177e4SLinus Torvalds 	*addr_len = sizeof(*haddr);
11221da177e4SLinus Torvalds 	haddr->hci_family = AF_BLUETOOTH;
11237b005bd3SMarcel Holtmann 	haddr->hci_dev    = hdev->id;
11249d4b68b2SMarcel Holtmann 	haddr->hci_channel= hci_pi(sk)->channel;
11251da177e4SLinus Torvalds 
11269d4b68b2SMarcel Holtmann done:
11271da177e4SLinus Torvalds 	release_sock(sk);
11289d4b68b2SMarcel Holtmann 	return err;
11291da177e4SLinus Torvalds }
11301da177e4SLinus Torvalds 
11316039aa73SGustavo Padovan static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg,
11326039aa73SGustavo Padovan 			  struct sk_buff *skb)
11331da177e4SLinus Torvalds {
11341da177e4SLinus Torvalds 	__u32 mask = hci_pi(sk)->cmsg_mask;
11351da177e4SLinus Torvalds 
11360d48d939SMarcel Holtmann 	if (mask & HCI_CMSG_DIR) {
11370d48d939SMarcel Holtmann 		int incoming = bt_cb(skb)->incoming;
11388fc9ced3SGustavo Padovan 		put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming),
11398fc9ced3SGustavo Padovan 			 &incoming);
11400d48d939SMarcel Holtmann 	}
11411da177e4SLinus Torvalds 
1142a61bbcf2SPatrick McHardy 	if (mask & HCI_CMSG_TSTAMP) {
1143f6e623a6SJohann Felix Soden #ifdef CONFIG_COMPAT
1144f6e623a6SJohann Felix Soden 		struct compat_timeval ctv;
1145f6e623a6SJohann Felix Soden #endif
1146a61bbcf2SPatrick McHardy 		struct timeval tv;
1147767c5eb5SMarcel Holtmann 		void *data;
1148767c5eb5SMarcel Holtmann 		int len;
1149a61bbcf2SPatrick McHardy 
1150a61bbcf2SPatrick McHardy 		skb_get_timestamp(skb, &tv);
1151767c5eb5SMarcel Holtmann 
11521da97f83SDavid S. Miller 		data = &tv;
11531da97f83SDavid S. Miller 		len = sizeof(tv);
11541da97f83SDavid S. Miller #ifdef CONFIG_COMPAT
1155da88cea1SH. J. Lu 		if (!COMPAT_USE_64BIT_TIME &&
1156da88cea1SH. J. Lu 		    (msg->msg_flags & MSG_CMSG_COMPAT)) {
1157767c5eb5SMarcel Holtmann 			ctv.tv_sec = tv.tv_sec;
1158767c5eb5SMarcel Holtmann 			ctv.tv_usec = tv.tv_usec;
1159767c5eb5SMarcel Holtmann 			data = &ctv;
1160767c5eb5SMarcel Holtmann 			len = sizeof(ctv);
1161767c5eb5SMarcel Holtmann 		}
11621da97f83SDavid S. Miller #endif
1163767c5eb5SMarcel Holtmann 
1164767c5eb5SMarcel Holtmann 		put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
1165a61bbcf2SPatrick McHardy 	}
11661da177e4SLinus Torvalds }
11671da177e4SLinus Torvalds 
11688528d3f7SMarcel Holtmann static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
11698528d3f7SMarcel Holtmann 			    size_t len, int flags)
11701da177e4SLinus Torvalds {
11711da177e4SLinus Torvalds 	int noblock = flags & MSG_DONTWAIT;
11721da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
11731da177e4SLinus Torvalds 	struct sk_buff *skb;
11741da177e4SLinus Torvalds 	int copied, err;
117583871f8cSDenis Kenzior 	unsigned int skblen;
11761da177e4SLinus Torvalds 
11771da177e4SLinus Torvalds 	BT_DBG("sock %p, sk %p", sock, sk);
11781da177e4SLinus Torvalds 
1179d94a6104SMarcel Holtmann 	if (flags & MSG_OOB)
11801da177e4SLinus Torvalds 		return -EOPNOTSUPP;
11811da177e4SLinus Torvalds 
1182ac714949SMarcel Holtmann 	if (hci_pi(sk)->channel == HCI_CHANNEL_LOGGING)
1183ac714949SMarcel Holtmann 		return -EOPNOTSUPP;
1184ac714949SMarcel Holtmann 
11851da177e4SLinus Torvalds 	if (sk->sk_state == BT_CLOSED)
11861da177e4SLinus Torvalds 		return 0;
11871da177e4SLinus Torvalds 
118870f23020SAndrei Emeltchenko 	skb = skb_recv_datagram(sk, flags, noblock, &err);
118970f23020SAndrei Emeltchenko 	if (!skb)
11901da177e4SLinus Torvalds 		return err;
11911da177e4SLinus Torvalds 
119283871f8cSDenis Kenzior 	skblen = skb->len;
11931da177e4SLinus Torvalds 	copied = skb->len;
11941da177e4SLinus Torvalds 	if (len < copied) {
11951da177e4SLinus Torvalds 		msg->msg_flags |= MSG_TRUNC;
11961da177e4SLinus Torvalds 		copied = len;
11971da177e4SLinus Torvalds 	}
11981da177e4SLinus Torvalds 
1199badff6d0SArnaldo Carvalho de Melo 	skb_reset_transport_header(skb);
120051f3d02bSDavid S. Miller 	err = skb_copy_datagram_msg(skb, 0, msg, copied);
12011da177e4SLinus Torvalds 
12023a208627SMarcel Holtmann 	switch (hci_pi(sk)->channel) {
12033a208627SMarcel Holtmann 	case HCI_CHANNEL_RAW:
12041da177e4SLinus Torvalds 		hci_sock_cmsg(sk, msg, skb);
12053a208627SMarcel Holtmann 		break;
120623500189SMarcel Holtmann 	case HCI_CHANNEL_USER:
1207cd82e61cSMarcel Holtmann 	case HCI_CHANNEL_MONITOR:
1208cd82e61cSMarcel Holtmann 		sock_recv_timestamp(msg, sk, skb);
1209cd82e61cSMarcel Holtmann 		break;
1210801c1e8dSJohan Hedberg 	default:
1211801c1e8dSJohan Hedberg 		if (hci_mgmt_chan_find(hci_pi(sk)->channel))
1212801c1e8dSJohan Hedberg 			sock_recv_timestamp(msg, sk, skb);
1213801c1e8dSJohan Hedberg 		break;
12143a208627SMarcel Holtmann 	}
12151da177e4SLinus Torvalds 
12161da177e4SLinus Torvalds 	skb_free_datagram(sk, skb);
12171da177e4SLinus Torvalds 
12184f34228bSLuiz Augusto von Dentz 	if (flags & MSG_TRUNC)
121983871f8cSDenis Kenzior 		copied = skblen;
122083871f8cSDenis Kenzior 
12211da177e4SLinus Torvalds 	return err ? : copied;
12221da177e4SLinus Torvalds }
12231da177e4SLinus Torvalds 
1224fa4335d7SJohan Hedberg static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk,
1225fa4335d7SJohan Hedberg 			struct msghdr *msg, size_t msglen)
1226fa4335d7SJohan Hedberg {
1227fa4335d7SJohan Hedberg 	void *buf;
1228fa4335d7SJohan Hedberg 	u8 *cp;
1229fa4335d7SJohan Hedberg 	struct mgmt_hdr *hdr;
1230fa4335d7SJohan Hedberg 	u16 opcode, index, len;
1231fa4335d7SJohan Hedberg 	struct hci_dev *hdev = NULL;
1232fa4335d7SJohan Hedberg 	const struct hci_mgmt_handler *handler;
1233fa4335d7SJohan Hedberg 	bool var_len, no_hdev;
1234fa4335d7SJohan Hedberg 	int err;
1235fa4335d7SJohan Hedberg 
1236fa4335d7SJohan Hedberg 	BT_DBG("got %zu bytes", msglen);
1237fa4335d7SJohan Hedberg 
1238fa4335d7SJohan Hedberg 	if (msglen < sizeof(*hdr))
1239fa4335d7SJohan Hedberg 		return -EINVAL;
1240fa4335d7SJohan Hedberg 
1241fa4335d7SJohan Hedberg 	buf = kmalloc(msglen, GFP_KERNEL);
1242fa4335d7SJohan Hedberg 	if (!buf)
1243fa4335d7SJohan Hedberg 		return -ENOMEM;
1244fa4335d7SJohan Hedberg 
1245fa4335d7SJohan Hedberg 	if (memcpy_from_msg(buf, msg, msglen)) {
1246fa4335d7SJohan Hedberg 		err = -EFAULT;
1247fa4335d7SJohan Hedberg 		goto done;
1248fa4335d7SJohan Hedberg 	}
1249fa4335d7SJohan Hedberg 
1250fa4335d7SJohan Hedberg 	hdr = buf;
1251fa4335d7SJohan Hedberg 	opcode = __le16_to_cpu(hdr->opcode);
1252fa4335d7SJohan Hedberg 	index = __le16_to_cpu(hdr->index);
1253fa4335d7SJohan Hedberg 	len = __le16_to_cpu(hdr->len);
1254fa4335d7SJohan Hedberg 
1255fa4335d7SJohan Hedberg 	if (len != msglen - sizeof(*hdr)) {
1256fa4335d7SJohan Hedberg 		err = -EINVAL;
1257fa4335d7SJohan Hedberg 		goto done;
1258fa4335d7SJohan Hedberg 	}
1259fa4335d7SJohan Hedberg 
1260fa4335d7SJohan Hedberg 	if (opcode >= chan->handler_count ||
1261fa4335d7SJohan Hedberg 	    chan->handlers[opcode].func == NULL) {
1262fa4335d7SJohan Hedberg 		BT_DBG("Unknown op %u", opcode);
1263fa4335d7SJohan Hedberg 		err = mgmt_cmd_status(sk, index, opcode,
1264fa4335d7SJohan Hedberg 				      MGMT_STATUS_UNKNOWN_COMMAND);
1265fa4335d7SJohan Hedberg 		goto done;
1266fa4335d7SJohan Hedberg 	}
1267fa4335d7SJohan Hedberg 
1268fa4335d7SJohan Hedberg 	handler = &chan->handlers[opcode];
1269fa4335d7SJohan Hedberg 
1270fa4335d7SJohan Hedberg 	if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) &&
1271fa4335d7SJohan Hedberg 	    !(handler->flags & HCI_MGMT_UNTRUSTED)) {
1272fa4335d7SJohan Hedberg 		err = mgmt_cmd_status(sk, index, opcode,
1273fa4335d7SJohan Hedberg 				      MGMT_STATUS_PERMISSION_DENIED);
1274fa4335d7SJohan Hedberg 		goto done;
1275fa4335d7SJohan Hedberg 	}
1276fa4335d7SJohan Hedberg 
1277fa4335d7SJohan Hedberg 	if (index != MGMT_INDEX_NONE) {
1278fa4335d7SJohan Hedberg 		hdev = hci_dev_get(index);
1279fa4335d7SJohan Hedberg 		if (!hdev) {
1280fa4335d7SJohan Hedberg 			err = mgmt_cmd_status(sk, index, opcode,
1281fa4335d7SJohan Hedberg 					      MGMT_STATUS_INVALID_INDEX);
1282fa4335d7SJohan Hedberg 			goto done;
1283fa4335d7SJohan Hedberg 		}
1284fa4335d7SJohan Hedberg 
1285fa4335d7SJohan Hedberg 		if (hci_dev_test_flag(hdev, HCI_SETUP) ||
1286fa4335d7SJohan Hedberg 		    hci_dev_test_flag(hdev, HCI_CONFIG) ||
1287fa4335d7SJohan Hedberg 		    hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
1288fa4335d7SJohan Hedberg 			err = mgmt_cmd_status(sk, index, opcode,
1289fa4335d7SJohan Hedberg 					      MGMT_STATUS_INVALID_INDEX);
1290fa4335d7SJohan Hedberg 			goto done;
1291fa4335d7SJohan Hedberg 		}
1292fa4335d7SJohan Hedberg 
1293fa4335d7SJohan Hedberg 		if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
1294fa4335d7SJohan Hedberg 		    !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
1295fa4335d7SJohan Hedberg 			err = mgmt_cmd_status(sk, index, opcode,
1296fa4335d7SJohan Hedberg 					      MGMT_STATUS_INVALID_INDEX);
1297fa4335d7SJohan Hedberg 			goto done;
1298fa4335d7SJohan Hedberg 		}
1299fa4335d7SJohan Hedberg 	}
1300fa4335d7SJohan Hedberg 
1301fa4335d7SJohan Hedberg 	no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
1302fa4335d7SJohan Hedberg 	if (no_hdev != !hdev) {
1303fa4335d7SJohan Hedberg 		err = mgmt_cmd_status(sk, index, opcode,
1304fa4335d7SJohan Hedberg 				      MGMT_STATUS_INVALID_INDEX);
1305fa4335d7SJohan Hedberg 		goto done;
1306fa4335d7SJohan Hedberg 	}
1307fa4335d7SJohan Hedberg 
1308fa4335d7SJohan Hedberg 	var_len = (handler->flags & HCI_MGMT_VAR_LEN);
1309fa4335d7SJohan Hedberg 	if ((var_len && len < handler->data_len) ||
1310fa4335d7SJohan Hedberg 	    (!var_len && len != handler->data_len)) {
1311fa4335d7SJohan Hedberg 		err = mgmt_cmd_status(sk, index, opcode,
1312fa4335d7SJohan Hedberg 				      MGMT_STATUS_INVALID_PARAMS);
1313fa4335d7SJohan Hedberg 		goto done;
1314fa4335d7SJohan Hedberg 	}
1315fa4335d7SJohan Hedberg 
1316fa4335d7SJohan Hedberg 	if (hdev && chan->hdev_init)
1317fa4335d7SJohan Hedberg 		chan->hdev_init(sk, hdev);
1318fa4335d7SJohan Hedberg 
1319fa4335d7SJohan Hedberg 	cp = buf + sizeof(*hdr);
1320fa4335d7SJohan Hedberg 
1321fa4335d7SJohan Hedberg 	err = handler->func(sk, hdev, cp, len);
1322fa4335d7SJohan Hedberg 	if (err < 0)
1323fa4335d7SJohan Hedberg 		goto done;
1324fa4335d7SJohan Hedberg 
1325fa4335d7SJohan Hedberg 	err = msglen;
1326fa4335d7SJohan Hedberg 
1327fa4335d7SJohan Hedberg done:
1328fa4335d7SJohan Hedberg 	if (hdev)
1329fa4335d7SJohan Hedberg 		hci_dev_put(hdev);
1330fa4335d7SJohan Hedberg 
1331fa4335d7SJohan Hedberg 	kfree(buf);
1332fa4335d7SJohan Hedberg 	return err;
1333fa4335d7SJohan Hedberg }
1334fa4335d7SJohan Hedberg 
1335ac714949SMarcel Holtmann static int hci_logging_frame(struct sock *sk, struct msghdr *msg, int len)
1336ac714949SMarcel Holtmann {
1337ac714949SMarcel Holtmann 	struct hci_mon_hdr *hdr;
1338ac714949SMarcel Holtmann 	struct sk_buff *skb;
1339ac714949SMarcel Holtmann 	struct hci_dev *hdev;
1340ac714949SMarcel Holtmann 	u16 index;
1341ac714949SMarcel Holtmann 	int err;
1342ac714949SMarcel Holtmann 
1343ac714949SMarcel Holtmann 	/* The logging frame consists at minimum of the standard header,
1344ac714949SMarcel Holtmann 	 * the priority byte, the ident length byte and at least one string
1345ac714949SMarcel Holtmann 	 * terminator NUL byte. Anything shorter are invalid packets.
1346ac714949SMarcel Holtmann 	 */
1347ac714949SMarcel Holtmann 	if (len < sizeof(*hdr) + 3)
1348ac714949SMarcel Holtmann 		return -EINVAL;
1349ac714949SMarcel Holtmann 
1350ac714949SMarcel Holtmann 	skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
1351ac714949SMarcel Holtmann 	if (!skb)
1352ac714949SMarcel Holtmann 		return err;
1353ac714949SMarcel Holtmann 
1354ac714949SMarcel Holtmann 	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
1355ac714949SMarcel Holtmann 		err = -EFAULT;
1356ac714949SMarcel Holtmann 		goto drop;
1357ac714949SMarcel Holtmann 	}
1358ac714949SMarcel Holtmann 
1359ac714949SMarcel Holtmann 	hdr = (void *)skb->data;
1360ac714949SMarcel Holtmann 
1361ac714949SMarcel Holtmann 	if (__le16_to_cpu(hdr->len) != len - sizeof(*hdr)) {
1362ac714949SMarcel Holtmann 		err = -EINVAL;
1363ac714949SMarcel Holtmann 		goto drop;
1364ac714949SMarcel Holtmann 	}
1365ac714949SMarcel Holtmann 
1366ac714949SMarcel Holtmann 	if (__le16_to_cpu(hdr->opcode) == 0x0000) {
1367ac714949SMarcel Holtmann 		__u8 priority = skb->data[sizeof(*hdr)];
1368ac714949SMarcel Holtmann 		__u8 ident_len = skb->data[sizeof(*hdr) + 1];
1369ac714949SMarcel Holtmann 
1370ac714949SMarcel Holtmann 		/* Only the priorities 0-7 are valid and with that any other
1371ac714949SMarcel Holtmann 		 * value results in an invalid packet.
1372ac714949SMarcel Holtmann 		 *
1373ac714949SMarcel Holtmann 		 * The priority byte is followed by an ident length byte and
1374ac714949SMarcel Holtmann 		 * the NUL terminated ident string. Check that the ident
1375ac714949SMarcel Holtmann 		 * length is not overflowing the packet and also that the
1376ac714949SMarcel Holtmann 		 * ident string itself is NUL terminated. In case the ident
1377ac714949SMarcel Holtmann 		 * length is zero, the length value actually doubles as NUL
1378ac714949SMarcel Holtmann 		 * terminator identifier.
1379ac714949SMarcel Holtmann 		 *
1380ac714949SMarcel Holtmann 		 * The message follows the ident string (if present) and
1381ac714949SMarcel Holtmann 		 * must be NUL terminated. Otherwise it is not a valid packet.
1382ac714949SMarcel Holtmann 		 */
1383ac714949SMarcel Holtmann 		if (priority > 7 || skb->data[len - 1] != 0x00 ||
1384ac714949SMarcel Holtmann 		    ident_len > len - sizeof(*hdr) - 3 ||
1385ac714949SMarcel Holtmann 		    skb->data[sizeof(*hdr) + ident_len + 1] != 0x00) {
1386ac714949SMarcel Holtmann 			err = -EINVAL;
1387ac714949SMarcel Holtmann 			goto drop;
1388ac714949SMarcel Holtmann 		}
1389ac714949SMarcel Holtmann 	} else {
1390ac714949SMarcel Holtmann 		err = -EINVAL;
1391ac714949SMarcel Holtmann 		goto drop;
1392ac714949SMarcel Holtmann 	}
1393ac714949SMarcel Holtmann 
1394ac714949SMarcel Holtmann 	index = __le16_to_cpu(hdr->index);
1395ac714949SMarcel Holtmann 
1396ac714949SMarcel Holtmann 	if (index != MGMT_INDEX_NONE) {
1397ac714949SMarcel Holtmann 		hdev = hci_dev_get(index);
1398ac714949SMarcel Holtmann 		if (!hdev) {
1399ac714949SMarcel Holtmann 			err = -ENODEV;
1400ac714949SMarcel Holtmann 			goto drop;
1401ac714949SMarcel Holtmann 		}
1402ac714949SMarcel Holtmann 	} else {
1403ac714949SMarcel Holtmann 		hdev = NULL;
1404ac714949SMarcel Holtmann 	}
1405ac714949SMarcel Holtmann 
1406ac714949SMarcel Holtmann 	hdr->opcode = cpu_to_le16(HCI_MON_USER_LOGGING);
1407ac714949SMarcel Holtmann 
1408ac714949SMarcel Holtmann 	hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, HCI_SOCK_TRUSTED, NULL);
1409ac714949SMarcel Holtmann 	err = len;
1410ac714949SMarcel Holtmann 
1411ac714949SMarcel Holtmann 	if (hdev)
1412ac714949SMarcel Holtmann 		hci_dev_put(hdev);
1413ac714949SMarcel Holtmann 
1414ac714949SMarcel Holtmann drop:
1415ac714949SMarcel Holtmann 	kfree_skb(skb);
1416ac714949SMarcel Holtmann 	return err;
1417ac714949SMarcel Holtmann }
1418ac714949SMarcel Holtmann 
14191b784140SYing Xue static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
14201b784140SYing Xue 			    size_t len)
14211da177e4SLinus Torvalds {
14221da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
1423801c1e8dSJohan Hedberg 	struct hci_mgmt_chan *chan;
14241da177e4SLinus Torvalds 	struct hci_dev *hdev;
14251da177e4SLinus Torvalds 	struct sk_buff *skb;
14261da177e4SLinus Torvalds 	int err;
14271da177e4SLinus Torvalds 
14281da177e4SLinus Torvalds 	BT_DBG("sock %p sk %p", sock, sk);
14291da177e4SLinus Torvalds 
14301da177e4SLinus Torvalds 	if (msg->msg_flags & MSG_OOB)
14311da177e4SLinus Torvalds 		return -EOPNOTSUPP;
14321da177e4SLinus Torvalds 
14331da177e4SLinus Torvalds 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
14341da177e4SLinus Torvalds 		return -EINVAL;
14351da177e4SLinus Torvalds 
14361da177e4SLinus Torvalds 	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
14371da177e4SLinus Torvalds 		return -EINVAL;
14381da177e4SLinus Torvalds 
14391da177e4SLinus Torvalds 	lock_sock(sk);
14401da177e4SLinus Torvalds 
14410381101fSJohan Hedberg 	switch (hci_pi(sk)->channel) {
14420381101fSJohan Hedberg 	case HCI_CHANNEL_RAW:
144323500189SMarcel Holtmann 	case HCI_CHANNEL_USER:
14440381101fSJohan Hedberg 		break;
1445cd82e61cSMarcel Holtmann 	case HCI_CHANNEL_MONITOR:
1446cd82e61cSMarcel Holtmann 		err = -EOPNOTSUPP;
1447cd82e61cSMarcel Holtmann 		goto done;
1448ac714949SMarcel Holtmann 	case HCI_CHANNEL_LOGGING:
1449ac714949SMarcel Holtmann 		err = hci_logging_frame(sk, msg, len);
1450ac714949SMarcel Holtmann 		goto done;
14510381101fSJohan Hedberg 	default:
1452801c1e8dSJohan Hedberg 		mutex_lock(&mgmt_chan_list_lock);
1453801c1e8dSJohan Hedberg 		chan = __hci_mgmt_chan_find(hci_pi(sk)->channel);
1454801c1e8dSJohan Hedberg 		if (chan)
1455fa4335d7SJohan Hedberg 			err = hci_mgmt_cmd(chan, sk, msg, len);
1456801c1e8dSJohan Hedberg 		else
14570381101fSJohan Hedberg 			err = -EINVAL;
1458801c1e8dSJohan Hedberg 
1459801c1e8dSJohan Hedberg 		mutex_unlock(&mgmt_chan_list_lock);
14600381101fSJohan Hedberg 		goto done;
14610381101fSJohan Hedberg 	}
14620381101fSJohan Hedberg 
146370f23020SAndrei Emeltchenko 	hdev = hci_pi(sk)->hdev;
146470f23020SAndrei Emeltchenko 	if (!hdev) {
14651da177e4SLinus Torvalds 		err = -EBADFD;
14661da177e4SLinus Torvalds 		goto done;
14671da177e4SLinus Torvalds 	}
14681da177e4SLinus Torvalds 
14697e21addcSMarcel Holtmann 	if (!test_bit(HCI_UP, &hdev->flags)) {
14707e21addcSMarcel Holtmann 		err = -ENETDOWN;
14717e21addcSMarcel Holtmann 		goto done;
14727e21addcSMarcel Holtmann 	}
14737e21addcSMarcel Holtmann 
147470f23020SAndrei Emeltchenko 	skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
147570f23020SAndrei Emeltchenko 	if (!skb)
14761da177e4SLinus Torvalds 		goto done;
14771da177e4SLinus Torvalds 
14786ce8e9ceSAl Viro 	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
14791da177e4SLinus Torvalds 		err = -EFAULT;
14801da177e4SLinus Torvalds 		goto drop;
14811da177e4SLinus Torvalds 	}
14821da177e4SLinus Torvalds 
14838528d3f7SMarcel Holtmann 	hci_skb_pkt_type(skb) = skb->data[0];
14841da177e4SLinus Torvalds 	skb_pull(skb, 1);
14851da177e4SLinus Torvalds 
14861bc5ad16SMarcel Holtmann 	if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
14871bc5ad16SMarcel Holtmann 		/* No permission check is needed for user channel
14881bc5ad16SMarcel Holtmann 		 * since that gets enforced when binding the socket.
14891bc5ad16SMarcel Holtmann 		 *
14901bc5ad16SMarcel Holtmann 		 * However check that the packet type is valid.
14911bc5ad16SMarcel Holtmann 		 */
1492d79f34e3SMarcel Holtmann 		if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT &&
1493d79f34e3SMarcel Holtmann 		    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
1494d79f34e3SMarcel Holtmann 		    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) {
14951bc5ad16SMarcel Holtmann 			err = -EINVAL;
14961bc5ad16SMarcel Holtmann 			goto drop;
14971bc5ad16SMarcel Holtmann 		}
14981bc5ad16SMarcel Holtmann 
14991bc5ad16SMarcel Holtmann 		skb_queue_tail(&hdev->raw_q, skb);
15001bc5ad16SMarcel Holtmann 		queue_work(hdev->workqueue, &hdev->tx_work);
1501d79f34e3SMarcel Holtmann 	} else if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) {
150283985319SHarvey Harrison 		u16 opcode = get_unaligned_le16(skb->data);
15031da177e4SLinus Torvalds 		u16 ogf = hci_opcode_ogf(opcode);
15041da177e4SLinus Torvalds 		u16 ocf = hci_opcode_ocf(opcode);
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds 		if (((ogf > HCI_SFLT_MAX_OGF) ||
15073bb3c755SGustavo Padovan 		     !hci_test_bit(ocf & HCI_FLT_OCF_BITS,
15083bb3c755SGustavo Padovan 				   &hci_sec_filter.ocf_mask[ogf])) &&
15091da177e4SLinus Torvalds 		    !capable(CAP_NET_RAW)) {
15101da177e4SLinus Torvalds 			err = -EPERM;
15111da177e4SLinus Torvalds 			goto drop;
15121da177e4SLinus Torvalds 		}
15131da177e4SLinus Torvalds 
15141982162bSMarcel Holtmann 		/* Since the opcode has already been extracted here, store
15151982162bSMarcel Holtmann 		 * a copy of the value for later use by the drivers.
15161982162bSMarcel Holtmann 		 */
15171982162bSMarcel Holtmann 		hci_skb_opcode(skb) = opcode;
15181982162bSMarcel Holtmann 
1519fee746b0SMarcel Holtmann 		if (ogf == 0x3f) {
15201da177e4SLinus Torvalds 			skb_queue_tail(&hdev->raw_q, skb);
15213eff45eaSGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->tx_work);
15221da177e4SLinus Torvalds 		} else {
152349c922bbSStephen Hemminger 			/* Stand-alone HCI commands must be flagged as
152411714b3dSJohan Hedberg 			 * single-command requests.
152511714b3dSJohan Hedberg 			 */
152644d27137SJohan Hedberg 			bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
152711714b3dSJohan Hedberg 
15281da177e4SLinus Torvalds 			skb_queue_tail(&hdev->cmd_q, skb);
1529c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
15301da177e4SLinus Torvalds 		}
15311da177e4SLinus Torvalds 	} else {
15321da177e4SLinus Torvalds 		if (!capable(CAP_NET_RAW)) {
15331da177e4SLinus Torvalds 			err = -EPERM;
15341da177e4SLinus Torvalds 			goto drop;
15351da177e4SLinus Torvalds 		}
15361da177e4SLinus Torvalds 
1537d79f34e3SMarcel Holtmann 		if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
1538d79f34e3SMarcel Holtmann 		    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) {
1539bb77543eSMarcel Holtmann 			err = -EINVAL;
1540bb77543eSMarcel Holtmann 			goto drop;
1541bb77543eSMarcel Holtmann 		}
1542bb77543eSMarcel Holtmann 
15431da177e4SLinus Torvalds 		skb_queue_tail(&hdev->raw_q, skb);
15443eff45eaSGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->tx_work);
15451da177e4SLinus Torvalds 	}
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds 	err = len;
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds done:
15501da177e4SLinus Torvalds 	release_sock(sk);
15511da177e4SLinus Torvalds 	return err;
15521da177e4SLinus Torvalds 
15531da177e4SLinus Torvalds drop:
15541da177e4SLinus Torvalds 	kfree_skb(skb);
15551da177e4SLinus Torvalds 	goto done;
15561da177e4SLinus Torvalds }
15571da177e4SLinus Torvalds 
15588fc9ced3SGustavo Padovan static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
15598fc9ced3SGustavo Padovan 			       char __user *optval, unsigned int len)
15601da177e4SLinus Torvalds {
15611da177e4SLinus Torvalds 	struct hci_ufilter uf = { .opcode = 0 };
15621da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
15631da177e4SLinus Torvalds 	int err = 0, opt = 0;
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds 	BT_DBG("sk %p, opt %d", sk, optname);
15661da177e4SLinus Torvalds 
156747b0f573SMarcel Holtmann 	if (level != SOL_HCI)
156847b0f573SMarcel Holtmann 		return -ENOPROTOOPT;
156947b0f573SMarcel Holtmann 
15701da177e4SLinus Torvalds 	lock_sock(sk);
15711da177e4SLinus Torvalds 
15722f39cdb7SMarcel Holtmann 	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
1573c2371e80SMarcel Holtmann 		err = -EBADFD;
15742f39cdb7SMarcel Holtmann 		goto done;
15752f39cdb7SMarcel Holtmann 	}
15762f39cdb7SMarcel Holtmann 
15771da177e4SLinus Torvalds 	switch (optname) {
15781da177e4SLinus Torvalds 	case HCI_DATA_DIR:
15791da177e4SLinus Torvalds 		if (get_user(opt, (int __user *)optval)) {
15801da177e4SLinus Torvalds 			err = -EFAULT;
15811da177e4SLinus Torvalds 			break;
15821da177e4SLinus Torvalds 		}
15831da177e4SLinus Torvalds 
15841da177e4SLinus Torvalds 		if (opt)
15851da177e4SLinus Torvalds 			hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
15861da177e4SLinus Torvalds 		else
15871da177e4SLinus Torvalds 			hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
15881da177e4SLinus Torvalds 		break;
15891da177e4SLinus Torvalds 
15901da177e4SLinus Torvalds 	case HCI_TIME_STAMP:
15911da177e4SLinus Torvalds 		if (get_user(opt, (int __user *)optval)) {
15921da177e4SLinus Torvalds 			err = -EFAULT;
15931da177e4SLinus Torvalds 			break;
15941da177e4SLinus Torvalds 		}
15951da177e4SLinus Torvalds 
15961da177e4SLinus Torvalds 		if (opt)
15971da177e4SLinus Torvalds 			hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
15981da177e4SLinus Torvalds 		else
15991da177e4SLinus Torvalds 			hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
16001da177e4SLinus Torvalds 		break;
16011da177e4SLinus Torvalds 
16021da177e4SLinus Torvalds 	case HCI_FILTER:
16030878b666SMarcel Holtmann 		{
16040878b666SMarcel Holtmann 			struct hci_filter *f = &hci_pi(sk)->filter;
16050878b666SMarcel Holtmann 
16060878b666SMarcel Holtmann 			uf.type_mask = f->type_mask;
16070878b666SMarcel Holtmann 			uf.opcode    = f->opcode;
16080878b666SMarcel Holtmann 			uf.event_mask[0] = *((u32 *) f->event_mask + 0);
16090878b666SMarcel Holtmann 			uf.event_mask[1] = *((u32 *) f->event_mask + 1);
16100878b666SMarcel Holtmann 		}
16110878b666SMarcel Holtmann 
16121da177e4SLinus Torvalds 		len = min_t(unsigned int, len, sizeof(uf));
16131da177e4SLinus Torvalds 		if (copy_from_user(&uf, optval, len)) {
16141da177e4SLinus Torvalds 			err = -EFAULT;
16151da177e4SLinus Torvalds 			break;
16161da177e4SLinus Torvalds 		}
16171da177e4SLinus Torvalds 
16181da177e4SLinus Torvalds 		if (!capable(CAP_NET_RAW)) {
16191da177e4SLinus Torvalds 			uf.type_mask &= hci_sec_filter.type_mask;
16201da177e4SLinus Torvalds 			uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
16211da177e4SLinus Torvalds 			uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
16221da177e4SLinus Torvalds 		}
16231da177e4SLinus Torvalds 
16241da177e4SLinus Torvalds 		{
16251da177e4SLinus Torvalds 			struct hci_filter *f = &hci_pi(sk)->filter;
16261da177e4SLinus Torvalds 
16271da177e4SLinus Torvalds 			f->type_mask = uf.type_mask;
16281da177e4SLinus Torvalds 			f->opcode    = uf.opcode;
16291da177e4SLinus Torvalds 			*((u32 *) f->event_mask + 0) = uf.event_mask[0];
16301da177e4SLinus Torvalds 			*((u32 *) f->event_mask + 1) = uf.event_mask[1];
16311da177e4SLinus Torvalds 		}
16321da177e4SLinus Torvalds 		break;
16331da177e4SLinus Torvalds 
16341da177e4SLinus Torvalds 	default:
16351da177e4SLinus Torvalds 		err = -ENOPROTOOPT;
16361da177e4SLinus Torvalds 		break;
16371da177e4SLinus Torvalds 	}
16381da177e4SLinus Torvalds 
16392f39cdb7SMarcel Holtmann done:
16401da177e4SLinus Torvalds 	release_sock(sk);
16411da177e4SLinus Torvalds 	return err;
16421da177e4SLinus Torvalds }
16431da177e4SLinus Torvalds 
16448fc9ced3SGustavo Padovan static int hci_sock_getsockopt(struct socket *sock, int level, int optname,
16458fc9ced3SGustavo Padovan 			       char __user *optval, int __user *optlen)
16461da177e4SLinus Torvalds {
16471da177e4SLinus Torvalds 	struct hci_ufilter uf;
16481da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
1649cedc5469SMarcel Holtmann 	int len, opt, err = 0;
1650cedc5469SMarcel Holtmann 
1651cedc5469SMarcel Holtmann 	BT_DBG("sk %p, opt %d", sk, optname);
16521da177e4SLinus Torvalds 
165347b0f573SMarcel Holtmann 	if (level != SOL_HCI)
165447b0f573SMarcel Holtmann 		return -ENOPROTOOPT;
165547b0f573SMarcel Holtmann 
16561da177e4SLinus Torvalds 	if (get_user(len, optlen))
16571da177e4SLinus Torvalds 		return -EFAULT;
16581da177e4SLinus Torvalds 
1659cedc5469SMarcel Holtmann 	lock_sock(sk);
1660cedc5469SMarcel Holtmann 
1661cedc5469SMarcel Holtmann 	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
1662c2371e80SMarcel Holtmann 		err = -EBADFD;
1663cedc5469SMarcel Holtmann 		goto done;
1664cedc5469SMarcel Holtmann 	}
1665cedc5469SMarcel Holtmann 
16661da177e4SLinus Torvalds 	switch (optname) {
16671da177e4SLinus Torvalds 	case HCI_DATA_DIR:
16681da177e4SLinus Torvalds 		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
16691da177e4SLinus Torvalds 			opt = 1;
16701da177e4SLinus Torvalds 		else
16711da177e4SLinus Torvalds 			opt = 0;
16721da177e4SLinus Torvalds 
16731da177e4SLinus Torvalds 		if (put_user(opt, optval))
1674cedc5469SMarcel Holtmann 			err = -EFAULT;
16751da177e4SLinus Torvalds 		break;
16761da177e4SLinus Torvalds 
16771da177e4SLinus Torvalds 	case HCI_TIME_STAMP:
16781da177e4SLinus Torvalds 		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
16791da177e4SLinus Torvalds 			opt = 1;
16801da177e4SLinus Torvalds 		else
16811da177e4SLinus Torvalds 			opt = 0;
16821da177e4SLinus Torvalds 
16831da177e4SLinus Torvalds 		if (put_user(opt, optval))
1684cedc5469SMarcel Holtmann 			err = -EFAULT;
16851da177e4SLinus Torvalds 		break;
16861da177e4SLinus Torvalds 
16871da177e4SLinus Torvalds 	case HCI_FILTER:
16881da177e4SLinus Torvalds 		{
16891da177e4SLinus Torvalds 			struct hci_filter *f = &hci_pi(sk)->filter;
16901da177e4SLinus Torvalds 
1691e15ca9a0SMathias Krause 			memset(&uf, 0, sizeof(uf));
16921da177e4SLinus Torvalds 			uf.type_mask = f->type_mask;
16931da177e4SLinus Torvalds 			uf.opcode    = f->opcode;
16941da177e4SLinus Torvalds 			uf.event_mask[0] = *((u32 *) f->event_mask + 0);
16951da177e4SLinus Torvalds 			uf.event_mask[1] = *((u32 *) f->event_mask + 1);
16961da177e4SLinus Torvalds 		}
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 		len = min_t(unsigned int, len, sizeof(uf));
16991da177e4SLinus Torvalds 		if (copy_to_user(optval, &uf, len))
1700cedc5469SMarcel Holtmann 			err = -EFAULT;
17011da177e4SLinus Torvalds 		break;
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds 	default:
1704cedc5469SMarcel Holtmann 		err = -ENOPROTOOPT;
17051da177e4SLinus Torvalds 		break;
17061da177e4SLinus Torvalds 	}
17071da177e4SLinus Torvalds 
1708cedc5469SMarcel Holtmann done:
1709cedc5469SMarcel Holtmann 	release_sock(sk);
1710cedc5469SMarcel Holtmann 	return err;
17111da177e4SLinus Torvalds }
17121da177e4SLinus Torvalds 
171390ddc4f0SEric Dumazet static const struct proto_ops hci_sock_ops = {
17141da177e4SLinus Torvalds 	.family		= PF_BLUETOOTH,
17151da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
17161da177e4SLinus Torvalds 	.release	= hci_sock_release,
17171da177e4SLinus Torvalds 	.bind		= hci_sock_bind,
17181da177e4SLinus Torvalds 	.getname	= hci_sock_getname,
17191da177e4SLinus Torvalds 	.sendmsg	= hci_sock_sendmsg,
17201da177e4SLinus Torvalds 	.recvmsg	= hci_sock_recvmsg,
17211da177e4SLinus Torvalds 	.ioctl		= hci_sock_ioctl,
17221da177e4SLinus Torvalds 	.poll		= datagram_poll,
17231da177e4SLinus Torvalds 	.listen		= sock_no_listen,
17241da177e4SLinus Torvalds 	.shutdown	= sock_no_shutdown,
17251da177e4SLinus Torvalds 	.setsockopt	= hci_sock_setsockopt,
17261da177e4SLinus Torvalds 	.getsockopt	= hci_sock_getsockopt,
17271da177e4SLinus Torvalds 	.connect	= sock_no_connect,
17281da177e4SLinus Torvalds 	.socketpair	= sock_no_socketpair,
17291da177e4SLinus Torvalds 	.accept		= sock_no_accept,
17301da177e4SLinus Torvalds 	.mmap		= sock_no_mmap
17311da177e4SLinus Torvalds };
17321da177e4SLinus Torvalds 
17331da177e4SLinus Torvalds static struct proto hci_sk_proto = {
17341da177e4SLinus Torvalds 	.name		= "HCI",
17351da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
17361da177e4SLinus Torvalds 	.obj_size	= sizeof(struct hci_pinfo)
17371da177e4SLinus Torvalds };
17381da177e4SLinus Torvalds 
17393f378b68SEric Paris static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
17403f378b68SEric Paris 			   int kern)
17411da177e4SLinus Torvalds {
17421da177e4SLinus Torvalds 	struct sock *sk;
17431da177e4SLinus Torvalds 
17441da177e4SLinus Torvalds 	BT_DBG("sock %p", sock);
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds 	if (sock->type != SOCK_RAW)
17471da177e4SLinus Torvalds 		return -ESOCKTNOSUPPORT;
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds 	sock->ops = &hci_sock_ops;
17501da177e4SLinus Torvalds 
175111aa9c28SEric W. Biederman 	sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern);
17521da177e4SLinus Torvalds 	if (!sk)
17531da177e4SLinus Torvalds 		return -ENOMEM;
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds 	sock_init_data(sock, sk);
17561da177e4SLinus Torvalds 
17571da177e4SLinus Torvalds 	sock_reset_flag(sk, SOCK_ZAPPED);
17581da177e4SLinus Torvalds 
17591da177e4SLinus Torvalds 	sk->sk_protocol = protocol;
17601da177e4SLinus Torvalds 
17611da177e4SLinus Torvalds 	sock->state = SS_UNCONNECTED;
17621da177e4SLinus Torvalds 	sk->sk_state = BT_OPEN;
17631da177e4SLinus Torvalds 
17641da177e4SLinus Torvalds 	bt_sock_link(&hci_sk_list, sk);
17651da177e4SLinus Torvalds 	return 0;
17661da177e4SLinus Torvalds }
17671da177e4SLinus Torvalds 
1768ec1b4cf7SStephen Hemminger static const struct net_proto_family hci_sock_family_ops = {
17691da177e4SLinus Torvalds 	.family	= PF_BLUETOOTH,
17701da177e4SLinus Torvalds 	.owner	= THIS_MODULE,
17711da177e4SLinus Torvalds 	.create	= hci_sock_create,
17721da177e4SLinus Torvalds };
17731da177e4SLinus Torvalds 
17741da177e4SLinus Torvalds int __init hci_sock_init(void)
17751da177e4SLinus Torvalds {
17761da177e4SLinus Torvalds 	int err;
17771da177e4SLinus Torvalds 
1778b0a8e282SMarcel Holtmann 	BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr));
1779b0a8e282SMarcel Holtmann 
17801da177e4SLinus Torvalds 	err = proto_register(&hci_sk_proto, 0);
17811da177e4SLinus Torvalds 	if (err < 0)
17821da177e4SLinus Torvalds 		return err;
17831da177e4SLinus Torvalds 
17841da177e4SLinus Torvalds 	err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
1785f7c86637SMasatake YAMATO 	if (err < 0) {
1786f7c86637SMasatake YAMATO 		BT_ERR("HCI socket registration failed");
17871da177e4SLinus Torvalds 		goto error;
1788f7c86637SMasatake YAMATO 	}
1789f7c86637SMasatake YAMATO 
1790b0316615SAl Viro 	err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL);
1791f7c86637SMasatake YAMATO 	if (err < 0) {
1792f7c86637SMasatake YAMATO 		BT_ERR("Failed to create HCI proc file");
1793f7c86637SMasatake YAMATO 		bt_sock_unregister(BTPROTO_HCI);
1794f7c86637SMasatake YAMATO 		goto error;
1795f7c86637SMasatake YAMATO 	}
17961da177e4SLinus Torvalds 
17971da177e4SLinus Torvalds 	BT_INFO("HCI socket layer initialized");
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds 	return 0;
18001da177e4SLinus Torvalds 
18011da177e4SLinus Torvalds error:
18021da177e4SLinus Torvalds 	proto_unregister(&hci_sk_proto);
18031da177e4SLinus Torvalds 	return err;
18041da177e4SLinus Torvalds }
18051da177e4SLinus Torvalds 
1806b7440a14SAnand Gadiyar void hci_sock_cleanup(void)
18071da177e4SLinus Torvalds {
1808f7c86637SMasatake YAMATO 	bt_procfs_cleanup(&init_net, "hci");
18095e9d7f86SDavid Herrmann 	bt_sock_unregister(BTPROTO_HCI);
18101da177e4SLinus Torvalds 	proto_unregister(&hci_sk_proto);
18111da177e4SLinus Torvalds }
1812