]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Remove use of non-reentrant POSIX apis
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 22 Jan 2009 19:41:48 +0000 (19:41 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 22 Jan 2009 19:41:48 +0000 (19:41 +0000)
18 files changed:
ChangeLog
configure.in
proxy/libvirt_proxy.c
qemud/qemud.c
src/libvirt_private.syms
src/lxc_container.c
src/network_driver.c
src/openvz_driver.c
src/qemu_driver.c
src/remote_internal.c
src/storage_backend_fs.c
src/storage_driver.c
src/uml_driver.c
src/util.c
src/util.h
src/xen_unified.c
src/xen_unified.h
src/xend_internal.c

index febf84989af2fcf21e5cdb35c3a430a0bda51463..26186d2cc7b03719740a869b88cbcb648acbd38b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Thu Jan 21 19:04:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+
+       Remove use of non-reentrant POSIX api calls
+       * configure.in: Check for  strtok_r getmntent_r getgrnam_r getpwuid_r
+       * proxy/libvirt_proxy.c: Remove initialize of obsolete fields
+       * qemud/qemud.c: Use virGetUserDirectory instead of getpwuid()
+       * src/libvirt_private.syms, src/util.c, src/util.h: Add a generic
+       virGetUserDirectory call around getpwuid()
+       * src/lxc_container.c, src/storage_backend_fs.c: Use getmntent_r()
+       * src/network_driver.c, src/qemu_driver.c, src/storage_driver.c,
+       src/remote_internal.c, src/uml_driver.c: Use virGetUserDirectory()
+       * src/openvz_driver.c: Use strtok_r()
+       * src/xen_unified.c, src/xen_unified.h, src/xend_internal.c:
+       Replace gethostname() with getaddrinfo()
+
 Thu Jan 22 20:17:35 +0100 2009 Jim Meyering <meyering@redhat.com>
 
        xm_internal.c: fix locking bug: s/Lock/Unlock/
@@ -44,7 +59,7 @@ Thu Jan 22 09:51:29 PST 2009 John Levon <john.levon@sun.com>
        tests/sexpr2xmldata/sexpr2xml-net-bridged.xml,
        tests/sexpr2xmldata/sexpr2xml-net-e1000.xml: update tests
 
-Wed Jan 21 18:18:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+Thu Jan 22 18:18:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
 
        Missing test case fix up from Xen threadsafety changes
        * tests/sexpr2xmltest.c, tests/Makefile.am: Pass a real
index 493ea28364d2d672a5ac37d809ba579f2f80f991..dab68358a7fddd932708e9bc56cbdc0be72dda45 100644 (file)
@@ -75,7 +75,7 @@ dnl Availability of various common functions (non-fatal if missing).
 AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity getuid getgid])
 
 dnl Availability of various not common threadsafe functions
-AC_CHECK_FUNCS([strerror_r])
+AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r])
 
 dnl Availability of various common headers (non-fatal if missing).
 AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/syslimits.h sys/utsname.h sys/wait.h winsock2.h sched.h termios.h sys/poll.h syslog.h])
