This adds socket operations for SOCK_SEQPACKET and adds this type of
socket for conditions where SOCK_STREAM is involved because both type of
sockets are connect oriented.

Signed-off-by: Arseny Krasnov <arseny.kras...@kaspersky.com>
---
 net/vmw_vsock/af_vsock.c | 108 +++++++++++++++++++++++++++++++++------
 1 file changed, 92 insertions(+), 16 deletions(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 4a7cdf7756c0..d0ef066e9352 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -452,6 +452,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct 
vsock_sock *psk)
                new_transport = transport_dgram;
                break;
        case SOCK_STREAM:
+       case SOCK_SEQPACKET:
                if (vsock_use_local_transport(remote_cid))
                        new_transport = transport_local;
                else if (remote_cid <= VMADDR_CID_HOST || !transport_h2g ||
@@ -459,6 +460,13 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct 
vsock_sock *psk)
                        new_transport = transport_g2h;
                else
                        new_transport = transport_h2g;
+
+               if (sk->sk_type == SOCK_SEQPACKET) {
+                       if (!new_transport->seqpacket_seq_send_len ||
+                           !new_transport->seqpacket_seq_get_len ||
+                           !new_transport->seqpacket_dequeue)
+                               return -ENODEV;
+               }
                break;
        default:
                return -ESOCKTNOSUPPORT;
@@ -604,8 +612,8 @@ static void vsock_pending_work(struct work_struct *work)
 
 /**** SOCKET OPERATIONS ****/
 
