Merge "Clean up DNS proxying."
This commit is contained in:
commit
e7b8bc4e29
@ -69,6 +69,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
@ -532,30 +533,32 @@ android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned m
|
|||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__LIBC_HIDDEN__ FILE* android_open_proxy() {
|
||||||
static FILE* android_open_proxy()
|
const char* cache_mode = getenv("ANDROID_DNS_MODE");
|
||||||
{
|
bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
|
||||||
int sock;
|
if (!use_proxy) {
|
||||||
const int one = 1;
|
|
||||||
struct sockaddr_un proxy_addr;
|
|
||||||
|
|
||||||
sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
|
||||||
if (sock < 0) {
|
|
||||||
return NULL;
|
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));
|
memset(&proxy_addr, 0, sizeof(proxy_addr));
|
||||||
proxy_addr.sun_family = AF_UNIX;
|
proxy_addr.sun_family = AF_UNIX;
|
||||||
strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
|
strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
|
||||||
if (TEMP_FAILURE_RETRY(connect(sock,
|
|
||||||
(const struct sockaddr*) &proxy_addr,
|
if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
|
||||||
sizeof(proxy_addr))) != 0) {
|
close(s);
|
||||||
close(sock);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fdopen(sock, "r+");
|
return fdopen(s, "r+");
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hostent *
|
static struct hostent *
|
||||||
@ -565,8 +568,8 @@ android_read_hostent(FILE* proxy)
|
|||||||
char buf[4];
|
char buf[4];
|
||||||
if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
|
if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
|
||||||
|
|
||||||
/* This is reading serialized data from system/netd/server/DnsProxyListener.cpp
|
// This is reading serialized data from system/netd/server/DnsProxyListener.cpp
|
||||||
* and changes here need to be matched there */
|
// and changes here need to be matched there.
|
||||||
int result_code = strtol(buf, NULL, 10);
|
int result_code = strtol(buf, NULL, 10);
|
||||||
if (result_code != DnsProxyQueryResult) {
|
if (result_code != DnsProxyQueryResult) {
|
||||||
fread(&size, 1, sizeof(size), proxy);
|
fread(&size, 1, sizeof(size), proxy);
|
||||||
@ -748,80 +751,39 @@ gethostbyname_internal_real(const char *name, int af, res_state res)
|
|||||||
static struct hostent *
|
static struct hostent *
|
||||||
gethostbyname_internal(const char *name, int af, res_state res, unsigned netid, unsigned mark)
|
gethostbyname_internal(const char *name, int af, res_state res, unsigned netid, unsigned mark)
|
||||||
{
|
{
|
||||||
const char *cache_mode = getenv("ANDROID_DNS_MODE");
|
FILE* proxy = android_open_proxy();
|
||||||
FILE* proxy = NULL;
|
if (proxy == NULL) {
|
||||||
struct hostent *result = NULL;
|
// Either we're not supposed to be using the proxy or the proxy is unavailable.
|
||||||
|
|
||||||
if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
|
|
||||||
res_setnetid(res, netid);
|
res_setnetid(res, netid);
|
||||||
res_setmark(res, mark);
|
res_setmark(res, mark);
|
||||||
return gethostbyname_internal_real(name, af, res);
|
return gethostbyname_internal_real(name, af, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy = android_open_proxy();
|
|
||||||
if (proxy == NULL) goto exit;
|
|
||||||
|
|
||||||
netid = __netdClientDispatch.netIdForResolv(netid);
|
netid = __netdClientDispatch.netIdForResolv(netid);
|
||||||
|
|
||||||
/* This is writing to system/netd/server/DnsProxyListener.cpp and changes
|
// This is writing to system/netd/server/DnsProxyListener.cpp and changes
|
||||||
* here need to be matched there */
|
// here need to be matched there.
|
||||||
if (fprintf(proxy, "gethostbyname %u %s %d",
|
if (fprintf(proxy, "gethostbyname %u %s %d",
|
||||||
netid,
|
netid,
|
||||||
name == NULL ? "^" : name,
|
name == NULL ? "^" : name,
|
||||||
af) < 0) {
|
af) < 0) {
|
||||||
goto exit;
|
fclose(proxy);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
|
if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = android_read_hostent(proxy);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
if (proxy != NULL) {
|
|
||||||
fclose(proxy);
|
fclose(proxy);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct hostent* result = android_read_hostent(proxy);
|
||||||
|
fclose(proxy);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hostent *
|
static struct hostent *
|
||||||
android_gethostbyaddrfornet_proxy(const void *addr,
|
android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) {
|
||||||
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)
|
|
||||||
{
|
|
||||||
const u_char *uaddr = (const u_char *)addr;
|
const u_char *uaddr = (const u_char *)addr;
|
||||||
socklen_t size;
|
socklen_t size;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
@ -874,16 +836,43 @@ android_gethostbyaddrfornet_real(const void *addr,
|
|||||||
return hp;
|
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 *
|
struct hostent *
|
||||||
android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
|
android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
|
||||||
{
|
{
|
||||||
const char *cache_mode = getenv("ANDROID_DNS_MODE");
|
return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hostent *
|
struct hostent *
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Passing NETID_UNSET as the netId causes system/netd/server/DnsProxyListener.cpp to
|
* 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;
|
extern void _resolv_delete_cache_for_net(unsigned netid) __used_in_netd;
|
||||||
|
|
||||||
/* Internal use only. */
|
/* Internal use only. */
|
||||||
struct hostent *android_gethostbyaddrfornet_proxy(const void *, socklen_t, int , 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 android_getnameinfofornet(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, unsigned, unsigned) __LIBC_HIDDEN__;
|
||||||
int, unsigned, unsigned);
|
FILE* android_open_proxy(void) __LIBC_HIDDEN__;
|
||||||
|
|
||||||
/* delete the cache associated with a certain network */
|
/* delete the cache associated with a certain network */
|
||||||
extern void _resolv_delete_cache_for_net(unsigned netid);
|
extern void _resolv_delete_cache_for_net(unsigned netid);
|
||||||
|
@ -423,10 +423,6 @@ android_getaddrinfo_proxy(
|
|||||||
const char *hostname, const char *servname,
|
const char *hostname, const char *servname,
|
||||||
const struct addrinfo *hints, struct addrinfo **res, unsigned netid)
|
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;
|
int success = 0;
|
||||||
|
|
||||||
// Clear this at start, as we use its non-NULLness later (in the
|
// Clear this at start, as we use its non-NULLness later (in the
|
||||||
@ -442,36 +438,14 @@ android_getaddrinfo_proxy(
|
|||||||
return EAI_NODATA;
|
return EAI_NODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
FILE* proxy = android_open_proxy();
|
||||||
if (sock < 0) {
|
if (proxy == NULL) {
|
||||||
return EAI_NODATA;
|
return EAI_SYSTEM;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
netid = __netdClientDispatch.netIdForResolv(netid);
|
netid = __netdClientDispatch.netIdForResolv(netid);
|
||||||
|
|
||||||
// Send the request.
|
// 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",
|
if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %u",
|
||||||
hostname == NULL ? "^" : hostname,
|
hostname == NULL ? "^" : hostname,
|
||||||
servname == NULL ? "^" : servname,
|
servname == NULL ? "^" : servname,
|
||||||
@ -618,7 +592,6 @@ android_getaddrinfofornet(const char *hostname, const char *servname,
|
|||||||
struct addrinfo ai0;
|
struct addrinfo ai0;
|
||||||
struct addrinfo *pai;
|
struct addrinfo *pai;
|
||||||
const struct explore *ex;
|
const struct explore *ex;
|
||||||
const char* cache_mode = getenv("ANDROID_DNS_MODE");
|
|
||||||
|
|
||||||
/* hostname is allowed to be NULL */
|
/* hostname is allowed to be NULL */
|
||||||
/* servname 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)
|
if (pai->ai_flags & AI_NUMERICHOST)
|
||||||
ERR(EAI_NONAME);
|
ERR(EAI_NONAME);
|
||||||
|
|
||||||
/*
|
#if defined(__ANDROID__)
|
||||||
* BEGIN ANDROID CHANGES; proxying to the cache
|
int gai_error = android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
|
||||||
*/
|
if (gai_error != EAI_SYSTEM) {
|
||||||
if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) {
|
return gai_error;
|
||||||
// we're not the proxy - pass the request to them
|
|
||||||
return android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hostname as alphabetical name.
|
* hostname as alphabetical name.
|
||||||
|
@ -303,7 +303,7 @@ getnameinfo_inet(const struct sockaddr* sa, socklen_t salen,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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 (hp) {
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user