
On Wed, Oct 09, 2013 at 01:02:14PM +0200, Michal Privoznik wrote:
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_driver.c | 26 +++++++++---- src/qemu/qemu_migration.c | 98 +++++++++++++++++++++++++++++++++-------------- src/qemu/qemu_migration.h | 13 ++++--- 3 files changed, 96 insertions(+), 41 deletions(-) @@ -2260,31 +2260,61 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, if (VIR_STRDUP(migrateFrom, "stdio") < 0) goto cleanup; } else { + virSocketAddr listenAddressSocket; + bool hostIPv6Capable = false; + bool qemuIPv6Capable = false; virQEMUCapsPtr qemuCaps = NULL; struct addrinfo *info = NULL; struct addrinfo hints = { .ai_flags = AI_ADDRCONFIG, - .ai_socktype = SOCK_STREAM }; + .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 && + virSocketAddrParse(&listenAddressSocket, listenAddress, AF_UNSPEC) > 0) { + /* address parsed successfully */ + + if (virSocketAddrIsWildcard(&listenAddressSocket)) { + /* user wants us to listen on 0.0.0.0 or :: */ + + 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; + } + listenAddress = "[::]"; + } + } } else { - listenAddr = "0.0.0.0"; + /* Don't error out, the @listenAddress may be a hostname */ + if (!listenAddress) { + /* Listen on :: instead of 0.0.0.0 if QEMU understands it + * and there is at least one IPv6 address configured + */ + listenAddress = qemuIPv6Capable && hostIPv6Capable ? + "[::]" : "0.0.0.0"; + } }
I think this if/else would be clearer as if (listenAddress) { if (virSocketAddrParse(&listenAddressSocket, listenAddress, AF_UNSPEC) < 0) { virResetLastError(); ... } else { .... } } else { listenAddress = qemuIPv6Capable && hostIPv6Capable ? "[::]" : "0.0.0.0"; } Though this still means we'll be polluting the logs with the errors if this is a hostname. So perhaps we need a method virSocketAddrIsNumeric(const char *addR) so we can skip the parse stage entirely without errors, if it is a hostname. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|