From 7b700763f5f5d749e46d0dbd2b5b0b2dd74efd6c Mon Sep 17 00:00:00 2001 From: Tao Wu Date: Mon, 19 Sep 2016 16:50:10 -0700 Subject: [PATCH] Fallback to IPv6 when IPv4 is not available in adb Test: manual - make sure it works in both IPv4/IPv6 env. BUG: 31537253 Change-Id: Ica492bff34a8c0441516a213d0e8b78fcdfd3282 Signed-off-by: Tao Wu --- adb/sysdeps.h | 5 ++- include/cutils/sockets.h | 1 + libcutils/socket_loopback_server_unix.c | 43 ++++++++++++++++++------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/adb/sysdeps.h b/adb/sysdeps.h index ded821426..ad9b9fd61 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -598,7 +598,10 @@ inline int network_loopback_client(int port, int type, std::string* error) { } inline int network_loopback_server(int port, int type, std::string* error) { - return _fd_set_error_str(socket_loopback_server(port, type), error); + int fd = socket_loopback_server(port, type); + if (fd < 0 && errno == EAFNOSUPPORT) + return _fd_set_error_str(socket_loopback_server6(port, type), error); + return _fd_set_error_str(fd, error); } inline int network_inaddr_any_server(int port, int type, std::string* error) { diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h index a93c8eaa4..b9c22c165 100644 --- a/include/cutils/sockets.h +++ b/include/cutils/sockets.h @@ -89,6 +89,7 @@ cutils_socket_t socket_network_client(const char* host, int port, int type); int socket_network_client_timeout(const char* host, int port, int type, int timeout, int* getaddrinfo_error); int socket_loopback_server(int port, int type); +int socket_loopback_server6(int port, int type); int socket_local_server(const char* name, int namespaceId, int type); int socket_local_server_bind(int s, const char* name, int namespaceId); int socket_local_client_connect(int fd, const char *name, int namespaceId, diff --git a/libcutils/socket_loopback_server_unix.c b/libcutils/socket_loopback_server_unix.c index b600e347e..7b92fd62d 100644 --- a/libcutils/socket_loopback_server_unix.c +++ b/libcutils/socket_loopback_server_unix.c @@ -31,24 +31,18 @@ #include -/* open listen() port on loopback interface */ -int socket_loopback_server(int port, int type) +static int _socket_loopback_server(int family, int type, struct sockaddr * addr, size_t size) { - struct sockaddr_in addr; int s, n; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket(AF_INET, type, 0); - if(s < 0) return -1; + s = socket(family, type, 0); + if(s < 0) + return -1; n = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n)); - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if(bind(s, addr, size) < 0) { close(s); return -1; } @@ -60,10 +54,35 @@ int socket_loopback_server(int port, int type) if (ret < 0) { close(s); - return -1; + return -1; } } return s; } +/* open listen() port on loopback IPv6 interface */ +int socket_loopback_server6(int port, int type) +{ + struct sockaddr_in6 addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port); + addr.sin6_addr = in6addr_loopback; + + return _socket_loopback_server(AF_INET6, type, (struct sockaddr *) &addr, sizeof(addr)); +} + +/* open listen() port on loopback interface */ +int socket_loopback_server(int port, int type) +{ + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + return _socket_loopback_server(AF_INET, type, (struct sockaddr *) &addr, sizeof(addr)); +}