-static int __vsock_bind_stream(struct vsock_sock *vsk,
-                              struct sockaddr_vm *addr)
+static int __vsock_bind_connectible(struct vsock_sock *vsk,
+                                   struct sockaddr_vm *addr)
 {
        static u32 port;
        struct sockaddr_vm new_addr;
@@ -684,8 +692,9 @@ static int __vsock_bind(struct sock *sk, struct sockaddr_vm 
*addr)
 
        switch (sk->sk_socket->type) {
        case SOCK_STREAM:
+       case SOCK_SEQPACKET:
                spin_lock_bh(&vsock_table_lock);
-               retval = __vsock_bind_stream(vsk, addr);
+               retval = __vsock_bind_connectible(vsk, addr);
                spin_unlock_bh(&vsock_table_lock);
                break;
 
@@ -767,6 +776,11 @@ static struct sock *__vsock_create(struct net *net,
        return sk;
 }
 
+static bool sock_type_connectible(u16 type)
+{
+       return (type == SOCK_STREAM || type == SOCK_SEQPACKET);
+}
+
 static void __vsock_release(struct sock *sk, int level)
 {
        if (sk) {
@@ -785,7 +799,7 @@ static void __vsock_release(struct sock *sk, int level)
 
                if (vsk->transport)
                        vsk->transport->release(vsk);
-               else if (sk->sk_type == SOCK_STREAM)
+               else if (sock_type_connectible(sk->sk_type))
                        vsock_remove_sock(vsk);
 
                sock_orphan(sk);
@@ -945,7 +959,7 @@ static int vsock_shutdown(struct socket *sock, int mode)
        sk = sock->sk;
        if (sock->state == SS_UNCONNECTED) {
                err = -ENOTCONN;
-               if (sk->sk_type == SOCK_STREAM)
+               if (sock_type_connectible(sk->sk_type))
                        return err;
        } else {
                sock->state = SS_DISCONNECTING;
@@ -960,7 +974,7 @@ static int vsock_shutdown(struct socket *sock, int mode)
                sk->sk_state_change(sk);
                release_sock(sk);
 
-               if (sk->sk_type == SOCK_STREAM) {
+               if (sock_type_connectible(sk->sk_type)) {
                        sock_reset_flag(sk, SOCK_DONE);
                        vsock_send_shutdown(sk, mode);
                }
@@ -1013,7 +1027,7 @@ static __poll_t vsock_poll(struct file *file, struct 
socket *sock,
                if (!(sk->sk_shutdown & SEND_SHUTDOWN))
                        mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
 
-       } else if (sock->type == SOCK_STREAM) {
+       } else if (sock_type_connectible(sk->sk_type)) {
                const struct vsock_transport *transport = vsk->transport;
                lock_sock(sk);
 
@@ -1259,8 +1273,8 @@ static void vsock_connect_timeout(struct work_struct 
*work)
        sock_put(sk);
 }
 
-static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
-                               int addr_len, int flags)
+static int vsock_connect(struct socket *sock, struct sockaddr *addr,
+                        int addr_len, int flags)
 {
        int err;
        struct sock *sk;
@@ -1410,7 +1424,7 @@ static int vsock_accept(struct socket *sock, struct 
socket *newsock, int flags,
 
        lock_sock(listener);
 
-       if (sock->type != SOCK_STREAM) {
+       if (!sock_type_connectible(sock->type)) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -1477,6 +1491,18 @@ static int vsock_accept(struct socket *sock, struct 
socket *newsock, int flags,
        return err;
 }
 
+static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
+                               int addr_len, int flags)
+{
+       return vsock_connect(sock, addr, addr_len, flags);
+}
+
+static int vsock_seqpacket_connect(struct socket *sock, struct sockaddr *addr,
+                                  int addr_len, int flags)
+{
+       return vsock_connect(sock, addr, addr_len, flags);
+}
+
 static int vsock_listen(struct socket *sock, int backlog)
 {
        int err;
@@ -1487,7 +1513,7 @@ static int vsock_listen(struct socket *sock, int backlog)
 
        lock_sock(sk);
 
-       if (sock->type != SOCK_STREAM) {
+       if (!sock_type_connectible(sk->sk_type)) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -1531,11 +1557,11 @@ static void vsock_update_buffer_size(struct vsock_sock 
*vsk,
        vsk->buffer_size = val;
 }
 
-static int vsock_stream_setsockopt(struct socket *sock,
-                                  int level,
-                                  int optname,
-                                  sockptr_t optval,
-                                  unsigned int optlen)
+static int vsock_setsockopt(struct socket *sock,
+                           int level,
+                           int optname,
+                           sockptr_t optval,
+                           unsigned int optlen)
 {
        int err;
        struct sock *sk;
@@ -1612,6 +1638,24 @@ static int vsock_stream_setsockopt(struct socket *sock,
        return err;
 }
 
+static int vsock_seqpacket_setsockopt(struct socket *sock,
+                                     int level,
+                                     int optname,
+                                     sockptr_t optval,
+                                     unsigned int optlen)
+{
+       return vsock_setsockopt(sock, level, optname, optval, optlen);
+}
+
+static int vsock_stream_setsockopt(struct socket *sock,
+                                  int level,
+                                  int optname,
+                                  sockptr_t optval,
+                                  unsigned int optlen)
+{
+       return vsock_setsockopt(sock, level, optname, optval, optlen);
+}
+
 static int vsock_stream_getsockopt(struct socket *sock,
                                   int level, int optname,
                                   char __user *optval,
@@ -1683,6 +1727,14 @@ static int vsock_stream_getsockopt(struct socket *sock,
        return 0;
 }
 
+static int vsock_seqpacket_getsockopt(struct socket *sock,
+                                     int level, int optname,
+                                     char __user *optval,
+                                     int __user *optlen)
+{
+       return vsock_stream_getsockopt(sock, level, optname, optval, optlen);
+}
+
 static int vsock_connectible_sendmsg(struct socket *sock, struct msghdr *msg,
                                     size_t len)
 {
@@ -2184,6 +2236,27 @@ static const struct proto_ops vsock_stream_ops = {
        .sendpage = sock_no_sendpage,
 };
 
+static const struct proto_ops vsock_seqpacket_ops = {
+       .family = PF_VSOCK,
+       .owner = THIS_MODULE,
+       .release = vsock_release,
+       .bind = vsock_bind,
+       .connect = vsock_seqpacket_connect,
+       .socketpair = sock_no_socketpair,
+       .accept = vsock_accept,
+       .getname = vsock_getname,
+       .poll = vsock_poll,
+       .ioctl = sock_no_ioctl,
+       .listen = vsock_listen,
+       .shutdown = vsock_shutdown,
+       .setsockopt = vsock_seqpacket_setsockopt,
+       .getsockopt = vsock_seqpacket_getsockopt,
+       .sendmsg = vsock_seqpacket_sendmsg,
+       .recvmsg = vsock_seqpacket_recvmsg,
+       .mmap = sock_no_mmap,
+       .sendpage = sock_no_sendpage,
+};
+
 static int vsock_create(struct net *net, struct socket *sock,
                        int protocol, int kern)
 {
@@ -2204,6 +2277,9 @@ static int vsock_create(struct net *net, struct socket 
*sock,
        case SOCK_STREAM:
                sock->ops = &vsock_stream_ops;
                break;
+       case SOCK_SEQPACKET:
+               sock->ops = &vsock_seqpacket_ops;
+               break;
        default:
                return -ESOCKTNOSUPPORT;
        }
-- 
2.25.1

Reply via email to