mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 06:50:22 +03:00
rpc: ensure all sockets bind to same port when service is NULL
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. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
b632e00ffb
commit
f8b3905edf
@ -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 (addr.data.sa.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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user