Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

af_vsock: rest of SEQPACKET support

Add socket ops for SEQPACKET type and .seqpacket_allow() callback
to query transports if they support SEQPACKET. Also split path
for data check for STREAM and SEQPACKET branches.

Signed-off-by: Arseny Krasnov <arseny.krasnov@kaspersky.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arseny Krasnov and committed by
David S. Miller
0798e78b fbe70c48

+48 -2
+2
include/net/af_vsock.h
··· 140 140 int flags); 141 141 int (*seqpacket_enqueue)(struct vsock_sock *vsk, struct msghdr *msg, 142 142 size_t len); 143 + bool (*seqpacket_allow)(u32 remote_cid); 144 + u32 (*seqpacket_has_data)(struct vsock_sock *vsk); 143 145 144 146 /* Notification. */ 145 147 int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
+46 -2
net/vmw_vsock/af_vsock.c
··· 452 452 new_transport = transport_dgram; 453 453 break; 454 454 case SOCK_STREAM: 455 + case SOCK_SEQPACKET: 455 456 if (vsock_use_local_transport(remote_cid)) 456 457 new_transport = transport_local; 457 458 else if (remote_cid <= VMADDR_CID_HOST || !transport_h2g || ··· 484 483 */ 485 484 if (!new_transport || !try_module_get(new_transport->module)) 486 485 return -ENODEV; 486 + 487 + if (sk->sk_type == SOCK_SEQPACKET) { 488 + if (!new_transport->seqpacket_allow || 489 + !new_transport->seqpacket_allow(remote_cid)) { 490 + module_put(new_transport->module); 491 + return -ESOCKTNOSUPPORT; 492 + } 493 + } 487 494 488 495 ret = new_transport->init(vsk, psk); 489 496 if (ret) { ··· 693 684 694 685 switch (sk->sk_socket->type) { 695 686 case SOCK_STREAM: 687 + case SOCK_SEQPACKET: 696 688 spin_lock_bh(&vsock_table_lock); 697 689 retval = __vsock_bind_connectible(vsk, addr); 698 690 spin_unlock_bh(&vsock_table_lock); ··· 780 770 781 771 static bool sock_type_connectible(u16 type) 782 772 { 783 - return type == SOCK_STREAM; 773 + return (type == SOCK_STREAM) || (type == SOCK_SEQPACKET); 784 774 } 785 775 786 776 static void __vsock_release(struct sock *sk, int level) ··· 858 848 return vsk->transport->stream_has_data(vsk); 859 849 } 860 850 EXPORT_SYMBOL_GPL(vsock_stream_has_data); 851 + 852 + static s64 vsock_has_data(struct vsock_sock *vsk) 853 + { 854 + struct sock *sk = sk_vsock(vsk); 855 + 856 + if (sk->sk_type == SOCK_SEQPACKET) 857 + return vsk->transport->seqpacket_has_data(vsk); 858 + else 859 + return vsock_stream_has_data(vsk); 860 + } 861 861 862 862 s64 vsock_stream_has_space(struct vsock_sock *vsk) 863 863 { ··· 1877 1857 err = 0; 1878 1858 transport = vsk->transport; 1879 1859 1880 - while ((data = vsock_stream_has_data(vsk)) == 0) { 1860 + while ((data = vsock_has_data(vsk)) == 0) { 1881 1861 prepare_to_wait(sk_sleep(sk), wait, TASK_INTERRUPTIBLE); 1882 1862 1883 1863 if (sk->sk_err != 0 || ··· 2140 2120 .sendpage = sock_no_sendpage, 2141 2121 }; 2142 2122 2123 + static const struct proto_ops vsock_seqpacket_ops = { 2124 + .family = PF_VSOCK, 2125 + .owner = THIS_MODULE, 2126 + .release = vsock_release, 2127 + .bind = vsock_bind, 2128 + .connect = vsock_connect, 2129 + .socketpair = sock_no_socketpair, 2130 + .accept = vsock_accept, 2131 + .getname = vsock_getname, 2132 + .poll = vsock_poll, 2133 + .ioctl = sock_no_ioctl, 2134 + .listen = vsock_listen, 2135 + .shutdown = vsock_shutdown, 2136 + .setsockopt = vsock_connectible_setsockopt, 2137 + .getsockopt = vsock_connectible_getsockopt, 2138 + .sendmsg = vsock_connectible_sendmsg, 2139 + .recvmsg = vsock_connectible_recvmsg, 2140 + .mmap = sock_no_mmap, 2141 + .sendpage = sock_no_sendpage, 2142 + }; 2143 + 2143 2144 static int vsock_create(struct net *net, struct socket *sock, 2144 2145 int protocol, int kern) 2145 2146 { ··· 2180 2139 break; 2181 2140 case SOCK_STREAM: 2182 2141 sock->ops = &vsock_stream_ops; 2142 + break; 2143 + case SOCK_SEQPACKET: 2144 + sock->ops = &vsock_seqpacket_ops; 2183 2145 break; 2184 2146 default: 2185 2147 return -ESOCKTNOSUPPORT;