18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci   BlueZ - Bluetooth protocol stack for Linux
38c2ecf20Sopenharmony_ci   Copyright (C) 2000-2001 Qualcomm Incorporated
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci   This program is free software; you can redistribute it and/or modify
88c2ecf20Sopenharmony_ci   it under the terms of the GNU General Public License version 2 as
98c2ecf20Sopenharmony_ci   published by the Free Software Foundation;
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
128c2ecf20Sopenharmony_ci   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138c2ecf20Sopenharmony_ci   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
148c2ecf20Sopenharmony_ci   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
158c2ecf20Sopenharmony_ci   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
168c2ecf20Sopenharmony_ci   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
178c2ecf20Sopenharmony_ci   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
188c2ecf20Sopenharmony_ci   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
218c2ecf20Sopenharmony_ci   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
228c2ecf20Sopenharmony_ci   SOFTWARE IS DISCLAIMED.
238c2ecf20Sopenharmony_ci*/
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* Bluetooth HCI sockets. */
268c2ecf20Sopenharmony_ci#include <linux/compat.h>
278c2ecf20Sopenharmony_ci#include <linux/export.h>
288c2ecf20Sopenharmony_ci#include <linux/utsname.h>
298c2ecf20Sopenharmony_ci#include <linux/sched.h>
308c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include <net/bluetooth/bluetooth.h>
338c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_core.h>
348c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_mon.h>
358c2ecf20Sopenharmony_ci#include <net/bluetooth/mgmt.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include "mgmt_util.h"
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic LIST_HEAD(mgmt_chan_list);
408c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(mgmt_chan_list_lock);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic DEFINE_IDA(sock_cookie_ida);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic atomic_t monitor_promisc = ATOMIC_INIT(0);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* ----- HCI socket interface ----- */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* Socket info */
498c2ecf20Sopenharmony_ci#define hci_pi(sk) ((struct hci_pinfo *) sk)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistruct hci_pinfo {
528c2ecf20Sopenharmony_ci	struct bt_sock    bt;
538c2ecf20Sopenharmony_ci	struct hci_dev    *hdev;
548c2ecf20Sopenharmony_ci	struct hci_filter filter;
558c2ecf20Sopenharmony_ci	__u8              cmsg_mask;
568c2ecf20Sopenharmony_ci	unsigned short    channel;
578c2ecf20Sopenharmony_ci	unsigned long     flags;
588c2ecf20Sopenharmony_ci	__u32             cookie;
598c2ecf20Sopenharmony_ci	char              comm[TASK_COMM_LEN];
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic struct hci_dev *hci_hdev_from_sock(struct sock *sk)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct hci_dev *hdev = hci_pi(sk)->hdev;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (!hdev)
678c2ecf20Sopenharmony_ci		return ERR_PTR(-EBADFD);
688c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
698c2ecf20Sopenharmony_ci		return ERR_PTR(-EPIPE);
708c2ecf20Sopenharmony_ci	return hdev;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_civoid hci_sock_set_flag(struct sock *sk, int nr)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	set_bit(nr, &hci_pi(sk)->flags);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_civoid hci_sock_clear_flag(struct sock *sk, int nr)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	clear_bit(nr, &hci_pi(sk)->flags);
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciint hci_sock_test_flag(struct sock *sk, int nr)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	return test_bit(nr, &hci_pi(sk)->flags);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ciunsigned short hci_sock_get_channel(struct sock *sk)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	return hci_pi(sk)->channel;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ciu32 hci_sock_get_cookie(struct sock *sk)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	return hci_pi(sk)->cookie;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic bool hci_sock_gen_cookie(struct sock *sk)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	int id = hci_pi(sk)->cookie;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	if (!id) {
1038c2ecf20Sopenharmony_ci		id = ida_simple_get(&sock_cookie_ida, 1, 0, GFP_KERNEL);
1048c2ecf20Sopenharmony_ci		if (id < 0)
1058c2ecf20Sopenharmony_ci			id = 0xffffffff;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci		hci_pi(sk)->cookie = id;
1088c2ecf20Sopenharmony_ci		get_task_comm(hci_pi(sk)->comm, current);
1098c2ecf20Sopenharmony_ci		return true;
1108c2ecf20Sopenharmony_ci	}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	return false;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic void hci_sock_free_cookie(struct sock *sk)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	int id = hci_pi(sk)->cookie;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	if (id) {
1208c2ecf20Sopenharmony_ci		hci_pi(sk)->cookie = 0xffffffff;
1218c2ecf20Sopenharmony_ci		ida_simple_remove(&sock_cookie_ida, id);
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic inline int hci_test_bit(int nr, const void *addr)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/* Security filter */
1318c2ecf20Sopenharmony_ci#define HCI_SFLT_MAX_OGF  5
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistruct hci_sec_filter {
1348c2ecf20Sopenharmony_ci	__u32 type_mask;
1358c2ecf20Sopenharmony_ci	__u32 event_mask[2];
1368c2ecf20Sopenharmony_ci	__u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic const struct hci_sec_filter hci_sec_filter = {
1408c2ecf20Sopenharmony_ci	/* Packet types */
1418c2ecf20Sopenharmony_ci	0x10,
1428c2ecf20Sopenharmony_ci	/* Events */
1438c2ecf20Sopenharmony_ci	{ 0x1000d9fe, 0x0000b00c },
1448c2ecf20Sopenharmony_ci	/* Commands */
1458c2ecf20Sopenharmony_ci	{
1468c2ecf20Sopenharmony_ci		{ 0x0 },
1478c2ecf20Sopenharmony_ci		/* OGF_LINK_CTL */
1488c2ecf20Sopenharmony_ci		{ 0xbe000006, 0x00000001, 0x00000000, 0x00 },
1498c2ecf20Sopenharmony_ci		/* OGF_LINK_POLICY */
1508c2ecf20Sopenharmony_ci		{ 0x00005200, 0x00000000, 0x00000000, 0x00 },
1518c2ecf20Sopenharmony_ci		/* OGF_HOST_CTL */
1528c2ecf20Sopenharmony_ci		{ 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
1538c2ecf20Sopenharmony_ci		/* OGF_INFO_PARAM */
1548c2ecf20Sopenharmony_ci		{ 0x000002be, 0x00000000, 0x00000000, 0x00 },
1558c2ecf20Sopenharmony_ci		/* OGF_STATUS_PARAM */
1568c2ecf20Sopenharmony_ci		{ 0x000000ea, 0x00000000, 0x00000000, 0x00 }
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci};
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic struct bt_sock_list hci_sk_list = {
1618c2ecf20Sopenharmony_ci	.lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic bool is_filtered_packet(struct sock *sk, struct sk_buff *skb)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	struct hci_filter *flt;
1678c2ecf20Sopenharmony_ci	int flt_type, flt_event;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	/* Apply filter */
1708c2ecf20Sopenharmony_ci	flt = &hci_pi(sk)->filter;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	flt_type = hci_skb_pkt_type(skb) & HCI_FLT_TYPE_BITS;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	if (!test_bit(flt_type, &flt->type_mask))
1758c2ecf20Sopenharmony_ci		return true;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	/* Extra filter for event packets only */
1788c2ecf20Sopenharmony_ci	if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT)
1798c2ecf20Sopenharmony_ci		return false;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	if (!hci_test_bit(flt_event, &flt->event_mask))
1848c2ecf20Sopenharmony_ci		return true;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	/* Check filter only when opcode is set */
1878c2ecf20Sopenharmony_ci	if (!flt->opcode)
1888c2ecf20Sopenharmony_ci		return false;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (flt_event == HCI_EV_CMD_COMPLETE &&
1918c2ecf20Sopenharmony_ci	    flt->opcode != get_unaligned((__le16 *)(skb->data + 3)))
1928c2ecf20Sopenharmony_ci		return true;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	if (flt_event == HCI_EV_CMD_STATUS &&
1958c2ecf20Sopenharmony_ci	    flt->opcode != get_unaligned((__le16 *)(skb->data + 4)))
1968c2ecf20Sopenharmony_ci		return true;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	return false;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci/* Send frame to RAW socket */
2028c2ecf20Sopenharmony_civoid hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	struct sock *sk;
2058c2ecf20Sopenharmony_ci	struct sk_buff *skb_copy = NULL;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	BT_DBG("hdev %p len %d", hdev, skb->len);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	read_lock(&hci_sk_list.lock);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	sk_for_each(sk, &hci_sk_list.head) {
2128c2ecf20Sopenharmony_ci		struct sk_buff *nskb;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci		if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
2158c2ecf20Sopenharmony_ci			continue;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		/* Don't send frame to the socket it came from */
2188c2ecf20Sopenharmony_ci		if (skb->sk == sk)
2198c2ecf20Sopenharmony_ci			continue;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) {
2228c2ecf20Sopenharmony_ci			if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT &&
2238c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
2248c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
2258c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
2268c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_ISODATA_PKT)
2278c2ecf20Sopenharmony_ci				continue;
2288c2ecf20Sopenharmony_ci			if (is_filtered_packet(sk, skb))
2298c2ecf20Sopenharmony_ci				continue;
2308c2ecf20Sopenharmony_ci		} else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
2318c2ecf20Sopenharmony_ci			if (!bt_cb(skb)->incoming)
2328c2ecf20Sopenharmony_ci				continue;
2338c2ecf20Sopenharmony_ci			if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
2348c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
2358c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
2368c2ecf20Sopenharmony_ci			    hci_skb_pkt_type(skb) != HCI_ISODATA_PKT)
2378c2ecf20Sopenharmony_ci				continue;
2388c2ecf20Sopenharmony_ci		} else {
2398c2ecf20Sopenharmony_ci			/* Don't send frame to other channel types */
2408c2ecf20Sopenharmony_ci			continue;
2418c2ecf20Sopenharmony_ci		}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		if (!skb_copy) {
2448c2ecf20Sopenharmony_ci			/* Create a private copy with headroom */
2458c2ecf20Sopenharmony_ci			skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true);
2468c2ecf20Sopenharmony_ci			if (!skb_copy)
2478c2ecf20Sopenharmony_ci				continue;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci			/* Put type byte before the data */
2508c2ecf20Sopenharmony_ci			memcpy(skb_push(skb_copy, 1), &hci_skb_pkt_type(skb), 1);
2518c2ecf20Sopenharmony_ci		}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci		nskb = skb_clone(skb_copy, GFP_ATOMIC);
2548c2ecf20Sopenharmony_ci		if (!nskb)
2558c2ecf20Sopenharmony_ci			continue;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci		if (sock_queue_rcv_skb(sk, nskb))
2588c2ecf20Sopenharmony_ci			kfree_skb(nskb);
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	read_unlock(&hci_sk_list.lock);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	kfree_skb(skb_copy);
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci/* Send frame to sockets with specific channel */
2678c2ecf20Sopenharmony_cistatic void __hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
2688c2ecf20Sopenharmony_ci				  int flag, struct sock *skip_sk)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	struct sock *sk;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	BT_DBG("channel %u len %d", channel, skb->len);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	sk_for_each(sk, &hci_sk_list.head) {
2758c2ecf20Sopenharmony_ci		struct sk_buff *nskb;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci		/* Ignore socket without the flag set */
2788c2ecf20Sopenharmony_ci		if (!hci_sock_test_flag(sk, flag))
2798c2ecf20Sopenharmony_ci			continue;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		/* Skip the original socket */
2828c2ecf20Sopenharmony_ci		if (sk == skip_sk)
2838c2ecf20Sopenharmony_ci			continue;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci		if (sk->sk_state != BT_BOUND)
2868c2ecf20Sopenharmony_ci			continue;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		if (hci_pi(sk)->channel != channel)
2898c2ecf20Sopenharmony_ci			continue;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci		nskb = skb_clone(skb, GFP_ATOMIC);
2928c2ecf20Sopenharmony_ci		if (!nskb)
2938c2ecf20Sopenharmony_ci			continue;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci		if (sock_queue_rcv_skb(sk, nskb))
2968c2ecf20Sopenharmony_ci			kfree_skb(nskb);
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_civoid hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
3028c2ecf20Sopenharmony_ci			 int flag, struct sock *skip_sk)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	read_lock(&hci_sk_list.lock);
3058c2ecf20Sopenharmony_ci	__hci_send_to_channel(channel, skb, flag, skip_sk);
3068c2ecf20Sopenharmony_ci	read_unlock(&hci_sk_list.lock);
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci/* Send frame to monitor socket */
3108c2ecf20Sopenharmony_civoid hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	struct sk_buff *skb_copy = NULL;
3138c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
3148c2ecf20Sopenharmony_ci	__le16 opcode;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (!atomic_read(&monitor_promisc))
3178c2ecf20Sopenharmony_ci		return;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	BT_DBG("hdev %p len %d", hdev, skb->len);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	switch (hci_skb_pkt_type(skb)) {
3228c2ecf20Sopenharmony_ci	case HCI_COMMAND_PKT:
3238c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_COMMAND_PKT);
3248c2ecf20Sopenharmony_ci		break;
3258c2ecf20Sopenharmony_ci	case HCI_EVENT_PKT:
3268c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_EVENT_PKT);
3278c2ecf20Sopenharmony_ci		break;
3288c2ecf20Sopenharmony_ci	case HCI_ACLDATA_PKT:
3298c2ecf20Sopenharmony_ci		if (bt_cb(skb)->incoming)
3308c2ecf20Sopenharmony_ci			opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT);
3318c2ecf20Sopenharmony_ci		else
3328c2ecf20Sopenharmony_ci			opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT);
3338c2ecf20Sopenharmony_ci		break;
3348c2ecf20Sopenharmony_ci	case HCI_SCODATA_PKT:
3358c2ecf20Sopenharmony_ci		if (bt_cb(skb)->incoming)
3368c2ecf20Sopenharmony_ci			opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT);
3378c2ecf20Sopenharmony_ci		else
3388c2ecf20Sopenharmony_ci			opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT);
3398c2ecf20Sopenharmony_ci		break;
3408c2ecf20Sopenharmony_ci	case HCI_ISODATA_PKT:
3418c2ecf20Sopenharmony_ci		if (bt_cb(skb)->incoming)
3428c2ecf20Sopenharmony_ci			opcode = cpu_to_le16(HCI_MON_ISO_RX_PKT);
3438c2ecf20Sopenharmony_ci		else
3448c2ecf20Sopenharmony_ci			opcode = cpu_to_le16(HCI_MON_ISO_TX_PKT);
3458c2ecf20Sopenharmony_ci		break;
3468c2ecf20Sopenharmony_ci	case HCI_DIAG_PKT:
3478c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG);
3488c2ecf20Sopenharmony_ci		break;
3498c2ecf20Sopenharmony_ci	default:
3508c2ecf20Sopenharmony_ci		return;
3518c2ecf20Sopenharmony_ci	}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	/* Create a private copy with headroom */
3548c2ecf20Sopenharmony_ci	skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true);
3558c2ecf20Sopenharmony_ci	if (!skb_copy)
3568c2ecf20Sopenharmony_ci		return;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	/* Put header before the data */
3598c2ecf20Sopenharmony_ci	hdr = skb_push(skb_copy, HCI_MON_HDR_SIZE);
3608c2ecf20Sopenharmony_ci	hdr->opcode = opcode;
3618c2ecf20Sopenharmony_ci	hdr->index = cpu_to_le16(hdev->id);
3628c2ecf20Sopenharmony_ci	hdr->len = cpu_to_le16(skb->len);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy,
3658c2ecf20Sopenharmony_ci			    HCI_SOCK_TRUSTED, NULL);
3668c2ecf20Sopenharmony_ci	kfree_skb(skb_copy);
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_civoid hci_send_monitor_ctrl_event(struct hci_dev *hdev, u16 event,
3708c2ecf20Sopenharmony_ci				 void *data, u16 data_len, ktime_t tstamp,
3718c2ecf20Sopenharmony_ci				 int flag, struct sock *skip_sk)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	struct sock *sk;
3748c2ecf20Sopenharmony_ci	__le16 index;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	if (hdev)
3778c2ecf20Sopenharmony_ci		index = cpu_to_le16(hdev->id);
3788c2ecf20Sopenharmony_ci	else
3798c2ecf20Sopenharmony_ci		index = cpu_to_le16(MGMT_INDEX_NONE);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	read_lock(&hci_sk_list.lock);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	sk_for_each(sk, &hci_sk_list.head) {
3848c2ecf20Sopenharmony_ci		struct hci_mon_hdr *hdr;
3858c2ecf20Sopenharmony_ci		struct sk_buff *skb;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		if (hci_pi(sk)->channel != HCI_CHANNEL_CONTROL)
3888c2ecf20Sopenharmony_ci			continue;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		/* Ignore socket without the flag set */
3918c2ecf20Sopenharmony_ci		if (!hci_sock_test_flag(sk, flag))
3928c2ecf20Sopenharmony_ci			continue;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		/* Skip the original socket */
3958c2ecf20Sopenharmony_ci		if (sk == skip_sk)
3968c2ecf20Sopenharmony_ci			continue;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		skb = bt_skb_alloc(6 + data_len, GFP_ATOMIC);
3998c2ecf20Sopenharmony_ci		if (!skb)
4008c2ecf20Sopenharmony_ci			continue;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci		put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
4038c2ecf20Sopenharmony_ci		put_unaligned_le16(event, skb_put(skb, 2));
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci		if (data)
4068c2ecf20Sopenharmony_ci			skb_put_data(skb, data, data_len);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci		skb->tstamp = tstamp;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci		hdr = skb_push(skb, HCI_MON_HDR_SIZE);
4118c2ecf20Sopenharmony_ci		hdr->opcode = cpu_to_le16(HCI_MON_CTRL_EVENT);
4128c2ecf20Sopenharmony_ci		hdr->index = index;
4138c2ecf20Sopenharmony_ci		hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci		__hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
4168c2ecf20Sopenharmony_ci				      HCI_SOCK_TRUSTED, NULL);
4178c2ecf20Sopenharmony_ci		kfree_skb(skb);
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	read_unlock(&hci_sk_list.lock);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
4268c2ecf20Sopenharmony_ci	struct hci_mon_new_index *ni;
4278c2ecf20Sopenharmony_ci	struct hci_mon_index_info *ii;
4288c2ecf20Sopenharmony_ci	struct sk_buff *skb;
4298c2ecf20Sopenharmony_ci	__le16 opcode;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	switch (event) {
4328c2ecf20Sopenharmony_ci	case HCI_DEV_REG:
4338c2ecf20Sopenharmony_ci		skb = bt_skb_alloc(HCI_MON_NEW_INDEX_SIZE, GFP_ATOMIC);
4348c2ecf20Sopenharmony_ci		if (!skb)
4358c2ecf20Sopenharmony_ci			return NULL;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		ni = skb_put(skb, HCI_MON_NEW_INDEX_SIZE);
4388c2ecf20Sopenharmony_ci		ni->type = hdev->dev_type;
4398c2ecf20Sopenharmony_ci		ni->bus = hdev->bus;
4408c2ecf20Sopenharmony_ci		bacpy(&ni->bdaddr, &hdev->bdaddr);
4418c2ecf20Sopenharmony_ci		memcpy_and_pad(ni->name, sizeof(ni->name), hdev->name,
4428c2ecf20Sopenharmony_ci			       strnlen(hdev->name, sizeof(ni->name)), '\0');
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_NEW_INDEX);
4458c2ecf20Sopenharmony_ci		break;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	case HCI_DEV_UNREG:
4488c2ecf20Sopenharmony_ci		skb = bt_skb_alloc(0, GFP_ATOMIC);
4498c2ecf20Sopenharmony_ci		if (!skb)
4508c2ecf20Sopenharmony_ci			return NULL;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_DEL_INDEX);
4538c2ecf20Sopenharmony_ci		break;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	case HCI_DEV_SETUP:
4568c2ecf20Sopenharmony_ci		if (hdev->manufacturer == 0xffff)
4578c2ecf20Sopenharmony_ci			return NULL;
4588c2ecf20Sopenharmony_ci		fallthrough;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	case HCI_DEV_UP:
4618c2ecf20Sopenharmony_ci		skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC);
4628c2ecf20Sopenharmony_ci		if (!skb)
4638c2ecf20Sopenharmony_ci			return NULL;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci		ii = skb_put(skb, HCI_MON_INDEX_INFO_SIZE);
4668c2ecf20Sopenharmony_ci		bacpy(&ii->bdaddr, &hdev->bdaddr);
4678c2ecf20Sopenharmony_ci		ii->manufacturer = cpu_to_le16(hdev->manufacturer);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_INDEX_INFO);
4708c2ecf20Sopenharmony_ci		break;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	case HCI_DEV_OPEN:
4738c2ecf20Sopenharmony_ci		skb = bt_skb_alloc(0, GFP_ATOMIC);
4748c2ecf20Sopenharmony_ci		if (!skb)
4758c2ecf20Sopenharmony_ci			return NULL;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_OPEN_INDEX);
4788c2ecf20Sopenharmony_ci		break;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	case HCI_DEV_CLOSE:
4818c2ecf20Sopenharmony_ci		skb = bt_skb_alloc(0, GFP_ATOMIC);
4828c2ecf20Sopenharmony_ci		if (!skb)
4838c2ecf20Sopenharmony_ci			return NULL;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci		opcode = cpu_to_le16(HCI_MON_CLOSE_INDEX);
4868c2ecf20Sopenharmony_ci		break;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	default:
4898c2ecf20Sopenharmony_ci		return NULL;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	__net_timestamp(skb);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	hdr = skb_push(skb, HCI_MON_HDR_SIZE);
4958c2ecf20Sopenharmony_ci	hdr->opcode = opcode;
4968c2ecf20Sopenharmony_ci	hdr->index = cpu_to_le16(hdev->id);
4978c2ecf20Sopenharmony_ci	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	return skb;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic struct sk_buff *create_monitor_ctrl_open(struct sock *sk)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
5058c2ecf20Sopenharmony_ci	struct sk_buff *skb;
5068c2ecf20Sopenharmony_ci	u16 format;
5078c2ecf20Sopenharmony_ci	u8 ver[3];
5088c2ecf20Sopenharmony_ci	u32 flags;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	/* No message needed when cookie is not present */
5118c2ecf20Sopenharmony_ci	if (!hci_pi(sk)->cookie)
5128c2ecf20Sopenharmony_ci		return NULL;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	switch (hci_pi(sk)->channel) {
5158c2ecf20Sopenharmony_ci	case HCI_CHANNEL_RAW:
5168c2ecf20Sopenharmony_ci		format = 0x0000;
5178c2ecf20Sopenharmony_ci		ver[0] = BT_SUBSYS_VERSION;
5188c2ecf20Sopenharmony_ci		put_unaligned_le16(BT_SUBSYS_REVISION, ver + 1);
5198c2ecf20Sopenharmony_ci		break;
5208c2ecf20Sopenharmony_ci	case HCI_CHANNEL_USER:
5218c2ecf20Sopenharmony_ci		format = 0x0001;
5228c2ecf20Sopenharmony_ci		ver[0] = BT_SUBSYS_VERSION;
5238c2ecf20Sopenharmony_ci		put_unaligned_le16(BT_SUBSYS_REVISION, ver + 1);
5248c2ecf20Sopenharmony_ci		break;
5258c2ecf20Sopenharmony_ci	case HCI_CHANNEL_CONTROL:
5268c2ecf20Sopenharmony_ci		format = 0x0002;
5278c2ecf20Sopenharmony_ci		mgmt_fill_version_info(ver);
5288c2ecf20Sopenharmony_ci		break;
5298c2ecf20Sopenharmony_ci	default:
5308c2ecf20Sopenharmony_ci		/* No message for unsupported format */
5318c2ecf20Sopenharmony_ci		return NULL;
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	skb = bt_skb_alloc(14 + TASK_COMM_LEN , GFP_ATOMIC);
5358c2ecf20Sopenharmony_ci	if (!skb)
5368c2ecf20Sopenharmony_ci		return NULL;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	flags = hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) ? 0x1 : 0x0;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
5418c2ecf20Sopenharmony_ci	put_unaligned_le16(format, skb_put(skb, 2));
5428c2ecf20Sopenharmony_ci	skb_put_data(skb, ver, sizeof(ver));
5438c2ecf20Sopenharmony_ci	put_unaligned_le32(flags, skb_put(skb, 4));
5448c2ecf20Sopenharmony_ci	skb_put_u8(skb, TASK_COMM_LEN);
5458c2ecf20Sopenharmony_ci	skb_put_data(skb, hci_pi(sk)->comm, TASK_COMM_LEN);
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	__net_timestamp(skb);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	hdr = skb_push(skb, HCI_MON_HDR_SIZE);
5508c2ecf20Sopenharmony_ci	hdr->opcode = cpu_to_le16(HCI_MON_CTRL_OPEN);
5518c2ecf20Sopenharmony_ci	if (hci_pi(sk)->hdev)
5528c2ecf20Sopenharmony_ci		hdr->index = cpu_to_le16(hci_pi(sk)->hdev->id);
5538c2ecf20Sopenharmony_ci	else
5548c2ecf20Sopenharmony_ci		hdr->index = cpu_to_le16(HCI_DEV_NONE);
5558c2ecf20Sopenharmony_ci	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return skb;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic struct sk_buff *create_monitor_ctrl_close(struct sock *sk)
5618c2ecf20Sopenharmony_ci{
5628c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
5638c2ecf20Sopenharmony_ci	struct sk_buff *skb;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	/* No message needed when cookie is not present */
5668c2ecf20Sopenharmony_ci	if (!hci_pi(sk)->cookie)
5678c2ecf20Sopenharmony_ci		return NULL;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	switch (hci_pi(sk)->channel) {
5708c2ecf20Sopenharmony_ci	case HCI_CHANNEL_RAW:
5718c2ecf20Sopenharmony_ci	case HCI_CHANNEL_USER:
5728c2ecf20Sopenharmony_ci	case HCI_CHANNEL_CONTROL:
5738c2ecf20Sopenharmony_ci		break;
5748c2ecf20Sopenharmony_ci	default:
5758c2ecf20Sopenharmony_ci		/* No message for unsupported format */
5768c2ecf20Sopenharmony_ci		return NULL;
5778c2ecf20Sopenharmony_ci	}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	skb = bt_skb_alloc(4, GFP_ATOMIC);
5808c2ecf20Sopenharmony_ci	if (!skb)
5818c2ecf20Sopenharmony_ci		return NULL;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	__net_timestamp(skb);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	hdr = skb_push(skb, HCI_MON_HDR_SIZE);
5888c2ecf20Sopenharmony_ci	hdr->opcode = cpu_to_le16(HCI_MON_CTRL_CLOSE);
5898c2ecf20Sopenharmony_ci	if (hci_pi(sk)->hdev)
5908c2ecf20Sopenharmony_ci		hdr->index = cpu_to_le16(hci_pi(sk)->hdev->id);
5918c2ecf20Sopenharmony_ci	else
5928c2ecf20Sopenharmony_ci		hdr->index = cpu_to_le16(HCI_DEV_NONE);
5938c2ecf20Sopenharmony_ci	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	return skb;
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic struct sk_buff *create_monitor_ctrl_command(struct sock *sk, u16 index,
5998c2ecf20Sopenharmony_ci						   u16 opcode, u16 len,
6008c2ecf20Sopenharmony_ci						   const void *buf)
6018c2ecf20Sopenharmony_ci{
6028c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
6038c2ecf20Sopenharmony_ci	struct sk_buff *skb;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	skb = bt_skb_alloc(6 + len, GFP_ATOMIC);
6068c2ecf20Sopenharmony_ci	if (!skb)
6078c2ecf20Sopenharmony_ci		return NULL;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
6108c2ecf20Sopenharmony_ci	put_unaligned_le16(opcode, skb_put(skb, 2));
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	if (buf)
6138c2ecf20Sopenharmony_ci		skb_put_data(skb, buf, len);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	__net_timestamp(skb);
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	hdr = skb_push(skb, HCI_MON_HDR_SIZE);
6188c2ecf20Sopenharmony_ci	hdr->opcode = cpu_to_le16(HCI_MON_CTRL_COMMAND);
6198c2ecf20Sopenharmony_ci	hdr->index = cpu_to_le16(index);
6208c2ecf20Sopenharmony_ci	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	return skb;
6238c2ecf20Sopenharmony_ci}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_cistatic void __printf(2, 3)
6268c2ecf20Sopenharmony_cisend_monitor_note(struct sock *sk, const char *fmt, ...)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	size_t len;
6298c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
6308c2ecf20Sopenharmony_ci	struct sk_buff *skb;
6318c2ecf20Sopenharmony_ci	va_list args;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	va_start(args, fmt);
6348c2ecf20Sopenharmony_ci	len = vsnprintf(NULL, 0, fmt, args);
6358c2ecf20Sopenharmony_ci	va_end(args);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	skb = bt_skb_alloc(len + 1, GFP_ATOMIC);
6388c2ecf20Sopenharmony_ci	if (!skb)
6398c2ecf20Sopenharmony_ci		return;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	va_start(args, fmt);
6428c2ecf20Sopenharmony_ci	vsprintf(skb_put(skb, len), fmt, args);
6438c2ecf20Sopenharmony_ci	*(u8 *)skb_put(skb, 1) = 0;
6448c2ecf20Sopenharmony_ci	va_end(args);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	__net_timestamp(skb);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE);
6498c2ecf20Sopenharmony_ci	hdr->opcode = cpu_to_le16(HCI_MON_SYSTEM_NOTE);
6508c2ecf20Sopenharmony_ci	hdr->index = cpu_to_le16(HCI_DEV_NONE);
6518c2ecf20Sopenharmony_ci	hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	if (sock_queue_rcv_skb(sk, skb))
6548c2ecf20Sopenharmony_ci		kfree_skb(skb);
6558c2ecf20Sopenharmony_ci}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_cistatic void send_monitor_replay(struct sock *sk)
6588c2ecf20Sopenharmony_ci{
6598c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	read_lock(&hci_dev_list_lock);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	list_for_each_entry(hdev, &hci_dev_list, list) {
6648c2ecf20Sopenharmony_ci		struct sk_buff *skb;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci		skb = create_monitor_event(hdev, HCI_DEV_REG);
6678c2ecf20Sopenharmony_ci		if (!skb)
6688c2ecf20Sopenharmony_ci			continue;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci		if (sock_queue_rcv_skb(sk, skb))
6718c2ecf20Sopenharmony_ci			kfree_skb(skb);
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci		if (!test_bit(HCI_RUNNING, &hdev->flags))
6748c2ecf20Sopenharmony_ci			continue;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci		skb = create_monitor_event(hdev, HCI_DEV_OPEN);
6778c2ecf20Sopenharmony_ci		if (!skb)
6788c2ecf20Sopenharmony_ci			continue;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci		if (sock_queue_rcv_skb(sk, skb))
6818c2ecf20Sopenharmony_ci			kfree_skb(skb);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci		if (test_bit(HCI_UP, &hdev->flags))
6848c2ecf20Sopenharmony_ci			skb = create_monitor_event(hdev, HCI_DEV_UP);
6858c2ecf20Sopenharmony_ci		else if (hci_dev_test_flag(hdev, HCI_SETUP))
6868c2ecf20Sopenharmony_ci			skb = create_monitor_event(hdev, HCI_DEV_SETUP);
6878c2ecf20Sopenharmony_ci		else
6888c2ecf20Sopenharmony_ci			skb = NULL;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci		if (skb) {
6918c2ecf20Sopenharmony_ci			if (sock_queue_rcv_skb(sk, skb))
6928c2ecf20Sopenharmony_ci				kfree_skb(skb);
6938c2ecf20Sopenharmony_ci		}
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	read_unlock(&hci_dev_list_lock);
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_cistatic void send_monitor_control_replay(struct sock *mon_sk)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	struct sock *sk;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	read_lock(&hci_sk_list.lock);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	sk_for_each(sk, &hci_sk_list.head) {
7068c2ecf20Sopenharmony_ci		struct sk_buff *skb;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci		skb = create_monitor_ctrl_open(sk);
7098c2ecf20Sopenharmony_ci		if (!skb)
7108c2ecf20Sopenharmony_ci			continue;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci		if (sock_queue_rcv_skb(mon_sk, skb))
7138c2ecf20Sopenharmony_ci			kfree_skb(skb);
7148c2ecf20Sopenharmony_ci	}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	read_unlock(&hci_sk_list.lock);
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci/* Generate internal stack event */
7208c2ecf20Sopenharmony_cistatic void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	struct hci_event_hdr *hdr;
7238c2ecf20Sopenharmony_ci	struct hci_ev_stack_internal *ev;
7248c2ecf20Sopenharmony_ci	struct sk_buff *skb;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
7278c2ecf20Sopenharmony_ci	if (!skb)
7288c2ecf20Sopenharmony_ci		return;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	hdr = skb_put(skb, HCI_EVENT_HDR_SIZE);
7318c2ecf20Sopenharmony_ci	hdr->evt  = HCI_EV_STACK_INTERNAL;
7328c2ecf20Sopenharmony_ci	hdr->plen = sizeof(*ev) + dlen;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	ev = skb_put(skb, sizeof(*ev) + dlen);
7358c2ecf20Sopenharmony_ci	ev->type = type;
7368c2ecf20Sopenharmony_ci	memcpy(ev->data, data, dlen);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	bt_cb(skb)->incoming = 1;
7398c2ecf20Sopenharmony_ci	__net_timestamp(skb);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
7428c2ecf20Sopenharmony_ci	hci_send_to_sock(hdev, skb);
7438c2ecf20Sopenharmony_ci	kfree_skb(skb);
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_civoid hci_sock_dev_event(struct hci_dev *hdev, int event)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	BT_DBG("hdev %s event %d", hdev->name, event);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	if (atomic_read(&monitor_promisc)) {
7518c2ecf20Sopenharmony_ci		struct sk_buff *skb;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci		/* Send event to monitor */
7548c2ecf20Sopenharmony_ci		skb = create_monitor_event(hdev, event);
7558c2ecf20Sopenharmony_ci		if (skb) {
7568c2ecf20Sopenharmony_ci			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
7578c2ecf20Sopenharmony_ci					    HCI_SOCK_TRUSTED, NULL);
7588c2ecf20Sopenharmony_ci			kfree_skb(skb);
7598c2ecf20Sopenharmony_ci		}
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	if (event <= HCI_DEV_DOWN) {
7638c2ecf20Sopenharmony_ci		struct hci_ev_si_device ev;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci		/* Send event to sockets */
7668c2ecf20Sopenharmony_ci		ev.event  = event;
7678c2ecf20Sopenharmony_ci		ev.dev_id = hdev->id;
7688c2ecf20Sopenharmony_ci		hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
7698c2ecf20Sopenharmony_ci	}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	if (event == HCI_DEV_UNREG) {
7728c2ecf20Sopenharmony_ci		struct sock *sk;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci		/* Wake up sockets using this dead device */
7758c2ecf20Sopenharmony_ci		read_lock(&hci_sk_list.lock);
7768c2ecf20Sopenharmony_ci		sk_for_each(sk, &hci_sk_list.head) {
7778c2ecf20Sopenharmony_ci			if (hci_pi(sk)->hdev == hdev) {
7788c2ecf20Sopenharmony_ci				sk->sk_err = EPIPE;
7798c2ecf20Sopenharmony_ci				sk->sk_state_change(sk);
7808c2ecf20Sopenharmony_ci			}
7818c2ecf20Sopenharmony_ci		}
7828c2ecf20Sopenharmony_ci		read_unlock(&hci_sk_list.lock);
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	struct hci_mgmt_chan *c;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	list_for_each_entry(c, &mgmt_chan_list, list) {
7918c2ecf20Sopenharmony_ci		if (c->channel == channel)
7928c2ecf20Sopenharmony_ci			return c;
7938c2ecf20Sopenharmony_ci	}
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	return NULL;
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel)
7998c2ecf20Sopenharmony_ci{
8008c2ecf20Sopenharmony_ci	struct hci_mgmt_chan *c;
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	mutex_lock(&mgmt_chan_list_lock);
8038c2ecf20Sopenharmony_ci	c = __hci_mgmt_chan_find(channel);
8048c2ecf20Sopenharmony_ci	mutex_unlock(&mgmt_chan_list_lock);
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	return c;
8078c2ecf20Sopenharmony_ci}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ciint hci_mgmt_chan_register(struct hci_mgmt_chan *c)
8108c2ecf20Sopenharmony_ci{
8118c2ecf20Sopenharmony_ci	if (c->channel < HCI_CHANNEL_CONTROL)
8128c2ecf20Sopenharmony_ci		return -EINVAL;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	mutex_lock(&mgmt_chan_list_lock);
8158c2ecf20Sopenharmony_ci	if (__hci_mgmt_chan_find(c->channel)) {
8168c2ecf20Sopenharmony_ci		mutex_unlock(&mgmt_chan_list_lock);
8178c2ecf20Sopenharmony_ci		return -EALREADY;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	list_add_tail(&c->list, &mgmt_chan_list);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	mutex_unlock(&mgmt_chan_list_lock);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	return 0;
8258c2ecf20Sopenharmony_ci}
8268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_mgmt_chan_register);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_civoid hci_mgmt_chan_unregister(struct hci_mgmt_chan *c)
8298c2ecf20Sopenharmony_ci{
8308c2ecf20Sopenharmony_ci	mutex_lock(&mgmt_chan_list_lock);
8318c2ecf20Sopenharmony_ci	list_del(&c->list);
8328c2ecf20Sopenharmony_ci	mutex_unlock(&mgmt_chan_list_lock);
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_mgmt_chan_unregister);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_cistatic int hci_sock_release(struct socket *sock)
8378c2ecf20Sopenharmony_ci{
8388c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
8398c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
8408c2ecf20Sopenharmony_ci	struct sk_buff *skb;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	BT_DBG("sock %p sk %p", sock, sk);
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (!sk)
8458c2ecf20Sopenharmony_ci		return 0;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	lock_sock(sk);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	switch (hci_pi(sk)->channel) {
8508c2ecf20Sopenharmony_ci	case HCI_CHANNEL_MONITOR:
8518c2ecf20Sopenharmony_ci		atomic_dec(&monitor_promisc);
8528c2ecf20Sopenharmony_ci		break;
8538c2ecf20Sopenharmony_ci	case HCI_CHANNEL_RAW:
8548c2ecf20Sopenharmony_ci	case HCI_CHANNEL_USER:
8558c2ecf20Sopenharmony_ci	case HCI_CHANNEL_CONTROL:
8568c2ecf20Sopenharmony_ci		/* Send event to monitor */
8578c2ecf20Sopenharmony_ci		skb = create_monitor_ctrl_close(sk);
8588c2ecf20Sopenharmony_ci		if (skb) {
8598c2ecf20Sopenharmony_ci			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
8608c2ecf20Sopenharmony_ci					    HCI_SOCK_TRUSTED, NULL);
8618c2ecf20Sopenharmony_ci			kfree_skb(skb);
8628c2ecf20Sopenharmony_ci		}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci		hci_sock_free_cookie(sk);
8658c2ecf20Sopenharmony_ci		break;
8668c2ecf20Sopenharmony_ci	}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	bt_sock_unlink(&hci_sk_list, sk);
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	hdev = hci_pi(sk)->hdev;
8718c2ecf20Sopenharmony_ci	if (hdev) {
8728c2ecf20Sopenharmony_ci		if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
8738c2ecf20Sopenharmony_ci			/* When releasing a user channel exclusive access,
8748c2ecf20Sopenharmony_ci			 * call hci_dev_do_close directly instead of calling
8758c2ecf20Sopenharmony_ci			 * hci_dev_close to ensure the exclusive access will
8768c2ecf20Sopenharmony_ci			 * be released and the controller brought back down.
8778c2ecf20Sopenharmony_ci			 *
8788c2ecf20Sopenharmony_ci			 * The checking of HCI_AUTO_OFF is not needed in this
8798c2ecf20Sopenharmony_ci			 * case since it will have been cleared already when
8808c2ecf20Sopenharmony_ci			 * opening the user channel.
8818c2ecf20Sopenharmony_ci			 */
8828c2ecf20Sopenharmony_ci			hci_dev_do_close(hdev);
8838c2ecf20Sopenharmony_ci			hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
8848c2ecf20Sopenharmony_ci			mgmt_index_added(hdev);
8858c2ecf20Sopenharmony_ci		}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci		atomic_dec(&hdev->promisc);
8888c2ecf20Sopenharmony_ci		hci_dev_put(hdev);
8898c2ecf20Sopenharmony_ci	}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	sock_orphan(sk);
8928c2ecf20Sopenharmony_ci	release_sock(sk);
8938c2ecf20Sopenharmony_ci	sock_put(sk);
8948c2ecf20Sopenharmony_ci	return 0;
8958c2ecf20Sopenharmony_ci}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_cistatic int hci_sock_reject_list_add(struct hci_dev *hdev, void __user *arg)
8988c2ecf20Sopenharmony_ci{
8998c2ecf20Sopenharmony_ci	bdaddr_t bdaddr;
9008c2ecf20Sopenharmony_ci	int err;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
9038c2ecf20Sopenharmony_ci		return -EFAULT;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	err = hci_bdaddr_list_add(&hdev->reject_list, &bdaddr, BDADDR_BREDR);
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	return err;
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_cistatic int hci_sock_reject_list_del(struct hci_dev *hdev, void __user *arg)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	bdaddr_t bdaddr;
9178c2ecf20Sopenharmony_ci	int err;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
9208c2ecf20Sopenharmony_ci		return -EFAULT;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	err = hci_bdaddr_list_del(&hdev->reject_list, &bdaddr, BDADDR_BREDR);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	return err;
9298c2ecf20Sopenharmony_ci}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci/* Ioctls that require bound socket */
9328c2ecf20Sopenharmony_cistatic int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
9338c2ecf20Sopenharmony_ci				unsigned long arg)
9348c2ecf20Sopenharmony_ci{
9358c2ecf20Sopenharmony_ci	struct hci_dev *hdev = hci_hdev_from_sock(sk);
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	if (IS_ERR(hdev))
9388c2ecf20Sopenharmony_ci		return PTR_ERR(hdev);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
9418c2ecf20Sopenharmony_ci		return -EBUSY;
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
9448c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	if (hdev->dev_type != HCI_PRIMARY)
9478c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	switch (cmd) {
9508c2ecf20Sopenharmony_ci	case HCISETRAW:
9518c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
9528c2ecf20Sopenharmony_ci			return -EPERM;
9538c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	case HCIGETCONNINFO:
9568c2ecf20Sopenharmony_ci		return hci_get_conn_info(hdev, (void __user *)arg);
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	case HCIGETAUTHINFO:
9598c2ecf20Sopenharmony_ci		return hci_get_auth_info(hdev, (void __user *)arg);
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	case HCIBLOCKADDR:
9628c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
9638c2ecf20Sopenharmony_ci			return -EPERM;
9648c2ecf20Sopenharmony_ci		return hci_sock_reject_list_add(hdev, (void __user *)arg);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	case HCIUNBLOCKADDR:
9678c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
9688c2ecf20Sopenharmony_ci			return -EPERM;
9698c2ecf20Sopenharmony_ci		return hci_sock_reject_list_del(hdev, (void __user *)arg);
9708c2ecf20Sopenharmony_ci	}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	return -ENOIOCTLCMD;
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
9768c2ecf20Sopenharmony_ci			  unsigned long arg)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
9798c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
9808c2ecf20Sopenharmony_ci	int err;
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	BT_DBG("cmd %x arg %lx", cmd, arg);
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	/* Make sure the cmd is valid before doing anything */
9858c2ecf20Sopenharmony_ci	switch (cmd) {
9868c2ecf20Sopenharmony_ci	case HCIGETDEVLIST:
9878c2ecf20Sopenharmony_ci	case HCIGETDEVINFO:
9888c2ecf20Sopenharmony_ci	case HCIGETCONNLIST:
9898c2ecf20Sopenharmony_ci	case HCIDEVUP:
9908c2ecf20Sopenharmony_ci	case HCIDEVDOWN:
9918c2ecf20Sopenharmony_ci	case HCIDEVRESET:
9928c2ecf20Sopenharmony_ci	case HCIDEVRESTAT:
9938c2ecf20Sopenharmony_ci	case HCISETSCAN:
9948c2ecf20Sopenharmony_ci	case HCISETAUTH:
9958c2ecf20Sopenharmony_ci	case HCISETENCRYPT:
9968c2ecf20Sopenharmony_ci	case HCISETPTYPE:
9978c2ecf20Sopenharmony_ci	case HCISETLINKPOL:
9988c2ecf20Sopenharmony_ci	case HCISETLINKMODE:
9998c2ecf20Sopenharmony_ci	case HCISETACLMTU:
10008c2ecf20Sopenharmony_ci	case HCISETSCOMTU:
10018c2ecf20Sopenharmony_ci	case HCIINQUIRY:
10028c2ecf20Sopenharmony_ci	case HCISETRAW:
10038c2ecf20Sopenharmony_ci	case HCIGETCONNINFO:
10048c2ecf20Sopenharmony_ci	case HCIGETAUTHINFO:
10058c2ecf20Sopenharmony_ci	case HCIBLOCKADDR:
10068c2ecf20Sopenharmony_ci	case HCIUNBLOCKADDR:
10078c2ecf20Sopenharmony_ci		break;
10088c2ecf20Sopenharmony_ci	default:
10098c2ecf20Sopenharmony_ci		return -ENOIOCTLCMD;
10108c2ecf20Sopenharmony_ci	}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	lock_sock(sk);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
10158c2ecf20Sopenharmony_ci		err = -EBADFD;
10168c2ecf20Sopenharmony_ci		goto done;
10178c2ecf20Sopenharmony_ci	}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	/* When calling an ioctl on an unbound raw socket, then ensure
10208c2ecf20Sopenharmony_ci	 * that the monitor gets informed. Ensure that the resulting event
10218c2ecf20Sopenharmony_ci	 * is only send once by checking if the cookie exists or not. The
10228c2ecf20Sopenharmony_ci	 * socket cookie will be only ever generated once for the lifetime
10238c2ecf20Sopenharmony_ci	 * of a given socket.
10248c2ecf20Sopenharmony_ci	 */
10258c2ecf20Sopenharmony_ci	if (hci_sock_gen_cookie(sk)) {
10268c2ecf20Sopenharmony_ci		struct sk_buff *skb;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci		/* Perform careful checks before setting the HCI_SOCK_TRUSTED
10298c2ecf20Sopenharmony_ci		 * flag. Make sure that not only the current task but also
10308c2ecf20Sopenharmony_ci		 * the socket opener has the required capability, since
10318c2ecf20Sopenharmony_ci		 * privileged programs can be tricked into making ioctl calls
10328c2ecf20Sopenharmony_ci		 * on HCI sockets, and the socket should not be marked as
10338c2ecf20Sopenharmony_ci		 * trusted simply because the ioctl caller is privileged.
10348c2ecf20Sopenharmony_ci		 */
10358c2ecf20Sopenharmony_ci		if (sk_capable(sk, CAP_NET_ADMIN))
10368c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci		/* Send event to monitor */
10398c2ecf20Sopenharmony_ci		skb = create_monitor_ctrl_open(sk);
10408c2ecf20Sopenharmony_ci		if (skb) {
10418c2ecf20Sopenharmony_ci			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
10428c2ecf20Sopenharmony_ci					    HCI_SOCK_TRUSTED, NULL);
10438c2ecf20Sopenharmony_ci			kfree_skb(skb);
10448c2ecf20Sopenharmony_ci		}
10458c2ecf20Sopenharmony_ci	}
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	release_sock(sk);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	switch (cmd) {
10508c2ecf20Sopenharmony_ci	case HCIGETDEVLIST:
10518c2ecf20Sopenharmony_ci		return hci_get_dev_list(argp);
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	case HCIGETDEVINFO:
10548c2ecf20Sopenharmony_ci		return hci_get_dev_info(argp);
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	case HCIGETCONNLIST:
10578c2ecf20Sopenharmony_ci		return hci_get_conn_list(argp);
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	case HCIDEVUP:
10608c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
10618c2ecf20Sopenharmony_ci			return -EPERM;
10628c2ecf20Sopenharmony_ci		return hci_dev_open(arg);
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	case HCIDEVDOWN:
10658c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
10668c2ecf20Sopenharmony_ci			return -EPERM;
10678c2ecf20Sopenharmony_ci		return hci_dev_close(arg);
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	case HCIDEVRESET:
10708c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
10718c2ecf20Sopenharmony_ci			return -EPERM;
10728c2ecf20Sopenharmony_ci		return hci_dev_reset(arg);
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	case HCIDEVRESTAT:
10758c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
10768c2ecf20Sopenharmony_ci			return -EPERM;
10778c2ecf20Sopenharmony_ci		return hci_dev_reset_stat(arg);
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	case HCISETSCAN:
10808c2ecf20Sopenharmony_ci	case HCISETAUTH:
10818c2ecf20Sopenharmony_ci	case HCISETENCRYPT:
10828c2ecf20Sopenharmony_ci	case HCISETPTYPE:
10838c2ecf20Sopenharmony_ci	case HCISETLINKPOL:
10848c2ecf20Sopenharmony_ci	case HCISETLINKMODE:
10858c2ecf20Sopenharmony_ci	case HCISETACLMTU:
10868c2ecf20Sopenharmony_ci	case HCISETSCOMTU:
10878c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN))
10888c2ecf20Sopenharmony_ci			return -EPERM;
10898c2ecf20Sopenharmony_ci		return hci_dev_cmd(cmd, argp);
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	case HCIINQUIRY:
10928c2ecf20Sopenharmony_ci		return hci_inquiry(argp);
10938c2ecf20Sopenharmony_ci	}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	lock_sock(sk);
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	err = hci_sock_bound_ioctl(sk, cmd, arg);
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_cidone:
11008c2ecf20Sopenharmony_ci	release_sock(sk);
11018c2ecf20Sopenharmony_ci	return err;
11028c2ecf20Sopenharmony_ci}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
11058c2ecf20Sopenharmony_cistatic int hci_sock_compat_ioctl(struct socket *sock, unsigned int cmd,
11068c2ecf20Sopenharmony_ci				 unsigned long arg)
11078c2ecf20Sopenharmony_ci{
11088c2ecf20Sopenharmony_ci	switch (cmd) {
11098c2ecf20Sopenharmony_ci	case HCIDEVUP:
11108c2ecf20Sopenharmony_ci	case HCIDEVDOWN:
11118c2ecf20Sopenharmony_ci	case HCIDEVRESET:
11128c2ecf20Sopenharmony_ci	case HCIDEVRESTAT:
11138c2ecf20Sopenharmony_ci		return hci_sock_ioctl(sock, cmd, arg);
11148c2ecf20Sopenharmony_ci	}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	return hci_sock_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
11178c2ecf20Sopenharmony_ci}
11188c2ecf20Sopenharmony_ci#endif
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_cistatic int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
11218c2ecf20Sopenharmony_ci			 int addr_len)
11228c2ecf20Sopenharmony_ci{
11238c2ecf20Sopenharmony_ci	struct sockaddr_hci haddr;
11248c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
11258c2ecf20Sopenharmony_ci	struct hci_dev *hdev = NULL;
11268c2ecf20Sopenharmony_ci	struct sk_buff *skb;
11278c2ecf20Sopenharmony_ci	int len, err = 0;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	BT_DBG("sock %p sk %p", sock, sk);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	if (!addr)
11328c2ecf20Sopenharmony_ci		return -EINVAL;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	memset(&haddr, 0, sizeof(haddr));
11358c2ecf20Sopenharmony_ci	len = min_t(unsigned int, sizeof(haddr), addr_len);
11368c2ecf20Sopenharmony_ci	memcpy(&haddr, addr, len);
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	if (haddr.hci_family != AF_BLUETOOTH)
11398c2ecf20Sopenharmony_ci		return -EINVAL;
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	lock_sock(sk);
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	/* Allow detaching from dead device and attaching to alive device, if
11448c2ecf20Sopenharmony_ci	 * the caller wants to re-bind (instead of close) this socket in
11458c2ecf20Sopenharmony_ci	 * response to hci_sock_dev_event(HCI_DEV_UNREG) notification.
11468c2ecf20Sopenharmony_ci	 */
11478c2ecf20Sopenharmony_ci	hdev = hci_pi(sk)->hdev;
11488c2ecf20Sopenharmony_ci	if (hdev && hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
11498c2ecf20Sopenharmony_ci		hci_pi(sk)->hdev = NULL;
11508c2ecf20Sopenharmony_ci		sk->sk_state = BT_OPEN;
11518c2ecf20Sopenharmony_ci		hci_dev_put(hdev);
11528c2ecf20Sopenharmony_ci	}
11538c2ecf20Sopenharmony_ci	hdev = NULL;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	if (sk->sk_state == BT_BOUND) {
11568c2ecf20Sopenharmony_ci		err = -EALREADY;
11578c2ecf20Sopenharmony_ci		goto done;
11588c2ecf20Sopenharmony_ci	}
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	switch (haddr.hci_channel) {
11618c2ecf20Sopenharmony_ci	case HCI_CHANNEL_RAW:
11628c2ecf20Sopenharmony_ci		if (hci_pi(sk)->hdev) {
11638c2ecf20Sopenharmony_ci			err = -EALREADY;
11648c2ecf20Sopenharmony_ci			goto done;
11658c2ecf20Sopenharmony_ci		}
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci		if (haddr.hci_dev != HCI_DEV_NONE) {
11688c2ecf20Sopenharmony_ci			hdev = hci_dev_get(haddr.hci_dev);
11698c2ecf20Sopenharmony_ci			if (!hdev) {
11708c2ecf20Sopenharmony_ci				err = -ENODEV;
11718c2ecf20Sopenharmony_ci				goto done;
11728c2ecf20Sopenharmony_ci			}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci			atomic_inc(&hdev->promisc);
11758c2ecf20Sopenharmony_ci		}
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci		hci_pi(sk)->channel = haddr.hci_channel;
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci		if (!hci_sock_gen_cookie(sk)) {
11808c2ecf20Sopenharmony_ci			/* In the case when a cookie has already been assigned,
11818c2ecf20Sopenharmony_ci			 * then there has been already an ioctl issued against
11828c2ecf20Sopenharmony_ci			 * an unbound socket and with that triggerd an open
11838c2ecf20Sopenharmony_ci			 * notification. Send a close notification first to
11848c2ecf20Sopenharmony_ci			 * allow the state transition to bounded.
11858c2ecf20Sopenharmony_ci			 */
11868c2ecf20Sopenharmony_ci			skb = create_monitor_ctrl_close(sk);
11878c2ecf20Sopenharmony_ci			if (skb) {
11888c2ecf20Sopenharmony_ci				hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
11898c2ecf20Sopenharmony_ci						    HCI_SOCK_TRUSTED, NULL);
11908c2ecf20Sopenharmony_ci				kfree_skb(skb);
11918c2ecf20Sopenharmony_ci			}
11928c2ecf20Sopenharmony_ci		}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci		if (capable(CAP_NET_ADMIN))
11958c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci		hci_pi(sk)->hdev = hdev;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci		/* Send event to monitor */
12008c2ecf20Sopenharmony_ci		skb = create_monitor_ctrl_open(sk);
12018c2ecf20Sopenharmony_ci		if (skb) {
12028c2ecf20Sopenharmony_ci			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
12038c2ecf20Sopenharmony_ci					    HCI_SOCK_TRUSTED, NULL);
12048c2ecf20Sopenharmony_ci			kfree_skb(skb);
12058c2ecf20Sopenharmony_ci		}
12068c2ecf20Sopenharmony_ci		break;
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	case HCI_CHANNEL_USER:
12098c2ecf20Sopenharmony_ci		if (hci_pi(sk)->hdev) {
12108c2ecf20Sopenharmony_ci			err = -EALREADY;
12118c2ecf20Sopenharmony_ci			goto done;
12128c2ecf20Sopenharmony_ci		}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci		if (haddr.hci_dev == HCI_DEV_NONE) {
12158c2ecf20Sopenharmony_ci			err = -EINVAL;
12168c2ecf20Sopenharmony_ci			goto done;
12178c2ecf20Sopenharmony_ci		}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN)) {
12208c2ecf20Sopenharmony_ci			err = -EPERM;
12218c2ecf20Sopenharmony_ci			goto done;
12228c2ecf20Sopenharmony_ci		}
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci		hdev = hci_dev_get(haddr.hci_dev);
12258c2ecf20Sopenharmony_ci		if (!hdev) {
12268c2ecf20Sopenharmony_ci			err = -ENODEV;
12278c2ecf20Sopenharmony_ci			goto done;
12288c2ecf20Sopenharmony_ci		}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci		if (test_bit(HCI_INIT, &hdev->flags) ||
12318c2ecf20Sopenharmony_ci		    hci_dev_test_flag(hdev, HCI_SETUP) ||
12328c2ecf20Sopenharmony_ci		    hci_dev_test_flag(hdev, HCI_CONFIG) ||
12338c2ecf20Sopenharmony_ci		    (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) &&
12348c2ecf20Sopenharmony_ci		     test_bit(HCI_UP, &hdev->flags))) {
12358c2ecf20Sopenharmony_ci			err = -EBUSY;
12368c2ecf20Sopenharmony_ci			hci_dev_put(hdev);
12378c2ecf20Sopenharmony_ci			goto done;
12388c2ecf20Sopenharmony_ci		}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci		if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) {
12418c2ecf20Sopenharmony_ci			err = -EUSERS;
12428c2ecf20Sopenharmony_ci			hci_dev_put(hdev);
12438c2ecf20Sopenharmony_ci			goto done;
12448c2ecf20Sopenharmony_ci		}
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci		mgmt_index_removed(hdev);
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci		err = hci_dev_open(hdev->id);
12498c2ecf20Sopenharmony_ci		if (err) {
12508c2ecf20Sopenharmony_ci			if (err == -EALREADY) {
12518c2ecf20Sopenharmony_ci				/* In case the transport is already up and
12528c2ecf20Sopenharmony_ci				 * running, clear the error here.
12538c2ecf20Sopenharmony_ci				 *
12548c2ecf20Sopenharmony_ci				 * This can happen when opening a user
12558c2ecf20Sopenharmony_ci				 * channel and HCI_AUTO_OFF grace period
12568c2ecf20Sopenharmony_ci				 * is still active.
12578c2ecf20Sopenharmony_ci				 */
12588c2ecf20Sopenharmony_ci				err = 0;
12598c2ecf20Sopenharmony_ci			} else {
12608c2ecf20Sopenharmony_ci				hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
12618c2ecf20Sopenharmony_ci				mgmt_index_added(hdev);
12628c2ecf20Sopenharmony_ci				hci_dev_put(hdev);
12638c2ecf20Sopenharmony_ci				goto done;
12648c2ecf20Sopenharmony_ci			}
12658c2ecf20Sopenharmony_ci		}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci		hci_pi(sk)->channel = haddr.hci_channel;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci		if (!hci_sock_gen_cookie(sk)) {
12708c2ecf20Sopenharmony_ci			/* In the case when a cookie has already been assigned,
12718c2ecf20Sopenharmony_ci			 * this socket will transition from a raw socket into
12728c2ecf20Sopenharmony_ci			 * a user channel socket. For a clean transition, send
12738c2ecf20Sopenharmony_ci			 * the close notification first.
12748c2ecf20Sopenharmony_ci			 */
12758c2ecf20Sopenharmony_ci			skb = create_monitor_ctrl_close(sk);
12768c2ecf20Sopenharmony_ci			if (skb) {
12778c2ecf20Sopenharmony_ci				hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
12788c2ecf20Sopenharmony_ci						    HCI_SOCK_TRUSTED, NULL);
12798c2ecf20Sopenharmony_ci				kfree_skb(skb);
12808c2ecf20Sopenharmony_ci			}
12818c2ecf20Sopenharmony_ci		}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci		/* The user channel is restricted to CAP_NET_ADMIN
12848c2ecf20Sopenharmony_ci		 * capabilities and with that implicitly trusted.
12858c2ecf20Sopenharmony_ci		 */
12868c2ecf20Sopenharmony_ci		hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci		hci_pi(sk)->hdev = hdev;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci		/* Send event to monitor */
12918c2ecf20Sopenharmony_ci		skb = create_monitor_ctrl_open(sk);
12928c2ecf20Sopenharmony_ci		if (skb) {
12938c2ecf20Sopenharmony_ci			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
12948c2ecf20Sopenharmony_ci					    HCI_SOCK_TRUSTED, NULL);
12958c2ecf20Sopenharmony_ci			kfree_skb(skb);
12968c2ecf20Sopenharmony_ci		}
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci		atomic_inc(&hdev->promisc);
12998c2ecf20Sopenharmony_ci		break;
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	case HCI_CHANNEL_MONITOR:
13028c2ecf20Sopenharmony_ci		if (haddr.hci_dev != HCI_DEV_NONE) {
13038c2ecf20Sopenharmony_ci			err = -EINVAL;
13048c2ecf20Sopenharmony_ci			goto done;
13058c2ecf20Sopenharmony_ci		}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_RAW)) {
13088c2ecf20Sopenharmony_ci			err = -EPERM;
13098c2ecf20Sopenharmony_ci			goto done;
13108c2ecf20Sopenharmony_ci		}
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci		hci_pi(sk)->channel = haddr.hci_channel;
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci		/* The monitor interface is restricted to CAP_NET_RAW
13158c2ecf20Sopenharmony_ci		 * capabilities and with that implicitly trusted.
13168c2ecf20Sopenharmony_ci		 */
13178c2ecf20Sopenharmony_ci		hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci		send_monitor_note(sk, "Linux version %s (%s)",
13208c2ecf20Sopenharmony_ci				  init_utsname()->release,
13218c2ecf20Sopenharmony_ci				  init_utsname()->machine);
13228c2ecf20Sopenharmony_ci		send_monitor_note(sk, "Bluetooth subsystem version %u.%u",
13238c2ecf20Sopenharmony_ci				  BT_SUBSYS_VERSION, BT_SUBSYS_REVISION);
13248c2ecf20Sopenharmony_ci		send_monitor_replay(sk);
13258c2ecf20Sopenharmony_ci		send_monitor_control_replay(sk);
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci		atomic_inc(&monitor_promisc);
13288c2ecf20Sopenharmony_ci		break;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	case HCI_CHANNEL_LOGGING:
13318c2ecf20Sopenharmony_ci		if (haddr.hci_dev != HCI_DEV_NONE) {
13328c2ecf20Sopenharmony_ci			err = -EINVAL;
13338c2ecf20Sopenharmony_ci			goto done;
13348c2ecf20Sopenharmony_ci		}
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_ADMIN)) {
13378c2ecf20Sopenharmony_ci			err = -EPERM;
13388c2ecf20Sopenharmony_ci			goto done;
13398c2ecf20Sopenharmony_ci		}
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci		hci_pi(sk)->channel = haddr.hci_channel;
13428c2ecf20Sopenharmony_ci		break;
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	default:
13458c2ecf20Sopenharmony_ci		if (!hci_mgmt_chan_find(haddr.hci_channel)) {
13468c2ecf20Sopenharmony_ci			err = -EINVAL;
13478c2ecf20Sopenharmony_ci			goto done;
13488c2ecf20Sopenharmony_ci		}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci		if (haddr.hci_dev != HCI_DEV_NONE) {
13518c2ecf20Sopenharmony_ci			err = -EINVAL;
13528c2ecf20Sopenharmony_ci			goto done;
13538c2ecf20Sopenharmony_ci		}
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci		/* Users with CAP_NET_ADMIN capabilities are allowed
13568c2ecf20Sopenharmony_ci		 * access to all management commands and events. For
13578c2ecf20Sopenharmony_ci		 * untrusted users the interface is restricted and
13588c2ecf20Sopenharmony_ci		 * also only untrusted events are sent.
13598c2ecf20Sopenharmony_ci		 */
13608c2ecf20Sopenharmony_ci		if (capable(CAP_NET_ADMIN))
13618c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci		hci_pi(sk)->channel = haddr.hci_channel;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci		/* At the moment the index and unconfigured index events
13668c2ecf20Sopenharmony_ci		 * are enabled unconditionally. Setting them on each
13678c2ecf20Sopenharmony_ci		 * socket when binding keeps this functionality. They
13688c2ecf20Sopenharmony_ci		 * however might be cleared later and then sending of these
13698c2ecf20Sopenharmony_ci		 * events will be disabled, but that is then intentional.
13708c2ecf20Sopenharmony_ci		 *
13718c2ecf20Sopenharmony_ci		 * This also enables generic events that are safe to be
13728c2ecf20Sopenharmony_ci		 * received by untrusted users. Example for such events
13738c2ecf20Sopenharmony_ci		 * are changes to settings, class of device, name etc.
13748c2ecf20Sopenharmony_ci		 */
13758c2ecf20Sopenharmony_ci		if (hci_pi(sk)->channel == HCI_CHANNEL_CONTROL) {
13768c2ecf20Sopenharmony_ci			if (!hci_sock_gen_cookie(sk)) {
13778c2ecf20Sopenharmony_ci				/* In the case when a cookie has already been
13788c2ecf20Sopenharmony_ci				 * assigned, this socket will transtion from
13798c2ecf20Sopenharmony_ci				 * a raw socket into a control socket. To
13808c2ecf20Sopenharmony_ci				 * allow for a clean transtion, send the
13818c2ecf20Sopenharmony_ci				 * close notification first.
13828c2ecf20Sopenharmony_ci				 */
13838c2ecf20Sopenharmony_ci				skb = create_monitor_ctrl_close(sk);
13848c2ecf20Sopenharmony_ci				if (skb) {
13858c2ecf20Sopenharmony_ci					hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
13868c2ecf20Sopenharmony_ci							    HCI_SOCK_TRUSTED, NULL);
13878c2ecf20Sopenharmony_ci					kfree_skb(skb);
13888c2ecf20Sopenharmony_ci				}
13898c2ecf20Sopenharmony_ci			}
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci			/* Send event to monitor */
13928c2ecf20Sopenharmony_ci			skb = create_monitor_ctrl_open(sk);
13938c2ecf20Sopenharmony_ci			if (skb) {
13948c2ecf20Sopenharmony_ci				hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
13958c2ecf20Sopenharmony_ci						    HCI_SOCK_TRUSTED, NULL);
13968c2ecf20Sopenharmony_ci				kfree_skb(skb);
13978c2ecf20Sopenharmony_ci			}
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS);
14008c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
14018c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_MGMT_OPTION_EVENTS);
14028c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_MGMT_SETTING_EVENTS);
14038c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
14048c2ecf20Sopenharmony_ci			hci_sock_set_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
14058c2ecf20Sopenharmony_ci		}
14068c2ecf20Sopenharmony_ci		break;
14078c2ecf20Sopenharmony_ci	}
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	sk->sk_state = BT_BOUND;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_cidone:
14128c2ecf20Sopenharmony_ci	release_sock(sk);
14138c2ecf20Sopenharmony_ci	return err;
14148c2ecf20Sopenharmony_ci}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_cistatic int hci_sock_getname(struct socket *sock, struct sockaddr *addr,
14178c2ecf20Sopenharmony_ci			    int peer)
14188c2ecf20Sopenharmony_ci{
14198c2ecf20Sopenharmony_ci	struct sockaddr_hci *haddr = (struct sockaddr_hci *)addr;
14208c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
14218c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
14228c2ecf20Sopenharmony_ci	int err = 0;
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	BT_DBG("sock %p sk %p", sock, sk);
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	if (peer)
14278c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	lock_sock(sk);
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	hdev = hci_hdev_from_sock(sk);
14328c2ecf20Sopenharmony_ci	if (IS_ERR(hdev)) {
14338c2ecf20Sopenharmony_ci		err = PTR_ERR(hdev);
14348c2ecf20Sopenharmony_ci		goto done;
14358c2ecf20Sopenharmony_ci	}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	haddr->hci_family = AF_BLUETOOTH;
14388c2ecf20Sopenharmony_ci	haddr->hci_dev    = hdev->id;
14398c2ecf20Sopenharmony_ci	haddr->hci_channel= hci_pi(sk)->channel;
14408c2ecf20Sopenharmony_ci	err = sizeof(*haddr);
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_cidone:
14438c2ecf20Sopenharmony_ci	release_sock(sk);
14448c2ecf20Sopenharmony_ci	return err;
14458c2ecf20Sopenharmony_ci}
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_cistatic void hci_sock_cmsg(struct sock *sk, struct msghdr *msg,
14488c2ecf20Sopenharmony_ci			  struct sk_buff *skb)
14498c2ecf20Sopenharmony_ci{
14508c2ecf20Sopenharmony_ci	__u8 mask = hci_pi(sk)->cmsg_mask;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	if (mask & HCI_CMSG_DIR) {
14538c2ecf20Sopenharmony_ci		int incoming = bt_cb(skb)->incoming;
14548c2ecf20Sopenharmony_ci		put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming),
14558c2ecf20Sopenharmony_ci			 &incoming);
14568c2ecf20Sopenharmony_ci	}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	if (mask & HCI_CMSG_TSTAMP) {
14598c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
14608c2ecf20Sopenharmony_ci		struct old_timeval32 ctv;
14618c2ecf20Sopenharmony_ci#endif
14628c2ecf20Sopenharmony_ci		struct __kernel_old_timeval tv;
14638c2ecf20Sopenharmony_ci		void *data;
14648c2ecf20Sopenharmony_ci		int len;
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci		skb_get_timestamp(skb, &tv);
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci		data = &tv;
14698c2ecf20Sopenharmony_ci		len = sizeof(tv);
14708c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
14718c2ecf20Sopenharmony_ci		if (!COMPAT_USE_64BIT_TIME &&
14728c2ecf20Sopenharmony_ci		    (msg->msg_flags & MSG_CMSG_COMPAT)) {
14738c2ecf20Sopenharmony_ci			ctv.tv_sec = tv.tv_sec;
14748c2ecf20Sopenharmony_ci			ctv.tv_usec = tv.tv_usec;
14758c2ecf20Sopenharmony_ci			data = &ctv;
14768c2ecf20Sopenharmony_ci			len = sizeof(ctv);
14778c2ecf20Sopenharmony_ci		}
14788c2ecf20Sopenharmony_ci#endif
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci		put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
14818c2ecf20Sopenharmony_ci	}
14828c2ecf20Sopenharmony_ci}
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_cistatic int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
14858c2ecf20Sopenharmony_ci			    size_t len, int flags)
14868c2ecf20Sopenharmony_ci{
14878c2ecf20Sopenharmony_ci	int noblock = flags & MSG_DONTWAIT;
14888c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
14898c2ecf20Sopenharmony_ci	struct sk_buff *skb;
14908c2ecf20Sopenharmony_ci	int copied, err;
14918c2ecf20Sopenharmony_ci	unsigned int skblen;
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci	BT_DBG("sock %p, sk %p", sock, sk);
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	if (flags & MSG_OOB)
14968c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	if (hci_pi(sk)->channel == HCI_CHANNEL_LOGGING)
14998c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	if (sk->sk_state == BT_CLOSED)
15028c2ecf20Sopenharmony_ci		return 0;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	skb = skb_recv_datagram(sk, flags, noblock, &err);
15058c2ecf20Sopenharmony_ci	if (!skb)
15068c2ecf20Sopenharmony_ci		return err;
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	skblen = skb->len;
15098c2ecf20Sopenharmony_ci	copied = skb->len;
15108c2ecf20Sopenharmony_ci	if (len < copied) {
15118c2ecf20Sopenharmony_ci		msg->msg_flags |= MSG_TRUNC;
15128c2ecf20Sopenharmony_ci		copied = len;
15138c2ecf20Sopenharmony_ci	}
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci	skb_reset_transport_header(skb);
15168c2ecf20Sopenharmony_ci	err = skb_copy_datagram_msg(skb, 0, msg, copied);
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci	switch (hci_pi(sk)->channel) {
15198c2ecf20Sopenharmony_ci	case HCI_CHANNEL_RAW:
15208c2ecf20Sopenharmony_ci		hci_sock_cmsg(sk, msg, skb);
15218c2ecf20Sopenharmony_ci		break;
15228c2ecf20Sopenharmony_ci	case HCI_CHANNEL_USER:
15238c2ecf20Sopenharmony_ci	case HCI_CHANNEL_MONITOR:
15248c2ecf20Sopenharmony_ci		sock_recv_timestamp(msg, sk, skb);
15258c2ecf20Sopenharmony_ci		break;
15268c2ecf20Sopenharmony_ci	default:
15278c2ecf20Sopenharmony_ci		if (hci_mgmt_chan_find(hci_pi(sk)->channel))
15288c2ecf20Sopenharmony_ci			sock_recv_timestamp(msg, sk, skb);
15298c2ecf20Sopenharmony_ci		break;
15308c2ecf20Sopenharmony_ci	}
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	skb_free_datagram(sk, skb);
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	if (flags & MSG_TRUNC)
15358c2ecf20Sopenharmony_ci		copied = skblen;
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	return err ? : copied;
15388c2ecf20Sopenharmony_ci}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_cistatic int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk,
15418c2ecf20Sopenharmony_ci			struct msghdr *msg, size_t msglen)
15428c2ecf20Sopenharmony_ci{
15438c2ecf20Sopenharmony_ci	void *buf;
15448c2ecf20Sopenharmony_ci	u8 *cp;
15458c2ecf20Sopenharmony_ci	struct mgmt_hdr *hdr;
15468c2ecf20Sopenharmony_ci	u16 opcode, index, len;
15478c2ecf20Sopenharmony_ci	struct hci_dev *hdev = NULL;
15488c2ecf20Sopenharmony_ci	const struct hci_mgmt_handler *handler;
15498c2ecf20Sopenharmony_ci	bool var_len, no_hdev;
15508c2ecf20Sopenharmony_ci	int err;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	BT_DBG("got %zu bytes", msglen);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	if (msglen < sizeof(*hdr))
15558c2ecf20Sopenharmony_ci		return -EINVAL;
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	buf = kmalloc(msglen, GFP_KERNEL);
15588c2ecf20Sopenharmony_ci	if (!buf)
15598c2ecf20Sopenharmony_ci		return -ENOMEM;
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	if (memcpy_from_msg(buf, msg, msglen)) {
15628c2ecf20Sopenharmony_ci		err = -EFAULT;
15638c2ecf20Sopenharmony_ci		goto done;
15648c2ecf20Sopenharmony_ci	}
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	hdr = buf;
15678c2ecf20Sopenharmony_ci	opcode = __le16_to_cpu(hdr->opcode);
15688c2ecf20Sopenharmony_ci	index = __le16_to_cpu(hdr->index);
15698c2ecf20Sopenharmony_ci	len = __le16_to_cpu(hdr->len);
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	if (len != msglen - sizeof(*hdr)) {
15728c2ecf20Sopenharmony_ci		err = -EINVAL;
15738c2ecf20Sopenharmony_ci		goto done;
15748c2ecf20Sopenharmony_ci	}
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	if (chan->channel == HCI_CHANNEL_CONTROL) {
15778c2ecf20Sopenharmony_ci		struct sk_buff *skb;
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci		/* Send event to monitor */
15808c2ecf20Sopenharmony_ci		skb = create_monitor_ctrl_command(sk, index, opcode, len,
15818c2ecf20Sopenharmony_ci						  buf + sizeof(*hdr));
15828c2ecf20Sopenharmony_ci		if (skb) {
15838c2ecf20Sopenharmony_ci			hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
15848c2ecf20Sopenharmony_ci					    HCI_SOCK_TRUSTED, NULL);
15858c2ecf20Sopenharmony_ci			kfree_skb(skb);
15868c2ecf20Sopenharmony_ci		}
15878c2ecf20Sopenharmony_ci	}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	if (opcode >= chan->handler_count ||
15908c2ecf20Sopenharmony_ci	    chan->handlers[opcode].func == NULL) {
15918c2ecf20Sopenharmony_ci		BT_DBG("Unknown op %u", opcode);
15928c2ecf20Sopenharmony_ci		err = mgmt_cmd_status(sk, index, opcode,
15938c2ecf20Sopenharmony_ci				      MGMT_STATUS_UNKNOWN_COMMAND);
15948c2ecf20Sopenharmony_ci		goto done;
15958c2ecf20Sopenharmony_ci	}
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	handler = &chan->handlers[opcode];
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_ci	if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) &&
16008c2ecf20Sopenharmony_ci	    !(handler->flags & HCI_MGMT_UNTRUSTED)) {
16018c2ecf20Sopenharmony_ci		err = mgmt_cmd_status(sk, index, opcode,
16028c2ecf20Sopenharmony_ci				      MGMT_STATUS_PERMISSION_DENIED);
16038c2ecf20Sopenharmony_ci		goto done;
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	if (index != MGMT_INDEX_NONE) {
16078c2ecf20Sopenharmony_ci		hdev = hci_dev_get(index);
16088c2ecf20Sopenharmony_ci		if (!hdev) {
16098c2ecf20Sopenharmony_ci			err = mgmt_cmd_status(sk, index, opcode,
16108c2ecf20Sopenharmony_ci					      MGMT_STATUS_INVALID_INDEX);
16118c2ecf20Sopenharmony_ci			goto done;
16128c2ecf20Sopenharmony_ci		}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_SETUP) ||
16158c2ecf20Sopenharmony_ci		    hci_dev_test_flag(hdev, HCI_CONFIG) ||
16168c2ecf20Sopenharmony_ci		    hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
16178c2ecf20Sopenharmony_ci			err = mgmt_cmd_status(sk, index, opcode,
16188c2ecf20Sopenharmony_ci					      MGMT_STATUS_INVALID_INDEX);
16198c2ecf20Sopenharmony_ci			goto done;
16208c2ecf20Sopenharmony_ci		}
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
16238c2ecf20Sopenharmony_ci		    !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
16248c2ecf20Sopenharmony_ci			err = mgmt_cmd_status(sk, index, opcode,
16258c2ecf20Sopenharmony_ci					      MGMT_STATUS_INVALID_INDEX);
16268c2ecf20Sopenharmony_ci			goto done;
16278c2ecf20Sopenharmony_ci		}
16288c2ecf20Sopenharmony_ci	}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	if (!(handler->flags & HCI_MGMT_HDEV_OPTIONAL)) {
16318c2ecf20Sopenharmony_ci		no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
16328c2ecf20Sopenharmony_ci		if (no_hdev != !hdev) {
16338c2ecf20Sopenharmony_ci			err = mgmt_cmd_status(sk, index, opcode,
16348c2ecf20Sopenharmony_ci					      MGMT_STATUS_INVALID_INDEX);
16358c2ecf20Sopenharmony_ci			goto done;
16368c2ecf20Sopenharmony_ci		}
16378c2ecf20Sopenharmony_ci	}
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	var_len = (handler->flags & HCI_MGMT_VAR_LEN);
16408c2ecf20Sopenharmony_ci	if ((var_len && len < handler->data_len) ||
16418c2ecf20Sopenharmony_ci	    (!var_len && len != handler->data_len)) {
16428c2ecf20Sopenharmony_ci		err = mgmt_cmd_status(sk, index, opcode,
16438c2ecf20Sopenharmony_ci				      MGMT_STATUS_INVALID_PARAMS);
16448c2ecf20Sopenharmony_ci		goto done;
16458c2ecf20Sopenharmony_ci	}
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	if (hdev && chan->hdev_init)
16488c2ecf20Sopenharmony_ci		chan->hdev_init(sk, hdev);
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	cp = buf + sizeof(*hdr);
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	err = handler->func(sk, hdev, cp, len);
16538c2ecf20Sopenharmony_ci	if (err < 0)
16548c2ecf20Sopenharmony_ci		goto done;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	err = msglen;
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_cidone:
16598c2ecf20Sopenharmony_ci	if (hdev)
16608c2ecf20Sopenharmony_ci		hci_dev_put(hdev);
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	kfree(buf);
16638c2ecf20Sopenharmony_ci	return err;
16648c2ecf20Sopenharmony_ci}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_cistatic int hci_logging_frame(struct sock *sk, struct msghdr *msg, int len)
16678c2ecf20Sopenharmony_ci{
16688c2ecf20Sopenharmony_ci	struct hci_mon_hdr *hdr;
16698c2ecf20Sopenharmony_ci	struct sk_buff *skb;
16708c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
16718c2ecf20Sopenharmony_ci	u16 index;
16728c2ecf20Sopenharmony_ci	int err;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	/* The logging frame consists at minimum of the standard header,
16758c2ecf20Sopenharmony_ci	 * the priority byte, the ident length byte and at least one string
16768c2ecf20Sopenharmony_ci	 * terminator NUL byte. Anything shorter are invalid packets.
16778c2ecf20Sopenharmony_ci	 */
16788c2ecf20Sopenharmony_ci	if (len < sizeof(*hdr) + 3)
16798c2ecf20Sopenharmony_ci		return -EINVAL;
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
16828c2ecf20Sopenharmony_ci	if (!skb)
16838c2ecf20Sopenharmony_ci		return err;
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
16868c2ecf20Sopenharmony_ci		err = -EFAULT;
16878c2ecf20Sopenharmony_ci		goto drop;
16888c2ecf20Sopenharmony_ci	}
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	hdr = (void *)skb->data;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	if (__le16_to_cpu(hdr->len) != len - sizeof(*hdr)) {
16938c2ecf20Sopenharmony_ci		err = -EINVAL;
16948c2ecf20Sopenharmony_ci		goto drop;
16958c2ecf20Sopenharmony_ci	}
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	if (__le16_to_cpu(hdr->opcode) == 0x0000) {
16988c2ecf20Sopenharmony_ci		__u8 priority = skb->data[sizeof(*hdr)];
16998c2ecf20Sopenharmony_ci		__u8 ident_len = skb->data[sizeof(*hdr) + 1];
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci		/* Only the priorities 0-7 are valid and with that any other
17028c2ecf20Sopenharmony_ci		 * value results in an invalid packet.
17038c2ecf20Sopenharmony_ci		 *
17048c2ecf20Sopenharmony_ci		 * The priority byte is followed by an ident length byte and
17058c2ecf20Sopenharmony_ci		 * the NUL terminated ident string. Check that the ident
17068c2ecf20Sopenharmony_ci		 * length is not overflowing the packet and also that the
17078c2ecf20Sopenharmony_ci		 * ident string itself is NUL terminated. In case the ident
17088c2ecf20Sopenharmony_ci		 * length is zero, the length value actually doubles as NUL
17098c2ecf20Sopenharmony_ci		 * terminator identifier.
17108c2ecf20Sopenharmony_ci		 *
17118c2ecf20Sopenharmony_ci		 * The message follows the ident string (if present) and
17128c2ecf20Sopenharmony_ci		 * must be NUL terminated. Otherwise it is not a valid packet.
17138c2ecf20Sopenharmony_ci		 */
17148c2ecf20Sopenharmony_ci		if (priority > 7 || skb->data[len - 1] != 0x00 ||
17158c2ecf20Sopenharmony_ci		    ident_len > len - sizeof(*hdr) - 3 ||
17168c2ecf20Sopenharmony_ci		    skb->data[sizeof(*hdr) + ident_len + 1] != 0x00) {
17178c2ecf20Sopenharmony_ci			err = -EINVAL;
17188c2ecf20Sopenharmony_ci			goto drop;
17198c2ecf20Sopenharmony_ci		}
17208c2ecf20Sopenharmony_ci	} else {
17218c2ecf20Sopenharmony_ci		err = -EINVAL;
17228c2ecf20Sopenharmony_ci		goto drop;
17238c2ecf20Sopenharmony_ci	}
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	index = __le16_to_cpu(hdr->index);
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	if (index != MGMT_INDEX_NONE) {
17288c2ecf20Sopenharmony_ci		hdev = hci_dev_get(index);
17298c2ecf20Sopenharmony_ci		if (!hdev) {
17308c2ecf20Sopenharmony_ci			err = -ENODEV;
17318c2ecf20Sopenharmony_ci			goto drop;
17328c2ecf20Sopenharmony_ci		}
17338c2ecf20Sopenharmony_ci	} else {
17348c2ecf20Sopenharmony_ci		hdev = NULL;
17358c2ecf20Sopenharmony_ci	}
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	hdr->opcode = cpu_to_le16(HCI_MON_USER_LOGGING);
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, HCI_SOCK_TRUSTED, NULL);
17408c2ecf20Sopenharmony_ci	err = len;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	if (hdev)
17438c2ecf20Sopenharmony_ci		hci_dev_put(hdev);
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_cidrop:
17468c2ecf20Sopenharmony_ci	kfree_skb(skb);
17478c2ecf20Sopenharmony_ci	return err;
17488c2ecf20Sopenharmony_ci}
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_cistatic int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
17518c2ecf20Sopenharmony_ci			    size_t len)
17528c2ecf20Sopenharmony_ci{
17538c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
17548c2ecf20Sopenharmony_ci	struct hci_mgmt_chan *chan;
17558c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
17568c2ecf20Sopenharmony_ci	struct sk_buff *skb;
17578c2ecf20Sopenharmony_ci	int err;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	BT_DBG("sock %p sk %p", sock, sk);
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	if (msg->msg_flags & MSG_OOB)
17628c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE|
17658c2ecf20Sopenharmony_ci			       MSG_CMSG_COMPAT))
17668c2ecf20Sopenharmony_ci		return -EINVAL;
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
17698c2ecf20Sopenharmony_ci		return -EINVAL;
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	lock_sock(sk);
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	switch (hci_pi(sk)->channel) {
17748c2ecf20Sopenharmony_ci	case HCI_CHANNEL_RAW:
17758c2ecf20Sopenharmony_ci	case HCI_CHANNEL_USER:
17768c2ecf20Sopenharmony_ci		break;
17778c2ecf20Sopenharmony_ci	case HCI_CHANNEL_MONITOR:
17788c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
17798c2ecf20Sopenharmony_ci		goto done;
17808c2ecf20Sopenharmony_ci	case HCI_CHANNEL_LOGGING:
17818c2ecf20Sopenharmony_ci		err = hci_logging_frame(sk, msg, len);
17828c2ecf20Sopenharmony_ci		goto done;
17838c2ecf20Sopenharmony_ci	default:
17848c2ecf20Sopenharmony_ci		mutex_lock(&mgmt_chan_list_lock);
17858c2ecf20Sopenharmony_ci		chan = __hci_mgmt_chan_find(hci_pi(sk)->channel);
17868c2ecf20Sopenharmony_ci		if (chan)
17878c2ecf20Sopenharmony_ci			err = hci_mgmt_cmd(chan, sk, msg, len);
17888c2ecf20Sopenharmony_ci		else
17898c2ecf20Sopenharmony_ci			err = -EINVAL;
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci		mutex_unlock(&mgmt_chan_list_lock);
17928c2ecf20Sopenharmony_ci		goto done;
17938c2ecf20Sopenharmony_ci	}
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	hdev = hci_hdev_from_sock(sk);
17968c2ecf20Sopenharmony_ci	if (IS_ERR(hdev)) {
17978c2ecf20Sopenharmony_ci		err = PTR_ERR(hdev);
17988c2ecf20Sopenharmony_ci		goto done;
17998c2ecf20Sopenharmony_ci	}
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	if (!test_bit(HCI_UP, &hdev->flags)) {
18028c2ecf20Sopenharmony_ci		err = -ENETDOWN;
18038c2ecf20Sopenharmony_ci		goto done;
18048c2ecf20Sopenharmony_ci	}
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
18078c2ecf20Sopenharmony_ci	if (!skb)
18088c2ecf20Sopenharmony_ci		goto done;
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
18118c2ecf20Sopenharmony_ci		err = -EFAULT;
18128c2ecf20Sopenharmony_ci		goto drop;
18138c2ecf20Sopenharmony_ci	}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	hci_skb_pkt_type(skb) = skb->data[0];
18168c2ecf20Sopenharmony_ci	skb_pull(skb, 1);
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ci	if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
18198c2ecf20Sopenharmony_ci		/* No permission check is needed for user channel
18208c2ecf20Sopenharmony_ci		 * since that gets enforced when binding the socket.
18218c2ecf20Sopenharmony_ci		 *
18228c2ecf20Sopenharmony_ci		 * However check that the packet type is valid.
18238c2ecf20Sopenharmony_ci		 */
18248c2ecf20Sopenharmony_ci		if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT &&
18258c2ecf20Sopenharmony_ci		    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
18268c2ecf20Sopenharmony_ci		    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
18278c2ecf20Sopenharmony_ci		    hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
18288c2ecf20Sopenharmony_ci			err = -EINVAL;
18298c2ecf20Sopenharmony_ci			goto drop;
18308c2ecf20Sopenharmony_ci		}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci		skb_queue_tail(&hdev->raw_q, skb);
18338c2ecf20Sopenharmony_ci		queue_work(hdev->workqueue, &hdev->tx_work);
18348c2ecf20Sopenharmony_ci	} else if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) {
18358c2ecf20Sopenharmony_ci		u16 opcode = get_unaligned_le16(skb->data);
18368c2ecf20Sopenharmony_ci		u16 ogf = hci_opcode_ogf(opcode);
18378c2ecf20Sopenharmony_ci		u16 ocf = hci_opcode_ocf(opcode);
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci		if (((ogf > HCI_SFLT_MAX_OGF) ||
18408c2ecf20Sopenharmony_ci		     !hci_test_bit(ocf & HCI_FLT_OCF_BITS,
18418c2ecf20Sopenharmony_ci				   &hci_sec_filter.ocf_mask[ogf])) &&
18428c2ecf20Sopenharmony_ci		    !capable(CAP_NET_RAW)) {
18438c2ecf20Sopenharmony_ci			err = -EPERM;
18448c2ecf20Sopenharmony_ci			goto drop;
18458c2ecf20Sopenharmony_ci		}
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci		/* Since the opcode has already been extracted here, store
18488c2ecf20Sopenharmony_ci		 * a copy of the value for later use by the drivers.
18498c2ecf20Sopenharmony_ci		 */
18508c2ecf20Sopenharmony_ci		hci_skb_opcode(skb) = opcode;
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci		if (ogf == 0x3f) {
18538c2ecf20Sopenharmony_ci			skb_queue_tail(&hdev->raw_q, skb);
18548c2ecf20Sopenharmony_ci			queue_work(hdev->workqueue, &hdev->tx_work);
18558c2ecf20Sopenharmony_ci		} else {
18568c2ecf20Sopenharmony_ci			/* Stand-alone HCI commands must be flagged as
18578c2ecf20Sopenharmony_ci			 * single-command requests.
18588c2ecf20Sopenharmony_ci			 */
18598c2ecf20Sopenharmony_ci			bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci			skb_queue_tail(&hdev->cmd_q, skb);
18628c2ecf20Sopenharmony_ci			queue_work(hdev->workqueue, &hdev->cmd_work);
18638c2ecf20Sopenharmony_ci		}
18648c2ecf20Sopenharmony_ci	} else {
18658c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_RAW)) {
18668c2ecf20Sopenharmony_ci			err = -EPERM;
18678c2ecf20Sopenharmony_ci			goto drop;
18688c2ecf20Sopenharmony_ci		}
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci		if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
18718c2ecf20Sopenharmony_ci		    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
18728c2ecf20Sopenharmony_ci		    hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
18738c2ecf20Sopenharmony_ci			err = -EINVAL;
18748c2ecf20Sopenharmony_ci			goto drop;
18758c2ecf20Sopenharmony_ci		}
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci		skb_queue_tail(&hdev->raw_q, skb);
18788c2ecf20Sopenharmony_ci		queue_work(hdev->workqueue, &hdev->tx_work);
18798c2ecf20Sopenharmony_ci	}
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	err = len;
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_cidone:
18848c2ecf20Sopenharmony_ci	release_sock(sk);
18858c2ecf20Sopenharmony_ci	return err;
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_cidrop:
18888c2ecf20Sopenharmony_ci	kfree_skb(skb);
18898c2ecf20Sopenharmony_ci	goto done;
18908c2ecf20Sopenharmony_ci}
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_cistatic int hci_sock_setsockopt(struct socket *sock, int level, int optname,
18938c2ecf20Sopenharmony_ci			       sockptr_t optval, unsigned int len)
18948c2ecf20Sopenharmony_ci{
18958c2ecf20Sopenharmony_ci	struct hci_ufilter uf = { .opcode = 0 };
18968c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
18978c2ecf20Sopenharmony_ci	int err = 0, opt = 0;
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	BT_DBG("sk %p, opt %d", sk, optname);
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	if (level != SOL_HCI)
19028c2ecf20Sopenharmony_ci		return -ENOPROTOOPT;
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	lock_sock(sk);
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
19078c2ecf20Sopenharmony_ci		err = -EBADFD;
19088c2ecf20Sopenharmony_ci		goto done;
19098c2ecf20Sopenharmony_ci	}
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	switch (optname) {
19128c2ecf20Sopenharmony_ci	case HCI_DATA_DIR:
19138c2ecf20Sopenharmony_ci		if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
19148c2ecf20Sopenharmony_ci			err = -EFAULT;
19158c2ecf20Sopenharmony_ci			break;
19168c2ecf20Sopenharmony_ci		}
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci		if (opt)
19198c2ecf20Sopenharmony_ci			hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
19208c2ecf20Sopenharmony_ci		else
19218c2ecf20Sopenharmony_ci			hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
19228c2ecf20Sopenharmony_ci		break;
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	case HCI_TIME_STAMP:
19258c2ecf20Sopenharmony_ci		if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
19268c2ecf20Sopenharmony_ci			err = -EFAULT;
19278c2ecf20Sopenharmony_ci			break;
19288c2ecf20Sopenharmony_ci		}
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci		if (opt)
19318c2ecf20Sopenharmony_ci			hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
19328c2ecf20Sopenharmony_ci		else
19338c2ecf20Sopenharmony_ci			hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
19348c2ecf20Sopenharmony_ci		break;
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	case HCI_FILTER:
19378c2ecf20Sopenharmony_ci		{
19388c2ecf20Sopenharmony_ci			struct hci_filter *f = &hci_pi(sk)->filter;
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci			uf.type_mask = f->type_mask;
19418c2ecf20Sopenharmony_ci			uf.opcode    = f->opcode;
19428c2ecf20Sopenharmony_ci			uf.event_mask[0] = *((u32 *) f->event_mask + 0);
19438c2ecf20Sopenharmony_ci			uf.event_mask[1] = *((u32 *) f->event_mask + 1);
19448c2ecf20Sopenharmony_ci		}
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci		len = min_t(unsigned int, len, sizeof(uf));
19478c2ecf20Sopenharmony_ci		if (copy_from_sockptr(&uf, optval, len)) {
19488c2ecf20Sopenharmony_ci			err = -EFAULT;
19498c2ecf20Sopenharmony_ci			break;
19508c2ecf20Sopenharmony_ci		}
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci		if (!capable(CAP_NET_RAW)) {
19538c2ecf20Sopenharmony_ci			uf.type_mask &= hci_sec_filter.type_mask;
19548c2ecf20Sopenharmony_ci			uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
19558c2ecf20Sopenharmony_ci			uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
19568c2ecf20Sopenharmony_ci		}
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci		{
19598c2ecf20Sopenharmony_ci			struct hci_filter *f = &hci_pi(sk)->filter;
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci			f->type_mask = uf.type_mask;
19628c2ecf20Sopenharmony_ci			f->opcode    = uf.opcode;
19638c2ecf20Sopenharmony_ci			*((u32 *) f->event_mask + 0) = uf.event_mask[0];
19648c2ecf20Sopenharmony_ci			*((u32 *) f->event_mask + 1) = uf.event_mask[1];
19658c2ecf20Sopenharmony_ci		}
19668c2ecf20Sopenharmony_ci		break;
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	default:
19698c2ecf20Sopenharmony_ci		err = -ENOPROTOOPT;
19708c2ecf20Sopenharmony_ci		break;
19718c2ecf20Sopenharmony_ci	}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_cidone:
19748c2ecf20Sopenharmony_ci	release_sock(sk);
19758c2ecf20Sopenharmony_ci	return err;
19768c2ecf20Sopenharmony_ci}
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_cistatic int hci_sock_getsockopt(struct socket *sock, int level, int optname,
19798c2ecf20Sopenharmony_ci			       char __user *optval, int __user *optlen)
19808c2ecf20Sopenharmony_ci{
19818c2ecf20Sopenharmony_ci	struct hci_ufilter uf;
19828c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
19838c2ecf20Sopenharmony_ci	int len, opt, err = 0;
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	BT_DBG("sk %p, opt %d", sk, optname);
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci	if (level != SOL_HCI)
19888c2ecf20Sopenharmony_ci		return -ENOPROTOOPT;
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci	if (get_user(len, optlen))
19918c2ecf20Sopenharmony_ci		return -EFAULT;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	lock_sock(sk);
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
19968c2ecf20Sopenharmony_ci		err = -EBADFD;
19978c2ecf20Sopenharmony_ci		goto done;
19988c2ecf20Sopenharmony_ci	}
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	switch (optname) {
20018c2ecf20Sopenharmony_ci	case HCI_DATA_DIR:
20028c2ecf20Sopenharmony_ci		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
20038c2ecf20Sopenharmony_ci			opt = 1;
20048c2ecf20Sopenharmony_ci		else
20058c2ecf20Sopenharmony_ci			opt = 0;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci		if (put_user(opt, optval))
20088c2ecf20Sopenharmony_ci			err = -EFAULT;
20098c2ecf20Sopenharmony_ci		break;
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci	case HCI_TIME_STAMP:
20128c2ecf20Sopenharmony_ci		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
20138c2ecf20Sopenharmony_ci			opt = 1;
20148c2ecf20Sopenharmony_ci		else
20158c2ecf20Sopenharmony_ci			opt = 0;
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci		if (put_user(opt, optval))
20188c2ecf20Sopenharmony_ci			err = -EFAULT;
20198c2ecf20Sopenharmony_ci		break;
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ci	case HCI_FILTER:
20228c2ecf20Sopenharmony_ci		{
20238c2ecf20Sopenharmony_ci			struct hci_filter *f = &hci_pi(sk)->filter;
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci			memset(&uf, 0, sizeof(uf));
20268c2ecf20Sopenharmony_ci			uf.type_mask = f->type_mask;
20278c2ecf20Sopenharmony_ci			uf.opcode    = f->opcode;
20288c2ecf20Sopenharmony_ci			uf.event_mask[0] = *((u32 *) f->event_mask + 0);
20298c2ecf20Sopenharmony_ci			uf.event_mask[1] = *((u32 *) f->event_mask + 1);
20308c2ecf20Sopenharmony_ci		}
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci		len = min_t(unsigned int, len, sizeof(uf));
20338c2ecf20Sopenharmony_ci		if (copy_to_user(optval, &uf, len))
20348c2ecf20Sopenharmony_ci			err = -EFAULT;
20358c2ecf20Sopenharmony_ci		break;
20368c2ecf20Sopenharmony_ci
20378c2ecf20Sopenharmony_ci	default:
20388c2ecf20Sopenharmony_ci		err = -ENOPROTOOPT;
20398c2ecf20Sopenharmony_ci		break;
20408c2ecf20Sopenharmony_ci	}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_cidone:
20438c2ecf20Sopenharmony_ci	release_sock(sk);
20448c2ecf20Sopenharmony_ci	return err;
20458c2ecf20Sopenharmony_ci}
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_cistatic void hci_sock_destruct(struct sock *sk)
20488c2ecf20Sopenharmony_ci{
20498c2ecf20Sopenharmony_ci	skb_queue_purge(&sk->sk_receive_queue);
20508c2ecf20Sopenharmony_ci	skb_queue_purge(&sk->sk_write_queue);
20518c2ecf20Sopenharmony_ci}
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_cistatic const struct proto_ops hci_sock_ops = {
20548c2ecf20Sopenharmony_ci	.family		= PF_BLUETOOTH,
20558c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
20568c2ecf20Sopenharmony_ci	.release	= hci_sock_release,
20578c2ecf20Sopenharmony_ci	.bind		= hci_sock_bind,
20588c2ecf20Sopenharmony_ci	.getname	= hci_sock_getname,
20598c2ecf20Sopenharmony_ci	.sendmsg	= hci_sock_sendmsg,
20608c2ecf20Sopenharmony_ci	.recvmsg	= hci_sock_recvmsg,
20618c2ecf20Sopenharmony_ci	.ioctl		= hci_sock_ioctl,
20628c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
20638c2ecf20Sopenharmony_ci	.compat_ioctl	= hci_sock_compat_ioctl,
20648c2ecf20Sopenharmony_ci#endif
20658c2ecf20Sopenharmony_ci	.poll		= datagram_poll,
20668c2ecf20Sopenharmony_ci	.listen		= sock_no_listen,
20678c2ecf20Sopenharmony_ci	.shutdown	= sock_no_shutdown,
20688c2ecf20Sopenharmony_ci	.setsockopt	= hci_sock_setsockopt,
20698c2ecf20Sopenharmony_ci	.getsockopt	= hci_sock_getsockopt,
20708c2ecf20Sopenharmony_ci	.connect	= sock_no_connect,
20718c2ecf20Sopenharmony_ci	.socketpair	= sock_no_socketpair,
20728c2ecf20Sopenharmony_ci	.accept		= sock_no_accept,
20738c2ecf20Sopenharmony_ci	.mmap		= sock_no_mmap
20748c2ecf20Sopenharmony_ci};
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_cistatic struct proto hci_sk_proto = {
20778c2ecf20Sopenharmony_ci	.name		= "HCI",
20788c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
20798c2ecf20Sopenharmony_ci	.obj_size	= sizeof(struct hci_pinfo)
20808c2ecf20Sopenharmony_ci};
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_cistatic int hci_sock_create(struct net *net, struct socket *sock, int protocol,
20838c2ecf20Sopenharmony_ci			   int kern)
20848c2ecf20Sopenharmony_ci{
20858c2ecf20Sopenharmony_ci	struct sock *sk;
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	BT_DBG("sock %p", sock);
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci	if (sock->type != SOCK_RAW)
20908c2ecf20Sopenharmony_ci		return -ESOCKTNOSUPPORT;
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	sock->ops = &hci_sock_ops;
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci	sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern);
20958c2ecf20Sopenharmony_ci	if (!sk)
20968c2ecf20Sopenharmony_ci		return -ENOMEM;
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci	sock_init_data(sock, sk);
20998c2ecf20Sopenharmony_ci
21008c2ecf20Sopenharmony_ci	sock_reset_flag(sk, SOCK_ZAPPED);
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci	sk->sk_protocol = protocol;
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_ci	sock->state = SS_UNCONNECTED;
21058c2ecf20Sopenharmony_ci	sk->sk_state = BT_OPEN;
21068c2ecf20Sopenharmony_ci	sk->sk_destruct = hci_sock_destruct;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	bt_sock_link(&hci_sk_list, sk);
21098c2ecf20Sopenharmony_ci	return 0;
21108c2ecf20Sopenharmony_ci}
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_cistatic const struct net_proto_family hci_sock_family_ops = {
21138c2ecf20Sopenharmony_ci	.family	= PF_BLUETOOTH,
21148c2ecf20Sopenharmony_ci	.owner	= THIS_MODULE,
21158c2ecf20Sopenharmony_ci	.create	= hci_sock_create,
21168c2ecf20Sopenharmony_ci};
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ciint __init hci_sock_init(void)
21198c2ecf20Sopenharmony_ci{
21208c2ecf20Sopenharmony_ci	int err;
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr));
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci	err = proto_register(&hci_sk_proto, 0);
21258c2ecf20Sopenharmony_ci	if (err < 0)
21268c2ecf20Sopenharmony_ci		return err;
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
21298c2ecf20Sopenharmony_ci	if (err < 0) {
21308c2ecf20Sopenharmony_ci		BT_ERR("HCI socket registration failed");
21318c2ecf20Sopenharmony_ci		goto error;
21328c2ecf20Sopenharmony_ci	}
21338c2ecf20Sopenharmony_ci
21348c2ecf20Sopenharmony_ci	err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL);
21358c2ecf20Sopenharmony_ci	if (err < 0) {
21368c2ecf20Sopenharmony_ci		BT_ERR("Failed to create HCI proc file");
21378c2ecf20Sopenharmony_ci		bt_sock_unregister(BTPROTO_HCI);
21388c2ecf20Sopenharmony_ci		goto error;
21398c2ecf20Sopenharmony_ci	}
21408c2ecf20Sopenharmony_ci
21418c2ecf20Sopenharmony_ci	BT_INFO("HCI socket layer initialized");
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	return 0;
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_cierror:
21468c2ecf20Sopenharmony_ci	proto_unregister(&hci_sk_proto);
21478c2ecf20Sopenharmony_ci	return err;
21488c2ecf20Sopenharmony_ci}
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_civoid hci_sock_cleanup(void)
21518c2ecf20Sopenharmony_ci{
21528c2ecf20Sopenharmony_ci	bt_procfs_cleanup(&init_net, "hci");
21538c2ecf20Sopenharmony_ci	bt_sock_unregister(BTPROTO_HCI);
21548c2ecf20Sopenharmony_ci	proto_unregister(&hci_sk_proto);
21558c2ecf20Sopenharmony_ci}
2156