⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hci_sock.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	BT_DBG("sock %p, sk %p", sock, sk);	if (flags & (MSG_OOB))		return -EOPNOTSUPP;	if (sk->sk_state == BT_CLOSED)		return 0;	if (!(skb = skb_recv_datagram(sk, flags, noblock, &err)))		return err;	msg->msg_namelen = 0;	copied = skb->len;	if (len < copied) {		msg->msg_flags |= MSG_TRUNC;		copied = len;	}	skb_reset_transport_header(skb);	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);	hci_sock_cmsg(sk, msg, skb);	skb_free_datagram(sk, skb);	return err ? : copied;}static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,			    struct msghdr *msg, size_t len){	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 || len > HCI_MAX_FRAME_SIZE)		return -EINVAL;	lock_sock(sk);	if (!(hdev = hci_pi(sk)->hdev)) {		err = -EBADFD;		goto done;	}	if (!(skb = bt_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;	}	bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);	skb_pull(skb, 1);	skb->dev = (void *) hdev;	if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {		u16 opcode = __le16_to_cpu(get_unaligned((__le16 *) skb->data));		u16 ogf = hci_opcode_ogf(opcode);		u16 ocf = hci_opcode_ocf(opcode);		if (((ogf > HCI_SFLT_MAX_OGF) ||				!hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&					!capable(CAP_NET_RAW)) {			err = -EPERM;			goto drop;		}		if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {			skb_queue_tail(&hdev->raw_q, skb);			hci_sched_tx(hdev);		} else {			skb_queue_tail(&hdev->cmd_q, skb);			hci_sched_cmd(hdev);		}	} else {		if (!capable(CAP_NET_RAW)) {			err = -EPERM;			goto drop;		}		skb_queue_tail(&hdev->raw_q, skb);		hci_sched_tx(hdev);	}	err = len;done:	release_sock(sk);	return err;drop:	kfree_skb(skb);	goto done;}static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len){	struct hci_ufilter uf = { .opcode = 0 };	struct sock *sk = sock->sk;	int err = 0, opt = 0;	BT_DBG("sk %p, opt %d", sk, optname);	lock_sock(sk);	switch (optname) {	case HCI_DATA_DIR:		if (get_user(opt, (int __user *)optval)) {			err = -EFAULT;			break;		}		if (opt)			hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;		else			hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;		break;	case HCI_TIME_STAMP:		if (get_user(opt, (int __user *)optval)) {			err = -EFAULT;			break;		}		if (opt)			hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;		else			hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;		break;	case HCI_FILTER:		{			struct hci_filter *f = &hci_pi(sk)->filter;			uf.type_mask = f->type_mask;			uf.opcode    = f->opcode;			uf.event_mask[0] = *((u32 *) f->event_mask + 0);			uf.event_mask[1] = *((u32 *) f->event_mask + 1);		}		len = min_t(unsigned int, len, sizeof(uf));		if (copy_from_user(&uf, optval, len)) {			err = -EFAULT;			break;		}		if (!capable(CAP_NET_RAW)) {			uf.type_mask &= hci_sec_filter.type_mask;			uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);			uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);		}		{			struct hci_filter *f = &hci_pi(sk)->filter;			f->type_mask = uf.type_mask;			f->opcode    = uf.opcode;			*((u32 *) f->event_mask + 0) = uf.event_mask[0];			*((u32 *) f->event_mask + 1) = uf.event_mask[1];		}		break;	default:		err = -ENOPROTOOPT;		break;	}	release_sock(sk);	return err;}static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen){	struct hci_ufilter uf;	struct sock *sk = sock->sk;	int len, opt;	if (get_user(len, optlen))		return -EFAULT;	switch (optname) {	case HCI_DATA_DIR:		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)			opt = 1;		else			opt = 0;		if (put_user(opt, optval))			return -EFAULT;		break;	case HCI_TIME_STAMP:		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)			opt = 1;		else			opt = 0;		if (put_user(opt, optval))			return -EFAULT;		break;	case HCI_FILTER:		{			struct hci_filter *f = &hci_pi(sk)->filter;			uf.type_mask = f->type_mask;			uf.opcode    = f->opcode;			uf.event_mask[0] = *((u32 *) f->event_mask + 0);			uf.event_mask[1] = *((u32 *) f->event_mask + 1);		}		len = min_t(unsigned int, len, sizeof(uf));		if (copy_to_user(optval, &uf, len))			return -EFAULT;		break;	default:		return -ENOPROTOOPT;		break;	}	return 0;}static const struct proto_ops hci_sock_ops = {	.family		= PF_BLUETOOTH,	.owner		= THIS_MODULE,	.release	= hci_sock_release,	.bind		= hci_sock_bind,	.getname	= hci_sock_getname,	.sendmsg	= hci_sock_sendmsg,	.recvmsg	= hci_sock_recvmsg,	.ioctl		= hci_sock_ioctl,	.poll		= datagram_poll,	.listen		= sock_no_listen,	.shutdown	= sock_no_shutdown,	.setsockopt	= hci_sock_setsockopt,	.getsockopt	= hci_sock_getsockopt,	.connect	= sock_no_connect,	.socketpair	= sock_no_socketpair,	.accept		= sock_no_accept,	.mmap		= sock_no_mmap};static struct proto hci_sk_proto = {	.name		= "HCI",	.owner		= THIS_MODULE,	.obj_size	= sizeof(struct hci_pinfo)};static int hci_sock_create(struct net *net, struct socket *sock, int protocol){	struct sock *sk;	BT_DBG("sock %p", sock);	if (sock->type != SOCK_RAW)		return -ESOCKTNOSUPPORT;	sock->ops = &hci_sock_ops;	sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);	if (!sk)		return -ENOMEM;	sock_init_data(sock, sk);	sock_reset_flag(sk, SOCK_ZAPPED);	sk->sk_protocol = protocol;	sock->state = SS_UNCONNECTED;	sk->sk_state = BT_OPEN;	bt_sock_link(&hci_sk_list, sk);	return 0;}static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr){	struct hci_dev *hdev = (struct hci_dev *) ptr;	struct hci_ev_si_device ev;	BT_DBG("hdev %s event %ld", hdev->name, event);	/* Send event to sockets */	ev.event  = event;	ev.dev_id = hdev->id;	hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);	if (event == HCI_DEV_UNREG) {		struct sock *sk;		struct hlist_node *node;		/* Detach sockets from device */		read_lock(&hci_sk_list.lock);		sk_for_each(sk, node, &hci_sk_list.head) {			local_bh_disable();			bh_lock_sock_nested(sk);			if (hci_pi(sk)->hdev == hdev) {				hci_pi(sk)->hdev = NULL;				sk->sk_err = EPIPE;				sk->sk_state = BT_OPEN;				sk->sk_state_change(sk);				hci_dev_put(hdev);			}			bh_unlock_sock(sk);			local_bh_enable();		}		read_unlock(&hci_sk_list.lock);	}	return NOTIFY_DONE;}static struct net_proto_family hci_sock_family_ops = {	.family	= PF_BLUETOOTH,	.owner	= THIS_MODULE,	.create	= hci_sock_create,};static struct notifier_block hci_sock_nblock = {	.notifier_call = hci_sock_dev_event};int __init hci_sock_init(void){	int err;	err = proto_register(&hci_sk_proto, 0);	if (err < 0)		return err;	err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);	if (err < 0)		goto error;	hci_register_notifier(&hci_sock_nblock);	BT_INFO("HCI socket layer initialized");	return 0;error:	BT_ERR("HCI socket registration failed");	proto_unregister(&hci_sk_proto);	return err;}int __exit hci_sock_cleanup(void){	if (bt_sock_unregister(BTPROTO_HCI) < 0)		BT_ERR("HCI socket unregistration failed");	hci_unregister_notifier(&hci_sock_nblock);	proto_unregister(&hci_sk_proto);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -