If IPv6 is enabled on the host, bind to :: with IPV6_V6ONLY disabled to check for ports available on both IPv6 and IPv4. --- src/util/virportallocator.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c index 5b7ad41..246f6cd 100644 --- a/src/util/virportallocator.c +++ b/src/util/virportallocator.c @@ -99,14 +99,25 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, int ret = -1; size_t i; int fd = -1; + bool ipv6 = virHostHasIPv6(); *port = 0; virObjectLock(pa); for (i = pa->start; i <= pa->end && !*port; i++) { - int reuse = 1; - struct sockaddr_in addr; + int reuse = 1, v6only = 0; + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(i), + .sin_addr.s_addr = htonl(INADDR_ANY) + }; + struct sockaddr_in6 addr6 = { + .sin6_family = AF_INET6, + .sin6_port = htons(i), + .sin6_addr = IN6ADDR_ANY_INIT + }; bool used = false; + int rc; if (virBitmapGetBit(pa->bitmap, i - pa->start, &used) < 0) { @@ -118,10 +129,7 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, if (used) continue; - addr.sin_family = AF_INET; - addr.sin_port = htons(i); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - fd = socket(PF_INET, SOCK_STREAM, 0); + fd = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_STREAM, 0); if (fd < 0) { virReportSystemError(errno, "%s", _("Unable to open test socket")); @@ -134,7 +142,19 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, 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 unset socket IPV6_V6ONLY flag")); + goto cleanup; + } + + if (ipv6) + rc = bind(fd, (struct sockaddr*)&addr6, sizeof(addr6)); + else + rc = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); + + if (rc < 0) { if (errno != EADDRINUSE) { virReportSystemError(errno, _("Unable to bind to port %zu"), i); -- 1.8.1.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list