When the service passed to getaddrinfo is NULL the kernel will choose a free port to bind to. In a dual stack though we will get separate sockets for IPv4 and IPv6 and we need them to bind to the same port number. Thus once the kerel has auto-selected a port for the first socket, we must disable auto-select for subsequent IP sockets and force reuse of the first port. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/rpc/virnetsocket.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 254f39c4ec..fc13b1654a 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -311,6 +311,7 @@ int virNetSocketNewListenTCP(const char *nodename, int socketErrno = 0; int bindErrno = 0; virSocketAddr tmp_addr; + int port = 0; *retsocks = NULL; *nretsocks = 0; @@ -379,7 +380,24 @@ int virNetSocketNewListenTCP(const char *nodename, } #endif - if (bind(fd, runp->ai_addr, runp->ai_addrlen) < 0) { + addr.len = runp->ai_addrlen; + memcpy(&addr.data.sa, runp->ai_addr, runp->ai_addrlen); + + /* When service is NULL, we let the kernel auto-select the + * port. Once we've selected a port for one IP protocol + * though, we want to ensure we pick the same port for the + * other IP protocol + */ + if (port != 0 && service == NULL) { + if (runp->ai_addr->sa_family == AF_INET) { + addr.data.inet4.sin_port = port; + } else if (addr.data.sa.sa_family == AF_INET6) { + addr.data.inet6.sin6_port = port; + } + VIR_DEBUG("Used saved port %d", port); + } + + if (bind(fd, &addr.data.sa, addr.len) < 0) { if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { virReportSystemError(errno, "%s", _("Unable to bind to port")); goto error; @@ -396,6 +414,14 @@ int virNetSocketNewListenTCP(const char *nodename, goto error; } + if (port == 0 && service == NULL) { + if (addr.data.sa.sa_family == AF_INET) + port = addr.data.inet4.sin_port; + else if (addr.data.sa.sa_family == AF_INET6) + port = addr.data.inet6.sin6_port; + VIR_DEBUG("Saved port %d", port); + } + VIR_DEBUG("%p f=%d f=%d", &addr, runp->ai_family, addr.data.sa.sa_family); if (VIR_EXPAND_N(socks, nsocks, 1) < 0) -- 2.21.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list