diff options
Diffstat (limited to 'libc/dns/net/getaddrinfo.c')
-rw-r--r-- | libc/dns/net/getaddrinfo.c | 121 |
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))) |