If the hostname as returned by "gethostname" resolves
to "localhost" (as it does with the broken Fedora-12
installer), then live migration will fail because the
source will try to migrate to itself. Detect this
situation up-front and abort the live migration before
we do any real work.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 2 +-
src/util/util.c | 37 +++++++++++++++++++++++++++++++++++--
src/util/util.h | 1 +
4 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e3806cd..69ad686 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -568,6 +568,7 @@ virExecDaemonize;
virSetCloseExec;
virSetNonBlock;
virFormatMacAddr;
+virGetHostnameLocalhost;
virGetHostname;
virParseMacAddr;
virFileDeletePid;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0d8ec04..2123880 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7748,7 +7748,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
/* Get hostname */
- if ((hostname = virGetHostname(dconn)) == NULL)
+ if ((hostname = virGetHostnameLocalhost(0)) == NULL)
goto cleanup;
/* XXX this really should have been a properly well-formed
diff --git a/src/util/util.c b/src/util/util.c
index cdab300..72cc222 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2193,11 +2193,11 @@ char *virIndexToDiskName(int idx, const char *prefix)
#define AI_CANONIDN 0
#endif
-char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
+char *virGetHostnameLocalhost(int allow_localhost)
{
int r;
char hostname[HOST_NAME_MAX+1], *result;
- struct addrinfo hints, *info;
+ struct addrinfo hints, *info, *res;
r = gethostname (hostname, sizeof(hostname));
if (r == -1) {
@@ -2217,6 +2217,34 @@ char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
hostname, gai_strerror(r));
return NULL;
}
+
+ /* if we aren't allowing localhost, then we iterate through the
+ * list and make sure none of the IPv4 addresses are 127.0.0.1 and
+ * that none of the IPv6 addresses are ::1
+ */
+ if (!allow_localhost) {
+ res = info;
+ while (res) {
+ if (res->ai_family == AF_INET) {
+ if (htonl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr) ==
INADDR_LOOPBACK) {
+ virUtilError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("canonical hostname pointed to localhost, but
this is not allowed"));
+ freeaddrinfo(info);
+ return NULL;
+ }
+ }
+ else if (res->ai_family == AF_INET6) {
+ if (IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6
*)res->ai_addr)->sin6_addr)) {
+ virUtilError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("canonical hostname pointed to localhost, but
this is not allowed"));
+ freeaddrinfo(info);
+ return NULL;
+ }
+ }
+ res = res->ai_next;
+ }
+ }
+
if (info->ai_canonname == NULL) {
virUtilError(VIR_ERR_INTERNAL_ERROR,
"%s", _("could not determine canonical host
name"));
@@ -2233,6 +2261,11 @@ char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
return result;
}
+char *virGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ return virGetHostnameLocalhost(1);
+}
+
/* send signal to a single process */
int virKillProcess(pid_t pid, int sig)
{
diff --git a/src/util/util.h b/src/util/util.h
index 4207508..d024fe1 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -232,6 +232,7 @@ static inline int getuid (void) { return 0; }
static inline int getgid (void) { return 0; }
#endif
+char *virGetHostnameLocalhost(int allow_localhost);
char *virGetHostname(virConnectPtr conn);
int virKillProcess(pid_t pid, int sig);
--
1.6.6