summaryrefslogtreecommitdiff
path: root/libc/dns/net/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/dns/net/getaddrinfo.c')
-rw-r--r--libc/dns/net/getaddrinfo.c121
1 files changed, 58 insertions, 63 deletions
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index 2612d6a4d..c73c08521 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -324,7 +324,11 @@ freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *next;
- assert(ai != NULL);
+#if __ANDROID__
+ if (ai == NULL) return;
+#else
+ _DIAGASSERT(ai != NULL);
+#endif
do {
next = ai->ai_next;
@@ -408,16 +412,21 @@ _have_ipv4(unsigned mark) {
return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
}
+bool readBE32(FILE* fp, int32_t* result) {
+ int32_t tmp;
+ if (fread(&tmp, sizeof(tmp), 1, fp) != 1) {
+ return false;
+ }
+ *result = ntohl(tmp);
+ return true;
+}
+
// Returns 0 on success, else returns on error.
static int
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
@@ -433,27 +442,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 (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %u",
hostname == NULL ? "^" : hostname,
servname == NULL ? "^" : servname,
@@ -486,61 +482,62 @@ android_getaddrinfo_proxy(
struct addrinfo* ai = NULL;
struct addrinfo** nextres = res;
while (1) {
- uint32_t addrinfo_len;
- if (fread(&addrinfo_len, sizeof(addrinfo_len),
- 1, proxy) != 1) {
+ int32_t have_more;
+ if (!readBE32(proxy, &have_more)) {
break;
}
- addrinfo_len = ntohl(addrinfo_len);
- if (addrinfo_len == 0) {
+ if (have_more == 0) {
success = 1;
break;
}
- if (addrinfo_len < sizeof(struct addrinfo)) {
- break;
- }
- struct addrinfo* ai = calloc(1, addrinfo_len +
- sizeof(struct sockaddr_storage));
+ struct addrinfo* ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
if (ai == NULL) {
break;
}
-
- if (fread(ai, addrinfo_len, 1, proxy) != 1) {
- // Error; fall through.
+ ai->ai_addr = (struct sockaddr*)(ai + 1);
+
+ // struct addrinfo {
+ // int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+ // int ai_family; /* PF_xxx */
+ // int ai_socktype; /* SOCK_xxx */
+ // int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ // socklen_t ai_addrlen; /* length of ai_addr */
+ // char *ai_canonname; /* canonical name for hostname */
+ // struct sockaddr *ai_addr; /* binary address */
+ // struct addrinfo *ai_next; /* next structure in linked list */
+ // };
+
+ // Read the struct piece by piece because we might be a 32-bit process
+ // talking to a 64-bit netd.
+ int32_t addr_len;
+ bool success =
+ readBE32(proxy, &ai->ai_flags) &&
+ readBE32(proxy, &ai->ai_family) &&
+ readBE32(proxy, &ai->ai_socktype) &&
+ readBE32(proxy, &ai->ai_protocol) &&
+ readBE32(proxy, &addr_len);
+ if (!success) {
break;
}
- // Zero out the pointer fields we copied which aren't
- // valid in this address space.
- ai->ai_addr = NULL;
- ai->ai_canonname = NULL;
- ai->ai_next = NULL;
-
- // struct sockaddr
- uint32_t addr_len;
- if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) {
- break;
- }
- addr_len = ntohl(addr_len);
+ // Set ai_addrlen and read the ai_addr data.
+ ai->ai_addrlen = addr_len;
if (addr_len != 0) {
- if (addr_len > sizeof(struct sockaddr_storage)) {
+ if ((size_t) addr_len > sizeof(struct sockaddr_storage)) {
// Bogus; too big.
break;
}
- struct sockaddr* addr = (struct sockaddr*)(ai + 1);
- if (fread(addr, addr_len, 1, proxy) != 1) {
+ if (fread(ai->ai_addr, addr_len, 1, proxy) != 1) {
break;
}
- ai->ai_addr = addr;
}
- // cannonname
- uint32_t name_len;
- if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
+ // The string for ai_cannonname.
+ int32_t name_len;
+ if (!readBE32(proxy, &name_len)) {
break;
}
- name_len = ntohl(name_len);
if (name_len != 0) {
ai->ai_canonname = (char*) malloc(name_len);
if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) {
@@ -599,7 +596,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 */
@@ -734,13 +730,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.
@@ -2017,7 +2012,7 @@ _sethtent(FILE **hostf)
{
if (!*hostf)
- *hostf = fopen(_PATH_HOSTS, "r" );
+ *hostf = fopen(_PATH_HOSTS, "re");
else
rewind(*hostf);
}
@@ -2046,7 +2041,7 @@ _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
assert(name != NULL);
assert(pai != NULL);
- if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" )))
+ if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re")))
return (NULL);
again:
if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))