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

📄 af_rxrpc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	int ret;	_enter(",{%d},,%zu", rx->sk.sk_state, len);	if (m->msg_flags & MSG_OOB)		return -EOPNOTSUPP;	if (m->msg_name) {		ret = rxrpc_validate_address(rx, m->msg_name, m->msg_namelen);		if (ret < 0) {			_leave(" = %d [bad addr]", ret);			return ret;		}	}	trans = NULL;	lock_sock(&rx->sk);	if (m->msg_name) {		ret = -EISCONN;		trans = rxrpc_name_to_transport(sock, m->msg_name,						m->msg_namelen, 0, GFP_KERNEL);		if (IS_ERR(trans)) {			ret = PTR_ERR(trans);			trans = NULL;			goto out;		}	} else {		trans = rx->trans;		if (trans)			atomic_inc(&trans->usage);	}	switch (rx->sk.sk_state) {	case RXRPC_SERVER_LISTENING:		if (!m->msg_name) {			ret = rxrpc_server_sendmsg(iocb, rx, m, len);			break;		}	case RXRPC_SERVER_BOUND:	case RXRPC_CLIENT_BOUND:		if (!m->msg_name) {			ret = -ENOTCONN;			break;		}	case RXRPC_CLIENT_CONNECTED:		ret = rxrpc_client_sendmsg(iocb, rx, trans, m, len);		break;	default:		ret = -ENOTCONN;		break;	}out:	release_sock(&rx->sk);	if (trans)		rxrpc_put_transport(trans);	_leave(" = %d", ret);	return ret;}/* * set RxRPC socket options */static int rxrpc_setsockopt(struct socket *sock, int level, int optname,			    char __user *optval, int optlen){	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);	unsigned min_sec_level;	int ret;	_enter(",%d,%d,,%d", level, optname, optlen);	lock_sock(&rx->sk);	ret = -EOPNOTSUPP;	if (level == SOL_RXRPC) {		switch (optname) {		case RXRPC_EXCLUSIVE_CONNECTION:			ret = -EINVAL;			if (optlen != 0)				goto error;			ret = -EISCONN;			if (rx->sk.sk_state != RXRPC_UNCONNECTED)				goto error;			set_bit(RXRPC_SOCK_EXCLUSIVE_CONN, &rx->flags);			goto success;		case RXRPC_SECURITY_KEY:			ret = -EINVAL;			if (rx->key)				goto error;			ret = -EISCONN;			if (rx->sk.sk_state != RXRPC_UNCONNECTED)				goto error;			ret = rxrpc_request_key(rx, optval, optlen);			goto error;		case RXRPC_SECURITY_KEYRING:			ret = -EINVAL;			if (rx->key)				goto error;			ret = -EISCONN;			if (rx->sk.sk_state != RXRPC_UNCONNECTED)				goto error;			ret = rxrpc_server_keyring(rx, optval, optlen);			goto error;		case RXRPC_MIN_SECURITY_LEVEL:			ret = -EINVAL;			if (optlen != sizeof(unsigned))				goto error;			ret = -EISCONN;			if (rx->sk.sk_state != RXRPC_UNCONNECTED)				goto error;			ret = get_user(min_sec_level,				       (unsigned __user *) optval);			if (ret < 0)				goto error;			ret = -EINVAL;			if (min_sec_level > RXRPC_SECURITY_MAX)				goto error;			rx->min_sec_level = min_sec_level;			goto success;		default:			break;		}	}success:	ret = 0;error:	release_sock(&rx->sk);	return ret;}/* * permit an RxRPC socket to be polled */static unsigned int rxrpc_poll(struct file *file, struct socket *sock,			       poll_table *wait){	unsigned int mask;	struct sock *sk = sock->sk;	poll_wait(file, sk->sk_sleep, wait);	mask = 0;	/* the socket is readable if there are any messages waiting on the Rx	 * queue */	if (!skb_queue_empty(&sk->sk_receive_queue))		mask |= POLLIN | POLLRDNORM;	/* the socket is writable if there is space to add new data to the	 * socket; there is no guarantee that any particular call in progress	 * on the socket may have space in the Tx ACK window */	if (rxrpc_writable(sk))		mask |= POLLOUT | POLLWRNORM;	return mask;}/* * create an RxRPC socket */static int rxrpc_create(struct net *net, struct socket *sock, int protocol){	struct rxrpc_sock *rx;	struct sock *sk;	_enter("%p,%d", sock, protocol);	if (net != &init_net)		return -EAFNOSUPPORT;	/* we support transport protocol UDP only */	if (protocol != PF_INET)		return -EPROTONOSUPPORT;	if (sock->type != SOCK_DGRAM)		return -ESOCKTNOSUPPORT;	sock->ops = &rxrpc_rpc_ops;	sock->state = SS_UNCONNECTED;	sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto);	if (!sk)		return -ENOMEM;	sock_init_data(sock, sk);	sk->sk_state		= RXRPC_UNCONNECTED;	sk->sk_write_space	= rxrpc_write_space;	sk->sk_max_ack_backlog	= sysctl_rxrpc_max_qlen;	sk->sk_destruct		= rxrpc_sock_destructor;	rx = rxrpc_sk(sk);	rx->proto = protocol;	rx->calls = RB_ROOT;	INIT_LIST_HEAD(&rx->listen_link);	INIT_LIST_HEAD(&rx->secureq);	INIT_LIST_HEAD(&rx->acceptq);	rwlock_init(&rx->call_lock);	memset(&rx->srx, 0, sizeof(rx->srx));	_leave(" = 0 [%p]", rx);	return 0;}/* * RxRPC socket destructor */static void rxrpc_sock_destructor(struct sock *sk){	_enter("%p", sk);	rxrpc_purge_queue(&sk->sk_receive_queue);	BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));	BUG_TRAP(sk_unhashed(sk));	BUG_TRAP(!sk->sk_socket);	if (!sock_flag(sk, SOCK_DEAD)) {		printk("Attempt to release alive rxrpc socket: %p\n", sk);		return;	}}/* * release an RxRPC socket */static int rxrpc_release_sock(struct sock *sk){	struct rxrpc_sock *rx = rxrpc_sk(sk);	_enter("%p{%d,%d}", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));	/* declare the socket closed for business */	sock_orphan(sk);	sk->sk_shutdown = SHUTDOWN_MASK;	spin_lock_bh(&sk->sk_receive_queue.lock);	sk->sk_state = RXRPC_CLOSE;	spin_unlock_bh(&sk->sk_receive_queue.lock);	ASSERTCMP(rx->listen_link.next, !=, LIST_POISON1);	if (!list_empty(&rx->listen_link)) {		write_lock_bh(&rx->local->services_lock);		list_del(&rx->listen_link);		write_unlock_bh(&rx->local->services_lock);	}	/* try to flush out this socket */	rxrpc_release_calls_on_socket(rx);	flush_workqueue(rxrpc_workqueue);	rxrpc_purge_queue(&sk->sk_receive_queue);	if (rx->conn) {		rxrpc_put_connection(rx->conn);		rx->conn = NULL;	}	if (rx->bundle) {		rxrpc_put_bundle(rx->trans, rx->bundle);		rx->bundle = NULL;	}	if (rx->trans) {		rxrpc_put_transport(rx->trans);		rx->trans = NULL;	}	if (rx->local) {		rxrpc_put_local(rx->local);		rx->local = NULL;	}	key_put(rx->key);	rx->key = NULL;	key_put(rx->securities);	rx->securities = NULL;	sock_put(sk);	_leave(" = 0");	return 0;}/* * release an RxRPC BSD socket on close() or equivalent */static int rxrpc_release(struct socket *sock){	struct sock *sk = sock->sk;	_enter("%p{%p}", sock, sk);	if (!sk)		return 0;	sock->sk = NULL;	return rxrpc_release_sock(sk);}/* * RxRPC network protocol */static const struct proto_ops rxrpc_rpc_ops = {	.family		= PF_UNIX,	.owner		= THIS_MODULE,	.release	= rxrpc_release,	.bind		= rxrpc_bind,	.connect	= rxrpc_connect,	.socketpair	= sock_no_socketpair,	.accept		= sock_no_accept,	.getname	= sock_no_getname,	.poll		= rxrpc_poll,	.ioctl		= sock_no_ioctl,	.listen		= rxrpc_listen,	.shutdown	= sock_no_shutdown,	.setsockopt	= rxrpc_setsockopt,	.getsockopt	= sock_no_getsockopt,	.sendmsg	= rxrpc_sendmsg,	.recvmsg	= rxrpc_recvmsg,	.mmap		= sock_no_mmap,	.sendpage	= sock_no_sendpage,};static struct proto rxrpc_proto = {	.name		= "RXRPC",	.owner		= THIS_MODULE,	.obj_size	= sizeof(struct rxrpc_sock),	.max_header	= sizeof(struct rxrpc_header),};static struct net_proto_family rxrpc_family_ops = {	.family	= PF_RXRPC,	.create = rxrpc_create,	.owner	= THIS_MODULE,};/* * initialise and register the RxRPC protocol */static int __init af_rxrpc_init(void){	struct sk_buff *dummy_skb;	int ret = -1;	BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof(dummy_skb->cb));	rxrpc_epoch = htonl(get_seconds());	ret = -ENOMEM;	rxrpc_call_jar = kmem_cache_create(		"rxrpc_call_jar", sizeof(struct rxrpc_call), 0,		SLAB_HWCACHE_ALIGN, NULL);	if (!rxrpc_call_jar) {		printk(KERN_NOTICE "RxRPC: Failed to allocate call jar\n");		goto error_call_jar;	}	rxrpc_workqueue = create_workqueue("krxrpcd");	if (!rxrpc_workqueue) {		printk(KERN_NOTICE "RxRPC: Failed to allocate work queue\n");		goto error_work_queue;	}	ret = proto_register(&rxrpc_proto, 1);	if (ret < 0) {		printk(KERN_CRIT "RxRPC: Cannot register protocol\n");		goto error_proto;	}	ret = sock_register(&rxrpc_family_ops);	if (ret < 0) {		printk(KERN_CRIT "RxRPC: Cannot register socket family\n");		goto error_sock;	}	ret = register_key_type(&key_type_rxrpc);	if (ret < 0) {		printk(KERN_CRIT "RxRPC: Cannot register client key type\n");		goto error_key_type;	}	ret = register_key_type(&key_type_rxrpc_s);	if (ret < 0) {		printk(KERN_CRIT "RxRPC: Cannot register server key type\n");		goto error_key_type_s;	}#ifdef CONFIG_PROC_FS	proc_net_fops_create(&init_net, "rxrpc_calls", 0, &rxrpc_call_seq_fops);	proc_net_fops_create(&init_net, "rxrpc_conns", 0, &rxrpc_connection_seq_fops);#endif	return 0;error_key_type_s:	unregister_key_type(&key_type_rxrpc);error_key_type:	sock_unregister(PF_RXRPC);error_sock:	proto_unregister(&rxrpc_proto);error_proto:	destroy_workqueue(rxrpc_workqueue);error_work_queue:	kmem_cache_destroy(rxrpc_call_jar);error_call_jar:	return ret;}/* * unregister the RxRPC protocol */static void __exit af_rxrpc_exit(void){	_enter("");	unregister_key_type(&key_type_rxrpc_s);	unregister_key_type(&key_type_rxrpc);	sock_unregister(PF_RXRPC);	proto_unregister(&rxrpc_proto);	rxrpc_destroy_all_calls();	rxrpc_destroy_all_connections();	rxrpc_destroy_all_transports();	rxrpc_destroy_all_peers();	rxrpc_destroy_all_locals();	ASSERTCMP(atomic_read(&rxrpc_n_skbs), ==, 0);	_debug("flush scheduled work");	flush_workqueue(rxrpc_workqueue);	proc_net_remove(&init_net, "rxrpc_conns");	proc_net_remove(&init_net, "rxrpc_calls");	destroy_workqueue(rxrpc_workqueue);	kmem_cache_destroy(rxrpc_call_jar);	_leave("");}module_init(af_rxrpc_init);module_exit(af_rxrpc_exit);

⌨️ 快捷键说明

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