]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add AF_VSOCK support to socket units 5046/head
authorStefan Hajnoczi <stefanha@redhat.com>
Wed, 21 Dec 2016 17:02:08 +0000 (17:02 +0000)
committerStefan Hajnoczi <stefanha@redhat.com>
Tue, 10 Jan 2017 15:29:04 +0000 (15:29 +0000)
Accept AF_VSOCK listen addresses in socket unit files.  Both guest and
host can now take advantage of socket activation.

The QEMU guest agent has recently been modified to support socket
activation and can run over AF_VSOCK with this patch.

man/systemd.socket.xml
src/core/service.c
src/core/socket.c

index 0ce1203cfbdfa53d82ec87ee4b359f90a486f730..1d20a8f7f758270f9c65b9cb1c90b8539f54ea09 100644 (file)
         <varname>BindIPv6Only=</varname> setting (see below).
         </para>
 
+        <para>If the address string is a string in the format
+        <literal>vsock:x:y</literal>, it is read as CID <literal>x</literal> on
+        a port <literal>y</literal> address in the
+        <constant>AF_VSOCK</constant> family.  The CID is a unique 32-bit
+        integer identifier in <constant>AF_VSOCK</constant> analogous to an IP
+        address.  Specifying the CID is optional, and may be set to the empty
+        string.</para>
+
         <para>Note that <constant>SOCK_SEQPACKET</constant> (i.e.
         <varname>ListenSequentialPacket=</varname>) is only available
         for <constant>AF_UNIX</constant> sockets.
index dc7b685cd3a09418bb9d44bc011f603fbd75c9ce..54074ff7bcc6da5bc4f79d5023f5299accd9d014 100644 (file)
@@ -1292,7 +1292,7 @@ static int service_spawn(
                                 return r;
                 }
 
-                if (r == 0 && IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) {
+                if (r == 0 && IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
                         _cleanup_free_ char *addr = NULL;
                         char *t;
                         unsigned port;
index 521688bed50e7eab65bd3471e68b0b5612ca4446..c4ce88c5f4d515d75840ce60806459802e8f6d29 100644 (file)
@@ -485,12 +485,13 @@ static void peer_address_hash_func(const void *p, struct siphash *state) {
         const SocketPeer *s = p;
 
         assert(s);
-        assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6));
 
         if (s->peer.sa.sa_family == AF_INET)
                 siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state);
         else if (s->peer.sa.sa_family == AF_INET6)
                 siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state);
+        else if (s->peer.sa.sa_family == AF_VSOCK)
+                siphash24_compress(&s->peer.vm.svm_cid, sizeof(s->peer.vm.svm_cid), state);
         else
                 assert_not_reached("Unknown address family.");
 }
@@ -508,6 +509,12 @@ static int peer_address_compare_func(const void *a, const void *b) {
                 return memcmp(&x->peer.in.sin_addr, &y->peer.in.sin_addr, sizeof(x->peer.in.sin_addr));
         case AF_INET6:
                 return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr));
+        case AF_VSOCK:
+                if (x->peer.vm.svm_cid < y->peer.vm.svm_cid)
+                        return -1;
+                if (x->peer.vm.svm_cid > y->peer.vm.svm_cid)
+                        return 1;
+                return 0;
         }
         assert_not_reached("Black sheep in the family!");
 }
@@ -594,7 +601,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
         if (r < 0)
                 return log_error_errno(errno, "getpeername failed: %m");
 
-        if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6)) {
+        if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
                 *p = NULL;
                 return 0;
         }
@@ -941,6 +948,16 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
                 break;
         }
 
+        case AF_VSOCK:
+                if (asprintf(&r,
+                             "%u-%u:%u-%u:%u",
+                             nr,
+                             local.vm.svm_cid, local.vm.svm_port,
+                             remote.vm.svm_cid, remote.vm.svm_port) < 0)
+                        return -ENOMEM;
+
+                break;
+
         default:
                 assert_not_reached("Unhandled socket type.");
         }