On Thu, Oct 31, 2013 at 04:40:11PM +0100, Ján Tomko wrote: > Also try to bind on IPv6 to check if the port is occupied. > > https://bugzilla.redhat.com/show_bug.cgi?id=1025407 > --- > src/util/virportallocator.c | 45 ++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 38 insertions(+), 7 deletions(-) Have you tested this on a system where the IPv6 kernel module is not present, and on a system with IPv6 kmod is present, but no interfaces have any IPv6 addresses (not even link-local ones). I'm concerned this is going to trigger failures on IPv4 only hosts. > diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c > index 1922ea6..24b4bff 100644 > --- a/src/util/virportallocator.c > +++ b/src/util/virportallocator.c > @@ -99,21 +99,45 @@ virPortAllocatorPtr virPortAllocatorNew(const char *name, > } > > static int virPortAllocatorBindToPort(bool *used, > - unsigned short port) > + unsigned short port, > + int family) > { > - struct sockaddr_in addr = { > + struct sockaddr_in6 addr6 = { > + .sin6_family = AF_INET6, > + .sin6_port = htons(port), > + .sin6_addr = IN6ADDR_ANY_INIT, > + }; > + struct sockaddr_in addr4 = { > .sin_family = AF_INET, > .sin_port = htons(port), > .sin_addr.s_addr = htonl(INADDR_ANY) > }; > + struct sockaddr* addr; > + size_t addrlen; > + int v6only = 1; > int reuse = 1; > int ret = -1; > int fd = -1; > + bool ipv6 = false; > + > + if (family == AF_INET6) { > + addr = (struct sockaddr*)&addr6; > + addrlen = sizeof(addr6); > + ipv6 = true; > + } else if (family == AF_INET) { > + addr = (struct sockaddr*)&addr4; > + addrlen = sizeof(addr4); family can be AF_INET or AF_INET6 here... > + } else { > + virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown family %d"), family); > + return -1; > + } > > *used = false; > > fd = socket(PF_INET, SOCK_STREAM, 0); ...but you're hardcoding PF_INET here. I'm not sure it is valid to use an PF_INET socket with an AF_INET6 address in bind(). > if (fd < 0) { > + if (errno == EAFNOSUPPORT) > + return 0; > virReportSystemError(errno, "%s", _("Unable to open test socket")); > goto cleanup; > } > @@ -125,7 +149,14 @@ static int virPortAllocatorBindToPort(bool *used, > goto cleanup; > } > > - if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { > + if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only, > + sizeof(v6only)) < 0) { > + virReportSystemError(errno, "%s", > + _("Unable to set IPV6_V6ONLY flag")); > + goto cleanup; > + } > + > + if (bind(fd, addr, addrlen) < 0) { > if (errno == EADDRINUSE) { > *used = true; > ret = 0; > @@ -151,7 +182,7 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, > virObjectLock(pa); > > for (i = pa->start; i <= pa->end && !*port; i++) { > - bool used = false; > + bool used = false, v6used = false; > > if (virBitmapGetBit(pa->bitmap, > i - pa->start, &used) < 0) { > @@ -163,10 +194,10 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, > if (used) > continue; > > - if (virPortAllocatorBindToPort(&used, i) < 0) > + if (virPortAllocatorBindToPort(&v6used, i, AF_INET6) < 0 || > + virPortAllocatorBindToPort(&used, i, AF_INET) < 0) > goto cleanup; > - > - if (!used) { > + if (!used && !v6used) { > /* Add port to bitmap of reserved ports */ > if (virBitmapSetBit(pa->bitmap, > i - pa->start) < 0) { 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list