diff options
Diffstat (limited to 'net/bluetooth/hci_sock.c')
| -rw-r--r-- | net/bluetooth/hci_sock.c | 39 | 
1 files changed, 33 insertions, 6 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index b3753bad2a5..207be7abda9 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -49,6 +49,8 @@  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h> +static int enable_mgmt; +  /* ----- HCI socket interface ----- */  static inline int hci_test_bit(int nr, void *addr) @@ -353,25 +355,35 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a  static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)  { -	struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; +	struct sockaddr_hci haddr;  	struct sock *sk = sock->sk;  	struct hci_dev *hdev = NULL; -	int err = 0; +	int len, err = 0;  	BT_DBG("sock %p sk %p", sock, sk); -	if (!haddr || haddr->hci_family != AF_BLUETOOTH) +	if (!addr) +		return -EINVAL; + +	memset(&haddr, 0, sizeof(haddr)); +	len = min_t(unsigned int, sizeof(haddr), addr_len); +	memcpy(&haddr, addr, len); + +	if (haddr.hci_family != AF_BLUETOOTH) +		return -EINVAL; + +	if (haddr.hci_channel != HCI_CHANNEL_RAW && !enable_mgmt)  		return -EINVAL;  	lock_sock(sk); -	if (hci_pi(sk)->hdev) { +	if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) {  		err = -EALREADY;  		goto done;  	} -	if (haddr->hci_dev != HCI_DEV_NONE) { -		hdev = hci_dev_get(haddr->hci_dev); +	if (haddr.hci_dev != HCI_DEV_NONE) { +		hdev = hci_dev_get(haddr.hci_dev);  		if (!hdev) {  			err = -ENODEV;  			goto done; @@ -380,6 +392,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le  		atomic_inc(&hdev->promisc);  	} +	hci_pi(sk)->channel = haddr.hci_channel;  	hci_pi(sk)->hdev = hdev;  	sk->sk_state = BT_BOUND; @@ -502,6 +515,17 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,  	lock_sock(sk); +	switch (hci_pi(sk)->channel) { +	case HCI_CHANNEL_RAW: +		break; +	case HCI_CHANNEL_CONTROL: +		err = mgmt_control(sk, msg, len); +		goto done; +	default: +		err = -EINVAL; +		goto done; +	} +  	hdev = hci_pi(sk)->hdev;  	if (!hdev) {  		err = -EBADFD; @@ -831,3 +855,6 @@ void __exit hci_sock_cleanup(void)  	proto_unregister(&hci_sk_proto);  } + +module_param(enable_mgmt, bool, 0644); +MODULE_PARM_DESC(enable_mgmt, "Enable Management interface");  |