Ejemplo n.º 1
0
static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len,
                            struct scm_cookie *scm)
{
	struct sock *sk = sock->sk;
	struct hci_dev *hdev = hci_pi(sk)->hdev;
	struct sk_buff *skb;
	int err;

	DBG("sock %p sk %p", sock, sk);

	if (msg->msg_flags & MSG_OOB)
		return -EOPNOTSUPP;

	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
		return -EINVAL;

	if (!hdev)
		return -EBADFD;

	if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
		return err;

	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
		kfree_skb(skb);
		return -EFAULT;
	}

	skb->dev = (void *) hdev;
	skb->pkt_type = *((unsigned char *) skb->data);
	skb_pull(skb, 1);

	/* Send frame to HCI core */
	hci_send_raw(skb);

	return len;
}
Ejemplo n.º 2
0
static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len,
                            struct scm_cookie *scm)
{
	struct sock *sk = sock->sk;
	struct hci_dev *hdev;
	struct sk_buff *skb;
	int err;

	BT_DBG("sock %p sk %p", sock, sk);

	if (msg->msg_flags & MSG_OOB)
		return -EOPNOTSUPP;

	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
		return -EINVAL;

	if (len < 4)
		return -EINVAL;
	
	lock_sock(sk);

	if (!(hdev = hci_pi(sk)->hdev)) {
		err = -EBADFD;
		goto done;
	}

	if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
		goto done;

	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
		err = -EFAULT;
		goto drop;
	}

	skb->pkt_type = *((unsigned char *) skb->data);
	skb_pull(skb, 1);

	if (!capable(CAP_NET_RAW)) {
		err = -EPERM;

		if (skb->pkt_type == HCI_COMMAND_PKT) {
			__u16 opcode = __le16_to_cpu(*(__u16 *)skb->data);
			__u16 ogf = cmd_opcode_ogf(opcode) - 1;
			__u16 ocf = cmd_opcode_ocf(opcode) & HCI_FLT_OCF_BITS;

			if (ogf > HCI_SFLT_MAX_OGF ||
					!hci_test_bit(ocf, &hci_sec_filter.ocf_mask[ogf]))
				goto drop;
		} else
			goto drop;
	}
		
	/* Send frame to HCI core */
	skb->dev = (void *) hdev;
	hci_send_raw(skb);
	err = len;

done:
	release_sock(sk);
	return err;

drop:
	kfree_skb(skb);
	goto done;
}