index 3b0dc42d95fb343b920c0a2d7f4164b0b3eae348..f3d9edeacbfe56b3dc0afa15f693e04f201ea585 100644 (file)
@@ -76,9 +76,6 @@ proxyInitXen(void) {
 
     priv->handle = -1;
     priv->xendConfigVersion = -1;
-    priv->type = -1;
-    priv->len = -1;
-    priv->addr = NULL;
     priv->xshandle = NULL;
     priv->proxy = -1;
 
index 32902e8893c6f61676598be212e5e237b2c847d1..55f31d5ee14c4b5932833280fdeae97d522d062a 100644 (file)
@@ -718,20 +718,18 @@ static int qemudInitPaths(struct qemud_server *server,
         if (snprintf(server->logDir, PATH_MAX, "%s/log/libvirt/", LOCAL_STATE_DIR) >= PATH_MAX)
             goto snprintf_error;
     } else {
-        struct passwd *pw;
+        char *userdir = virGetUserDirectory(NULL, uid);
 
-        if (!(pw = getpwuid(uid))) {
-            VIR_ERROR(_("Failed to find user record for uid '%d': %s"),
-                     uid, strerror(errno));
-            return -1;
-        }
-
-        if (snprintf(sockname, maxlen, "@%s/.libvirt/libvirt-sock", pw->pw_dir) >= maxlen)
+        if (snprintf(sockname, maxlen, "@%s/.libvirt/libvirt-sock", userdir) >= maxlen) {
+            VIR_FREE(userdir);
             goto snprintf_error;
+        }
 
-        if (snprintf(server->logDir, PATH_MAX, "%s/.libvirt/log", pw->pw_dir) >= PATH_MAX)
+        if (snprintf(server->logDir, PATH_MAX, "%s/.libvirt/log", userdir) >= PATH_MAX) {
+            VIR_FREE(userdir);
             goto snprintf_error;
-
+        }
+        VIR_FREE(userdir);
     } /* !remote */
 
     return 0;
@@ -2486,8 +2484,9 @@ remoteReadConfigFile (struct qemud_server *server, const char *filename)
         if (getuid() != 0) {
             VIR_WARN0(_("Cannot set group when not running as root"));
         } else {
-            struct group *grp = getgrnam(unix_sock_group);
-            if (!grp) {
+            char buf[1024];
+            struct group grpdata, *grp;
+            if (getgrnam_r(unix_sock_group, &grpdata, buf, sizeof(buf), &grp) != 0 || !grp) {
                 VIR_ERROR(_("Failed to lookup group '%s'"), unix_sock_group);
                 goto free_and_fail;
             }
index efdbaeab3ca52b00a69cba8e7556c47ae6b7d1d2..7b177063a83351adc78da621960a50e7a65847c2 100644 (file)
@@ -310,6 +310,7 @@ virAsprintf;
 virRun;
 virSkipSpaces;
 virKillProcess;
+virGetUserDirectory;
 
 
 # uuid.h
index 03bd2b9ce5e8799f404f016fbb9c4fdd8c65bfe0..3bf533c133be9392d1d67d64954b3be393b4f8af 100644 (file)
@@ -414,19 +414,20 @@ static int lxcContainerMountNewFS(virDomainDefPtr vmDef)
 
 static int lxcContainerUnmountOldFS(void)
 {
-    struct mntent *mntent;
+    struct mntent mntent;
     char **mounts = NULL;
     int nmounts = 0;
     FILE *procmnt;
     int i;
+    char mntbuf[1024];
 
     if (!(procmnt = setmntent("/proc/mounts", "r"))) {
         virReportSystemError(NULL, errno, "%s",
                              _("failed to read /proc/mounts"));
         return -1;
     }
-    while ((mntent = getmntent(procmnt)) != NULL) {
-        if (!STRPREFIX(mntent->mnt_dir, "/.oldroot"))
+    while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
+        if (!STRPREFIX(mntent.mnt_dir, "/.oldroot"))
             continue;
 
         if (VIR_REALLOC_N(mounts, nmounts+1) < 0) {
@@ -434,7 +435,7 @@ static int lxcContainerUnmountOldFS(void)
             lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
             return -1;
         }
-        if (!(mounts[nmounts++] = strdup(mntent->mnt_dir))) {
+        if (!(mounts[nmounts++] = strdup(mntent.mnt_dir))) {
             endmntent(procmnt);
             lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
             return -1;
index 5d576638412cb416e95081f2ba0671ad32268e9a..c546a2b9690d9496cc5072e19aa4453d6cf852ee 100644 (file)
@@ -195,7 +195,6 @@ networkAutostartConfigs(struct network_driver *driver) {
 static int
 networkStartup(void) {
     uid_t uid = geteuid();
-    struct passwd *pw;
     char *base = NULL;
     int err;
 
@@ -216,19 +215,22 @@ networkStartup(void) {
         if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
             goto out_of_memory;
     } else {
-        if (!(pw = getpwuid(uid))) {
-            networkLog(NETWORK_ERR, _("Failed to find user record for uid '%d': %s\n"),
-                     uid, strerror(errno));
-            goto out_of_memory;
-        }
+        char *userdir = virGetUserDirectory(NULL, uid);
+
+        if (!userdir)
+            goto error;
 
         if (virAsprintf(&driverState->logDir,
-                        "%s/.libvirt/qemu/log", pw->pw_dir) == -1)
+                        "%s/.libvirt/qemu/log", userdir) == -1) {
+            VIR_FREE(userdir);
             goto out_of_memory;
+        }
 
-        if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1) {
+        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
+            VIR_FREE(userdir);
             goto out_of_memory;
         }
+        VIR_FREE(userdir);
     }
 
     /* Configuration paths are either ~/.libvirt/qemu/... (session) or
index 4e83bedd3cf3e7a89f32e657e11b2cba244a59b9..d22ea396e405638024664de33dd0e0deec30fd99 100644 (file)
@@ -448,11 +448,12 @@ openvzGenerateContainerVethName(int veid)
     if ( (ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
         snprintf(temp, sizeof(temp), "eth0");
     } else {
+        char *saveptr;
         char   *s;
         int     max = 0;
 
         /* get maximum interface number (actually, it is the last one) */
-        for (s=strtok(temp, ";"); s; s=strtok(NULL, ";")) {
+        for (s=strtok_r(temp, ";", &saveptr); s; s=strtok_r(NULL, ";", &saveptr)) {
             int x;
 
             if (sscanf(s, "ifname=eth%d", &x) != 1) return NULL;
index d61d7ba76edc248e25c01a71027710c8cfa5688e..3d9a0a25f26f777f8adde5b279535db24dd52ee6 100644 (file)
@@ -382,7 +382,6 @@ next:
 static int
 qemudStartup(void) {
     uid_t uid = geteuid();
-    struct passwd *pw;
     char *base = NULL;
     char driverConf[PATH_MAX];
 
@@ -421,27 +420,30 @@ qemudStartup(void) {
                       "%s/run/libvirt/qemu/", LOCAL_STATE_DIR) == -1)
             goto out_of_memory;
     } else {
-        if (!(pw = getpwuid(uid))) {
-            qemudLog(QEMUD_ERR, _("Failed to find user record for uid '%d': %s\n"),
-                     uid, strerror(errno));
+        char *userdir = virGetUserDirectory(NULL, uid);
+        if (!userdir)
             goto error;
-        }
 
         if (virAsprintf(&qemu_driver->logDir,
-                        "%s/.libvirt/qemu/log", pw->pw_dir) == -1)
+                        "%s/.libvirt/qemu/log", userdir) == -1) {
+            VIR_FREE(userdir);
             goto out_of_memory;
+        }
 
-        if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1)
+        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
+            VIR_FREE(userdir);
             goto out_of_memory;
+        }
+        VIR_FREE(userdir);
 
         if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
             goto out_of_memory;
     }
 
     if (virFileMakePath(qemu_driver->stateDir) < 0) {
-            qemudLog(QEMUD_ERR, _("Failed to create state dir '%s': %s\n"),
-                     qemu_driver->stateDir, strerror(errno));
-            goto error;
+        qemudLog(QEMUD_ERR, _("Failed to create state dir '%s': %s\n"),
+                 qemu_driver->stateDir, strerror(errno));
+        goto error;
     }
 
     /* Configuration paths are either ~/.libvirt/qemu/... (session) or
index 51a40b8741a7f2b05986ceaa1abf8f1732ed0742..93b27afffea949036b6ed09f15af151aaa8798a0 100644 (file)
@@ -605,19 +605,16 @@ doRemoteOpen (virConnectPtr conn,
     case trans_unix: {
         if (!sockname) {
             if (flags & VIR_DRV_OPEN_REMOTE_USER) {
-                struct passwd *pw;
-                uid_t uid = getuid();
+                char *userdir = virGetUserDirectory(conn, getuid());
 
-                if (!(pw = getpwuid(uid))) {
-                    virReportSystemError(conn, errno,
-                                         _("unable to lookup user '%d'"),
-                                         uid);
+                if (!userdir)
                     goto failed;
-                }
 
-                if (virAsprintf(&sockname, "@%s" LIBVIRTD_USER_UNIX_SOCKET, pw->pw_dir) < 0)
+                if (virAsprintf(&sockname, "@%s" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0) {
+                    VIR_FREE(userdir);
                     goto out_of_memory;
-
+                }
+                VIR_FREE(userdir);
             } else {
                 if (flags & VIR_DRV_OPEN_REMOTE_RO)
                     sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET_RO);
index 0dd134cf82bc1c7eca02b75e9f2794d9eda5e16f..544f4e2f6b3b44f6a9869670cc9bcc3981944d9f 100644 (file)
@@ -385,7 +385,8 @@ static int
 virStorageBackendFileSystemIsMounted(virConnectPtr conn,
                                      virStoragePoolObjPtr pool) {
     FILE *mtab;
-    struct mntent *ent;
+    struct mntent ent;
+    char buf[1024];
 
     if ((mtab = fopen(_PATH_MOUNTED, "r")) == NULL) {
         virReportSystemError(conn, errno,
@@ -394,8 +395,8 @@ virStorageBackendFileSystemIsMounted(virConnectPtr conn,
         return -1;
     }
 
-    while ((ent = getmntent(mtab)) != NULL) {
-        if (STREQ(ent->mnt_dir, pool->def->target.path)) {
+    while ((getmntent_r(mtab, &ent, buf, sizeof(buf))) != NULL) {
+        if (STREQ(ent.mnt_dir, pool->def->target.path)) {
             fclose(mtab);
             return 1;
         }
index 6ca5c1e5ba31668ca4116ca8fadfb0f887d31a52..a4560611a933640531d4567a7a3c367cf916e5dd 100644 (file)
@@ -108,7 +108,6 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
 static int
 storageDriverStartup(void) {
     uid_t uid = geteuid();
-    struct passwd *pw;
     char *base = NULL;
     char driverConf[PATH_MAX];
 
@@ -125,16 +124,17 @@ storageDriverStartup(void) {
         if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
             goto out_of_memory;
     } else {
-        if (!(pw = getpwuid(uid))) {
-            storageLog("Failed to find user record for uid '%d': %s",
-                       uid, strerror(errno));
-            goto out_of_memory;
-        }
+        char *userdir = virGetUserDirectory(NULL, uid);
+
+        if (!userdir)
+            goto error;
 
-        if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1) {
+        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
             storageLog("out of memory in virAsprintf");
+            VIR_FREE(userdir);
             goto out_of_memory;
         }
+        VIR_FREE(userdir);
     }
 
     /* Configuration paths are either ~/.libvirt/storage/... (session) or
index 2af2305538e878f077824f35022910dcb2398579..65bbbe666b29b67f9cea847cce1cd2505c41cf53 100644 (file)
@@ -309,9 +309,9 @@ cleanup:
 static int
 umlStartup(void) {
     uid_t uid = geteuid();
-    struct passwd *pw;
     char *base = NULL;
     char driverConf[PATH_MAX];
+    char *userdir = NULL;
 
     if (VIR_ALLOC(uml_driver) < 0)
         return -1;
@@ -325,11 +325,9 @@ umlStartup(void) {
     /* Don't have a dom0 so start from 1 */
     uml_driver->nextvmid = 1;
 
-    if (!(pw = getpwuid(uid))) {
-        umlLog(VIR_LOG_ERROR, _("Failed to find user record for uid '%d': %s\n"),
-               uid, strerror(errno));
+    userdir = virGetUserDirectory(NULL, uid);
+    if (!userdir)
         goto error;
-    }
 
     if (!uid) {
         if (virAsprintf(&uml_driver->logDir,
@@ -339,16 +337,17 @@ umlStartup(void) {
         if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
             goto out_of_memory;
     } else {
+
         if (virAsprintf(&uml_driver->logDir,
-                        "%s/.libvirt/uml/log", pw->pw_dir) == -1)
+                        "%s/.libvirt/uml/log", userdir) == -1)
             goto out_of_memory;
 
-        if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1)
+        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
             goto out_of_memory;
     }
 
     if (virAsprintf(&uml_driver->monitorDir,
-                    "%s/.uml", pw->pw_dir) == -1)
+                    "%s/.uml", userdir) == -1)
         goto out_of_memory;
 
     /* Configuration paths are either ~/.libvirt/uml/... (session) or
@@ -403,6 +402,8 @@ umlStartup(void) {
     umlAutostartConfigs(uml_driver);
 
     umlDriverUnlock(uml_driver);
+    VIR_FREE(userdir);
+
     return 0;
 
 out_of_memory:
@@ -410,6 +411,7 @@ out_of_memory:
               "%s", _("umlStartup: out of memory\n"));
 
 error:
+    VIR_FREE(userdir);
     VIR_FREE(base);
     umlDriverUnlock(uml_driver);
     umlShutdown();
index 7fe4ad3c3c6a18993cdc0f26c88f3099ec45af29..e4524d9517722755f243edc96ae844da86024516 100644 (file)
@@ -49,6 +49,9 @@
 #include <paths.h>
 #endif
 #include <netdb.h>
+#ifdef HAVE_GETPWUID_R
+#include <pwd.h>
+#endif
 
 #include "virterror_internal.h"
 #include "logging.h"
@@ -1431,3 +1434,37 @@ int virKillProcess(pid_t pid, int sig)
     return kill(pid, sig);
 #endif
 }
+
+
+#ifdef HAVE_GETPWUID_R
+char *virGetUserDirectory(virConnectPtr conn,
+                          uid_t uid)
+{
+    char *strbuf;
+    char *ret;
+    struct passwd pwbuf;
+    struct passwd *pw;
+    size_t strbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+
+    if (VIR_ALLOC_N(strbuf, strbuflen) < 0) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    if (getpwuid_r(uid, &pwbuf, strbuf, strbuflen, &pw) != 0) {
+        virReportSystemError(conn, errno,
+                             _("Failed to find user record for uid '%d'"),
+                             uid);
+        VIR_FREE(strbuf);
+        return NULL;
+    }
+
+    ret = strdup(pw->pw_dir);
+
+    VIR_FREE(strbuf);
+    if (!ret)
+        virReportOOMError(conn);
+
+    return ret;
+}
+#endif
index 81cfad6b01ae3efd547db21dfdc9ac10ab85a417..a94212e016fa8fead0299d4d117b00b50eef923b 100644 (file)
@@ -172,4 +172,9 @@ char *virGetHostname(void);
 
 int virKillProcess(pid_t pid, int sig);
 
+#ifdef HAVE_GETPWUID_R
+char *virGetUserDirectory(virConnectPtr conn,
+                          uid_t uid);
+#endif
+
 #endif /* __VIR_UTIL_H__ */
index 95968150be546615b4f1d8bf5035372e4c8f1e6c..70d8c7d2c6e478ebc4fd545e0e728d12bdb0d3ea 100644 (file)
@@ -284,9 +284,6 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
 
     priv->handle = -1;
     priv->xendConfigVersion = -1;
-    priv->type = -1;
-    priv->len = -1;
-    priv->addr = NULL;
     priv->xshandle = NULL;
     priv->proxy = -1;
 
index 569c7babc8d49931ced44c997383ea4081608bd3..3123bd71dee2695f0cd83922767515d142deded2 100644 (file)
@@ -142,13 +142,11 @@ struct _xenUnifiedPrivate {
 
     int xendConfigVersion;      /* XenD config version */
 
-    /* XXX This code is not IPv6 aware. */
     /* connection to xend */
-    int type;                   /* PF_UNIX or PF_INET */
-    int len;                    /* length of addr */
-    struct sockaddr *addr;      /* type of address used */
-    struct sockaddr_un addr_un; /* the unix address */
-    struct sockaddr_in addr_in; /* the inet address */
+    struct sockaddr_storage addr;
+    socklen_t addrlen;
+    int addrfamily;
+    int addrprotocol;
 
     /* Keep track of the drivers which opened.  We keep a yes/no flag
      * here for each driver, corresponding to the array drivers in
index 8c6e6524e7341987548ba0ec079d4e33a83fa819..321dfdf14a60b7811e1b0855fd113a04e3a39118 100644 (file)
 #define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
 #endif
 
-/**
- * xend_connection_type:
- *
- * The connection to the Xen Daemon can be done either though a normal TCP
- * socket or a local domain direct connection.
- */
-enum xend_connection_type {
-    XEND_DOMAIN,
-    XEND_TCP,
-};
-
-/**
- * xend:
- *
- * Structure associated to a connection to a Xen daemon
- */
-struct xend {
-    int len;
-    int type;
-    struct sockaddr *addr;
-    struct sockaddr_un addr_un;
-    struct sockaddr_in addr_in;
-};
-
 
 #ifndef PROXY
 static int
@@ -146,7 +122,7 @@ do_connect(virConnectPtr xend)
     int no_slow_start = 1;
     xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) xend->privateData;
 
-    s = socket(priv->type, SOCK_STREAM, 0);
+    s = socket(priv->addrfamily, SOCK_STREAM, priv->addrprotocol);
     if (s == -1) {
         virXendError(xend, VIR_ERR_INTERNAL_ERROR,
                      "%s", _("failed to create a socket"));
@@ -160,7 +136,7 @@ do_connect(virConnectPtr xend)
                sizeof(no_slow_start));
 
 
-    if (connect(s, priv->addr, priv->len) == -1) {
+    if (connect(s, (struct sockaddr *)&priv->addr, priv->addrlen) == -1) {
         serrno = errno;
         close(s);
         errno = serrno;
@@ -774,18 +750,16 @@ xenDaemonOpen_unix(virConnectPtr conn, const char *path)
     if ((conn == NULL) || (path == NULL))
         return (-1);
 
-    addr = &priv->addr_un;
+    memset(&priv->addr, 0, sizeof(priv->addr));
+    priv->addrfamily = AF_UNIX;
+    priv->addrprotocol = PF_UNIX;
+    priv->addrlen = sizeof(struct sockaddr_un);
+
+    addr = (struct sockaddr_un *)&priv->addr;
     addr->sun_family = AF_UNIX;
     memset(addr->sun_path, 0, sizeof(addr->sun_path));
     strncpy(addr->sun_path, path, sizeof(addr->sun_path));
 
-    priv->len = sizeof(addr->sun_family) + strlen(addr->sun_path);
-    if ((unsigned int) priv->len > sizeof(addr->sun_path))
-        priv->len = sizeof(addr->sun_path);
-
-    priv->addr = (struct sockaddr *) addr;
-    priv->type = PF_UNIX;
-
     return (0);
 }
 
@@ -802,38 +776,71 @@ xenDaemonOpen_unix(virConnectPtr conn, const char *path)
  * Returns 0 in case of success, -1 in case of error.
  */
 static int
-xenDaemonOpen_tcp(virConnectPtr conn, const char *host, int port)
+xenDaemonOpen_tcp(virConnectPtr conn, const char *host, const char *port)
 {
-    struct in_addr ip;
-    struct hostent *pent;
     xenUnifiedPrivatePtr priv;
+    struct addrinfo *res, *r;
+    struct addrinfo hints;
+    int saved_errno = EINVAL;
+    int ret;
 
-    if ((conn == NULL) || (host == NULL) || (port <= 0))
+    if ((conn == NULL) || (host == NULL) || (port == NULL))
         return (-1);
 
     priv = (xenUnifiedPrivatePtr) conn->privateData;
 
-    pent = gethostbyname(host);
-    if (pent == NULL) {
-        if (inet_aton(host, &ip) == 0) {
-            virXendError(NULL, VIR_ERR_UNKNOWN_HOST,
-                         _("gethostbyname failed: %s"), host);
-            errno = ESRCH;
-            return (-1);
+    priv->addrlen = 0;
+    memset(&priv->addr, 0, sizeof(priv->addr));
+
+    // http://people.redhat.com/drepper/userapi-ipv6.html
+    memset (&hints, 0, sizeof hints);
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_ADDRCONFIG;
+
+    ret = getaddrinfo (host, port, &hints, &res);
+    if (ret != 0) {
+        virXendError(NULL, VIR_ERR_UNKNOWN_HOST,
+                     _("unable to resolve hostname '%s': %s"),
+                     host, gai_strerror (ret));
+        return -1;
+    }
+
+    /* Try to connect to each returned address in turn. */
+    for (r = res; r; r = r->ai_next) {
+        int sock;
+
+        sock = socket (r->ai_family, SOCK_STREAM, r->ai_protocol);
+        if (sock == -1) {
+            saved_errno = errno;
+            continue;
         }
-    } else {
-        memcpy(&ip, pent->h_addr_list[0], sizeof(ip));
+
+        if (connect (sock, r->ai_addr, r->ai_addrlen) == -1) {
+            saved_errno = errno;
+            close (sock);
+            continue;
+        }
+
+        priv->addrlen = r->ai_addrlen;
+        priv->addrfamily = r->ai_family;
+        priv->addrprotocol = r->ai_protocol;
+        memcpy(&priv->addr,
+               r->ai_addr,
+               r->ai_addrlen);
+        close(sock);
+        break;
     }
 
-    priv->len = sizeof(struct sockaddr_in);
-    priv->addr = (struct sockaddr *) &priv->addr_in;
-    priv->type = PF_INET;
+    freeaddrinfo (res);
 
-    priv->addr_in.sin_family = AF_INET;
-    priv->addr_in.sin_port = htons(port);
-    memcpy(&priv->addr_in.sin_addr, &ip, sizeof(ip));
+    if (!priv->addrlen) {
+        virReportSystemError(conn, saved_errno,
+                             _("unable to connect to '%s:%s'"),
+                             host, port);
+        return -1;
+    }
 
-    return (0);
+    return 0;
 }
 
 
@@ -2750,14 +2757,18 @@ xenDaemonOpen(virConnectPtr conn,
         /*
          * try though http on port 8000
          */
-        ret = xenDaemonOpen_tcp(conn, "localhost", 8000);
+        ret = xenDaemonOpen_tcp(conn, "localhost", "8000");
         if (ret < 0)
             goto failed;
         ret = xend_detect_config_version(conn);
         if (ret == -1)
             goto failed;
     } else if (STRCASEEQ (conn->uri->scheme, "http")) {
-        ret = xenDaemonOpen_tcp(conn, conn->uri->server, conn->uri->port);
+        char *port;
+        if (virAsprintf(&port, "%d", conn->uri->port) == -1)
+            goto failed;
+        ret = xenDaemonOpen_tcp(conn, conn->uri->server, port);
+        VIR_FREE(port);
         if (ret < 0)
             goto failed;
         ret = xend_detect_config_version(conn);