On Tue, Oct 01, 2013 at 11:01:37AM +0200, Ján Tomko wrote: > 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)); IMHO you could write this code without needing to have any upfront check for whether IPv6 is enabled. Set IPV6_V6ONLY == 1. Then unconditionally try to bind separately on IPv4, and IPv6, and catch the error you'd get back if either IPv4 or IPv6 were disabled on the host. Regards, 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