4fec1b
From 00f93eb12547bbd7314394e23faf72695972efcf Mon Sep 17 00:00:00 2001
4fec1b
Message-Id: <00f93eb12547bbd7314394e23faf72695972efcf@dist-git>
4fec1b
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
4fec1b
Date: Tue, 24 Jun 2014 16:02:37 +0200
4fec1b
Subject: [PATCH] Don't use AI_ADDRCONFIG when binding to wildcard addresses
4fec1b
4fec1b
https://bugzilla.redhat.com/show_bug.cgi?id=1112692
4fec1b
4fec1b
With parallel boot, network addresses might not yet be assigned [1],
4fec1b
but binding to wildcard addresses should work.
4fec1b
4fec1b
For non-wildcard addresses, ADDRCONFIG is still used. Document this
4fec1b
in libvirtd.conf.
4fec1b
4fec1b
[1] http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
4fec1b
4fec1b
(cherry picked from commit 819ca36e2b65a0a34263547161a98cec497780c8)
4fec1b
4fec1b
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
4fec1b
---
4fec1b
 daemon/libvirtd.conf   |  4 ++++
4fec1b
 src/rpc/virnetsocket.c | 28 ++++++++++++++++++++++++++--
4fec1b
 2 files changed, 30 insertions(+), 2 deletions(-)
4fec1b
4fec1b
diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf
4fec1b
index 5353927..e518ae5 100644
4fec1b
--- a/daemon/libvirtd.conf
4fec1b
+++ b/daemon/libvirtd.conf
4fec1b
@@ -48,6 +48,10 @@
4fec1b
 # Override the default configuration which binds to all network
4fec1b
 # interfaces. This can be a numeric IPv4/6 address, or hostname
4fec1b
 #
4fec1b
+# If the libvirtd service is started in parallel with network
4fec1b
+# startup (e.g. with systemd), binding to addresses other than
4fec1b
+# the wildcards (0.0.0.0/::) might not be available yet.
4fec1b
+#
4fec1b
 #listen_addr = "192.168.0.1"
4fec1b
 
4fec1b
 
4fec1b
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
4fec1b
index fcd41ca..85fedb0 100644
4fec1b
--- a/src/rpc/virnetsocket.c
4fec1b
+++ b/src/rpc/virnetsocket.c
4fec1b
@@ -224,15 +224,29 @@ int virNetSocketNewListenTCP(const char *nodename,
4fec1b
     struct addrinfo hints;
4fec1b
     int fd = -1;
4fec1b
     size_t i;
4fec1b
-    int addrInUse = false;
4fec1b
+    bool addrInUse = false;
4fec1b
+    bool familyNotSupported = false;
4fec1b
+    virSocketAddr tmp_addr;
4fec1b
 
4fec1b
     *retsocks = NULL;
4fec1b
     *nretsocks = 0;
4fec1b
 
4fec1b
     memset(&hints, 0, sizeof(hints));
4fec1b
-    hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
4fec1b
+    hints.ai_flags = AI_PASSIVE;
4fec1b
     hints.ai_socktype = SOCK_STREAM;
4fec1b
 
4fec1b
+    /* Don't use ADDRCONFIG for binding to the wildcard address.
4fec1b
+     * Just catch the error returned by socket() if the system has
4fec1b
+     * no IPv6 support.
4fec1b
+     *
4fec1b
+     * This allows libvirtd to be started in parallel with the network
4fec1b
+     * startup in most cases.
4fec1b
+     */
4fec1b
+    if (nodename &&
4fec1b
+        !(virSocketAddrParse(&tmp_addr, nodename, AF_UNSPEC) > 0 &&
4fec1b
+          virSocketAddrIsWildcard(&tmp_addr)))
4fec1b
+        hints.ai_flags |= AI_ADDRCONFIG;
4fec1b
+
4fec1b
     int e = getaddrinfo(nodename, service, &hints, &ai;;
4fec1b
     if (e != 0) {
4fec1b
         virReportError(VIR_ERR_SYSTEM_ERROR,
4fec1b
@@ -249,6 +263,11 @@ int virNetSocketNewListenTCP(const char *nodename,
4fec1b
 
4fec1b
         if ((fd = socket(runp->ai_family, runp->ai_socktype,
4fec1b
                          runp->ai_protocol)) < 0) {
4fec1b
+            if (errno == EAFNOSUPPORT) {
4fec1b
+                familyNotSupported = true;
4fec1b
+                runp = runp->ai_next;
4fec1b
+                continue;
4fec1b
+            }
4fec1b
             virReportSystemError(errno, "%s", _("Unable to create socket"));
4fec1b
             goto error;
4fec1b
         }
4fec1b
@@ -306,6 +325,11 @@ int virNetSocketNewListenTCP(const char *nodename,
4fec1b
         fd = -1;
4fec1b
     }
4fec1b
 
4fec1b
+    if (nsocks == 0 && familyNotSupported) {
4fec1b
+        virReportSystemError(EAFNOSUPPORT, "%s", _("Unable to bind to port"));
4fec1b
+        goto error;
4fec1b
+    }
4fec1b
+
4fec1b
     if (nsocks == 0 &&
4fec1b
         addrInUse) {
4fec1b
         virReportSystemError(EADDRINUSE, "%s", _("Unable to bind to port"));
4fec1b
-- 
4fec1b
2.0.0
4fec1b