diff --git a/libc/dns/gethnamaddr.c b/libc/dns/gethnamaddr.c index 0bd838e86..736858ff2 100644 --- a/libc/dns/gethnamaddr.c +++ b/libc/dns/gethnamaddr.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -532,30 +533,32 @@ android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned m return hp; } - -static FILE* android_open_proxy() -{ - int sock; - const int one = 1; - struct sockaddr_un proxy_addr; - - sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (sock < 0) { +__LIBC_HIDDEN__ FILE* android_open_proxy() { + const char* cache_mode = getenv("ANDROID_DNS_MODE"); + bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0); + if (!use_proxy) { return NULL; } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (s == -1) { + return NULL; + } + + const int one = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + struct sockaddr_un proxy_addr; memset(&proxy_addr, 0, sizeof(proxy_addr)); proxy_addr.sun_family = AF_UNIX; strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path)); - if (TEMP_FAILURE_RETRY(connect(sock, - (const struct sockaddr*) &proxy_addr, - sizeof(proxy_addr))) != 0) { - close(sock); + + if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) { + close(s); return NULL; } - return fdopen(sock, "r+"); + return fdopen(s, "r+"); } static struct hostent * @@ -565,8 +568,8 @@ android_read_hostent(FILE* proxy) char buf[4]; if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL; - /* This is reading serialized data from system/netd/server/DnsProxyListener.cpp - * and changes here need to be matched there */ + // This is reading serialized data from system/netd/server/DnsProxyListener.cpp + // and changes here need to be matched there. int result_code = strtol(buf, NULL, 10); if (result_code != DnsProxyQueryResult) { fread(&size, 1, sizeof(size), proxy); @@ -748,80 +751,39 @@ gethostbyname_internal_real(const char *name, int af, res_state res) static struct hostent * gethostbyname_internal(const char *name, int af, res_state res, unsigned netid, unsigned mark) { - const char *cache_mode = getenv("ANDROID_DNS_MODE"); - FILE* proxy = NULL; - struct hostent *result = NULL; - - if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) { + FILE* proxy = android_open_proxy(); + if (proxy == NULL) { + // Either we're not supposed to be using the proxy or the proxy is unavailable. res_setnetid(res, netid); res_setmark(res, mark); return gethostbyname_internal_real(name, af, res); } - proxy = android_open_proxy(); - if (proxy == NULL) goto exit; - netid = __netdClientDispatch.netIdForResolv(netid); - /* This is writing to system/netd/server/DnsProxyListener.cpp and changes - * here need to be matched there */ + // This is writing to system/netd/server/DnsProxyListener.cpp and changes + // here need to be matched there. if (fprintf(proxy, "gethostbyname %u %s %d", netid, name == NULL ? "^" : name, af) < 0) { - goto exit; + fclose(proxy); + return NULL; } if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { - goto exit; - } - - result = android_read_hostent(proxy); - -exit: - if (proxy != NULL) { fclose(proxy); + return NULL; } + + struct hostent* result = android_read_hostent(proxy); + fclose(proxy); return result; } -struct hostent * -android_gethostbyaddrfornet_proxy(const void *addr, - socklen_t len, int af, unsigned netid) -{ - struct hostent *result = NULL; - FILE* proxy = android_open_proxy(); - - if (proxy == NULL) goto exit; - - char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6 - const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf)); - if (addrStr == NULL) goto exit; - - netid = __netdClientDispatch.netIdForResolv(netid); - - if (fprintf(proxy, "gethostbyaddr %s %d %d %u", - addrStr, len, af, netid) < 0) { - goto exit; - } - - if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { - goto exit; - } - - result = android_read_hostent(proxy); -exit: - if (proxy != NULL) { - fclose(proxy); - } - return result; -} - -struct hostent * -android_gethostbyaddrfornet_real(const void *addr, - socklen_t len, int af, unsigned netid, unsigned mark) -{ +static struct hostent * +android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) { const u_char *uaddr = (const u_char *)addr; socklen_t size; struct hostent *hp; @@ -874,16 +836,43 @@ android_gethostbyaddrfornet_real(const void *addr, return hp; } +__LIBC_HIDDEN__ struct hostent* +android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af, unsigned netid, unsigned mark) { + FILE* proxy = android_open_proxy(); + if (proxy == NULL) { + // Either we're not supposed to be using the proxy or the proxy is unavailable. + return android_gethostbyaddrfornet_real(addr,len, af, netid, mark); + } + + char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6 + const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf)); + if (addrStr == NULL) { + fclose(proxy); + return NULL; + } + + netid = __netdClientDispatch.netIdForResolv(netid); + + if (fprintf(proxy, "gethostbyaddr %s %d %d %u", + addrStr, len, af, netid) < 0) { + fclose(proxy); + return NULL; + } + + if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { + fclose(proxy); + return NULL; + } + + struct hostent *result = android_read_hostent(proxy); + fclose(proxy); + return result; +} + struct hostent * android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) { - const char *cache_mode = getenv("ANDROID_DNS_MODE"); - - if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) { - return android_gethostbyaddrfornet_proxy(addr, len, af, netid); - } else { - return android_gethostbyaddrfornet_real(addr,len, af, netid, mark); - } + return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark); } struct hostent * diff --git a/libc/dns/include/resolv_netid.h b/libc/dns/include/resolv_netid.h index e5521b809..1d0f8691c 100644 --- a/libc/dns/include/resolv_netid.h +++ b/libc/dns/include/resolv_netid.h @@ -34,6 +34,7 @@ */ #include #include +#include /* * Passing NETID_UNSET as the netId causes system/netd/server/DnsProxyListener.cpp to @@ -68,9 +69,9 @@ extern void _resolv_flush_cache_for_net(unsigned netid) __used_in_netd; extern void _resolv_delete_cache_for_net(unsigned netid) __used_in_netd; /* Internal use only. */ -struct hostent *android_gethostbyaddrfornet_proxy(const void *, socklen_t, int , unsigned); -int android_getnameinfofornet(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, - int, unsigned, unsigned); +struct hostent *android_gethostbyaddrfornet_proxy(const void *, socklen_t, int , unsigned, unsigned) __LIBC_HIDDEN__; +int android_getnameinfofornet(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, unsigned, unsigned) __LIBC_HIDDEN__; +FILE* android_open_proxy(void) __LIBC_HIDDEN__; /* delete the cache associated with a certain network */ extern void _resolv_delete_cache_for_net(unsigned netid); diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c index 1ebd222fe..f0d522a02 100644 --- a/libc/dns/net/getaddrinfo.c +++ b/libc/dns/net/getaddrinfo.c @@ -423,10 +423,6 @@ android_getaddrinfo_proxy( const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res, unsigned netid) { - int sock; - const int one = 1; - struct sockaddr_un proxy_addr; - FILE* proxy = NULL; int success = 0; // Clear this at start, as we use its non-NULLness later (in the @@ -442,36 +438,14 @@ android_getaddrinfo_proxy( return EAI_NODATA; } - sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (sock < 0) { - return EAI_NODATA; - } - - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - memset(&proxy_addr, 0, sizeof(proxy_addr)); - proxy_addr.sun_family = AF_UNIX; - strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", - sizeof(proxy_addr.sun_path)); - if (TEMP_FAILURE_RETRY(connect(sock, - (const struct sockaddr*) &proxy_addr, - sizeof(proxy_addr))) != 0) { - close(sock); - return EAI_NODATA; + FILE* proxy = android_open_proxy(); + if (proxy == NULL) { + return EAI_SYSTEM; } netid = __netdClientDispatch.netIdForResolv(netid); // Send the request. - proxy = fdopen(sock, "r+"); - if (proxy == NULL) { - // Failed to map sock to FILE*. Check errno for the cause. - // @sonymobile.com saw failures in automated testing, but - // couldn't reproduce it for debugging. - // Fail with EAI_SYSTEM and let callers handle the failure. - close(sock); - return EAI_SYSTEM; - } - if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %u", hostname == NULL ? "^" : hostname, servname == NULL ? "^" : servname, @@ -618,7 +592,6 @@ android_getaddrinfofornet(const char *hostname, const char *servname, struct addrinfo ai0; struct addrinfo *pai; const struct explore *ex; - const char* cache_mode = getenv("ANDROID_DNS_MODE"); /* hostname is allowed to be NULL */ /* servname is allowed to be NULL */ @@ -753,13 +726,12 @@ android_getaddrinfofornet(const char *hostname, const char *servname, if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NONAME); - /* - * BEGIN ANDROID CHANGES; proxying to the cache - */ - if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) { - // we're not the proxy - pass the request to them - return android_getaddrinfo_proxy(hostname, servname, hints, res, netid); +#if defined(__ANDROID__) + int gai_error = android_getaddrinfo_proxy(hostname, servname, hints, res, netid); + if (gai_error != EAI_SYSTEM) { + return gai_error; } +#endif /* * hostname as alphabetical name. diff --git a/libc/dns/net/getnameinfo.c b/libc/dns/net/getnameinfo.c index b9c0280dd..893e982d1 100644 --- a/libc/dns/net/getnameinfo.c +++ b/libc/dns/net/getnameinfo.c @@ -303,7 +303,7 @@ getnameinfo_inet(const struct sockaddr* sa, socklen_t salen, break; } } else { - hp = android_gethostbyaddrfornet_proxy(addr, afd->a_addrlen, afd->a_af, netid); + hp = android_gethostbyaddrfornet_proxy(addr, afd->a_addrlen, afd->a_af, netid, mark); if (hp) { #if 0 /*