io: stronger check for support for IPv4/6
Instead of just checking for bind(), also check whether getaddrinfo can resolve IPv6 addresses. This catches failure when travis runs QEMU builds inside minimal docker containers Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
		
							parent
							
								
									618a5a8bc5
								
							
						
					
					
						commit
						cfd47a71df
					
				@ -23,44 +23,72 @@
 | 
				
			|||||||
#include "io/channel-util.h"
 | 
					#include "io/channel-util.h"
 | 
				
			||||||
#include "io-channel-helpers.h"
 | 
					#include "io-channel-helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int check_bind(struct sockaddr *sa, socklen_t salen, bool *has_proto)
 | 
					#ifndef AI_ADDRCONFIG
 | 
				
			||||||
{
 | 
					# define AI_ADDRCONFIG 0
 | 
				
			||||||
    int fd;
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef AI_V4MAPPED
 | 
				
			||||||
 | 
					# define AI_V4MAPPED 0
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef EAI_ADDRFAMILY
 | 
				
			||||||
 | 
					# define EAI_ADDRFAMILY 0
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fd = socket(sa->sa_family, SOCK_STREAM, 0);
 | 
					static int check_bind(const char *hostname, bool *has_proto)
 | 
				
			||||||
    if (fd < 0) {
 | 
					{
 | 
				
			||||||
        return -1;
 | 
					    int fd = -1;
 | 
				
			||||||
 | 
					    struct addrinfo ai, *res = NULL;
 | 
				
			||||||
 | 
					    int rc;
 | 
				
			||||||
 | 
					    int ret = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(&ai, 0, sizeof(ai));
 | 
				
			||||||
 | 
					    ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG;
 | 
				
			||||||
 | 
					    ai.ai_family = AF_UNSPEC;
 | 
				
			||||||
 | 
					    ai.ai_socktype = SOCK_STREAM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* lookup */
 | 
				
			||||||
 | 
					    rc = getaddrinfo(hostname, NULL, &ai, &res);
 | 
				
			||||||
 | 
					    if (rc != 0) {
 | 
				
			||||||
 | 
					        if (rc == EAI_ADDRFAMILY ||
 | 
				
			||||||
 | 
					            rc == EAI_FAMILY) {
 | 
				
			||||||
 | 
					            *has_proto = false;
 | 
				
			||||||
 | 
					            goto done;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        goto cleanup;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bind(fd, sa, salen) < 0) {
 | 
					    fd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 | 
				
			||||||
        close(fd);
 | 
					    if (fd < 0) {
 | 
				
			||||||
 | 
					        goto cleanup;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
 | 
				
			||||||
        if (errno == EADDRNOTAVAIL) {
 | 
					        if (errno == EADDRNOTAVAIL) {
 | 
				
			||||||
            *has_proto = false;
 | 
					            *has_proto = false;
 | 
				
			||||||
            return 0;
 | 
					            goto done;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return -1;
 | 
					        goto cleanup;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    close(fd);
 | 
					 | 
				
			||||||
    *has_proto = true;
 | 
					    *has_proto = true;
 | 
				
			||||||
    return 0;
 | 
					 done:
 | 
				
			||||||
 | 
					    ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 cleanup:
 | 
				
			||||||
 | 
					    if (fd != -1) {
 | 
				
			||||||
 | 
					        close(fd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (res) {
 | 
				
			||||||
 | 
					        freeaddrinfo(res);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int check_protocol_support(bool *has_ipv4, bool *has_ipv6)
 | 
					static int check_protocol_support(bool *has_ipv4, bool *has_ipv6)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct sockaddr_in sin = {
 | 
					    if (check_bind("127.0.0.1", has_ipv4) < 0) {
 | 
				
			||||||
        .sin_family = AF_INET,
 | 
					 | 
				
			||||||
        .sin_addr = { .s_addr = htonl(INADDR_LOOPBACK) },
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    struct sockaddr_in6 sin6 = {
 | 
					 | 
				
			||||||
        .sin6_family = AF_INET6,
 | 
					 | 
				
			||||||
        .sin6_addr = IN6ADDR_LOOPBACK_INIT,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (check_bind((struct sockaddr *)&sin, sizeof(sin), has_ipv4) < 0) {
 | 
					 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (check_bind((struct sockaddr *)&sin6, sizeof(sin6), has_ipv6) < 0) {
 | 
					    if (check_bind("::1", has_ipv6) < 0) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user