
On 10/09/2013 03:32 PM, Michal Privoznik wrote:
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_driver.c | 26 +++++++---- src/qemu/qemu_migration.c | 113 +++++++++++++++++++++++++++++++--------------- src/qemu/qemu_migration.h | 13 ++++-- 3 files changed, 103 insertions(+), 49 deletions(-)
@@ -2260,31 +2254,66 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, if (VIR_STRDUP(migrateFrom, "stdio") < 0) goto cleanup; } else { + virSocketAddr listenAddressSocket; + bool encloseAddress = false; + bool hostIPv6Capable = false; + bool qemuIPv6Capable = false; virQEMUCapsPtr qemuCaps = NULL; struct addrinfo *info = NULL; struct addrinfo hints = { .ai_flags = AI_ADDRCONFIG, .ai_socktype = SOCK_STREAM };
+ if (getaddrinfo("::", NULL, &hints, &info) == 0) { + freeaddrinfo(info); + hostIPv6Capable = true; + } if (!(qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, (*def)->emulator))) goto cleanup;
- /* Listen on :: instead of 0.0.0.0 if QEMU understands it - * and there is at least one IPv6 address configured - */ - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION) && - getaddrinfo("::", NULL, &hints, &info) == 0) { - freeaddrinfo(info); - listenAddr = "[::]"; + qemuIPv6Capable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION); + virObjectUnref(qemuCaps); + + if (listenAddress) { + if (virSocketAddrIsNumeric(listenAddress)) { + /* listenAddress is numeric IPv4 or IPv6 */ + if (virSocketAddrParse(&listenAddressSocket, listenAddress, AF_UNSPEC) < 0) + goto cleanup; + + /* address parsed successfully */ + if (VIR_SOCKET_ADDR_IS_FAMILY(&listenAddressSocket, AF_INET6)) { + if (!qemuIPv6Capable) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("qemu isn't capable of IPv6")); + goto cleanup; + } + if (!hostIPv6Capable) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("host isn't capable of IPv6")); + goto cleanup; + } + } + + /* IPv6 address must be enclosed in angle brackets on the cmd line */ + encloseAddress = true;
This sets it for IPv4 as well. Also s/ angle// (and maybe 'escape' would be better than 'enclose')
+ } else { + /* listenAddress is a hostname */ + } } else { - listenAddr = "0.0.0.0"; + /* Listen on :: instead of 0.0.0.0 if QEMU understands it + * and there is at least one IPv6 address configured + */ + listenAddress = qemuIPv6Capable && hostIPv6Capable ? + encloseAddress = true, "::" : "0.0.0.0"; } - virObjectUnref(qemuCaps);
- /* QEMU will be started with -incoming [::]:port - * or -incoming 0.0.0.0:port + /* QEMU will be started with -incoming [<IPv6 addr>]:port, + * -incoming <IPv4 addr>:port or -incoming <hostname>:port */ - if (virAsprintf(&migrateFrom, "tcp:%s:%d", listenAddr, port) < 0) + if ((encloseAddress && + virAsprintf(&migrateFrom, "tcp:[%s]:%d", listenAddress, port) < 0) || + (!encloseAddress && + virAsprintf(&migrateFrom, "tcp:%s:%d", listenAddress, port) < 0)) goto cleanup; }
ACK with that fixed