bionic: Replace iface with opaque netid in resolver.

Replace iface cache key with netid.

Replace _mark with netid.

Mark sockets used to test IPv4/IPv6 support as well as sockets
used to determine source address for rfc6724 sort.

Remove pid/uid mappings (functionality moved to system/netd).

Do not create resolv_cache when it does not exist, but rather only
when DNS configuration is supplied.

Clean up unused functions.

Change-Id: I9ccfda2902cc0943e87c9bc346ad9a2578accdab
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index 7da69f9..4c120d9 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -92,6 +92,8 @@
 #include <ctype.h>
 #include <errno.h>
 #include <netdb.h>
+#include "resolv_cache.h"
+#include "resolv_netid.h"
 #include "resolv_private.h"
 #include <stdbool.h>
 #include <stddef.h>
@@ -215,7 +217,7 @@
 
 static int str2number(const char *);
 static int explore_fqdn(const struct addrinfo *, const char *,
-	const char *, struct addrinfo **, const char *iface, int mark);
+	const char *, struct addrinfo **, unsigned netid, unsigned mark);
 static int explore_null(const struct addrinfo *,
 	const char *, struct addrinfo **);
 static int explore_numeric(const struct addrinfo *, const char *,
@@ -358,10 +360,12 @@
  * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
  */
 static int
-_test_connect(int pf, struct sockaddr *addr, size_t addrlen) {
+_test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
 	int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
 	if (s < 0)
 		return 0;
+	if (mark != MARK_UNSET && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
+		return 0;
 	int ret;
 	do {
 		ret = connect(s, addr, addrlen);
@@ -383,31 +387,31 @@
  * so checking for connectivity is the next best thing.
  */
 static int
-_have_ipv6() {
+_have_ipv6(unsigned mark) {
 	static const struct sockaddr_in6 sin6_test = {
 		.sin6_family = AF_INET6,
 		.sin6_addr.s6_addr = {  // 2000::
 			0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 		};
-        sockaddr_union addr = { .in6 = sin6_test };
-	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6));
+	sockaddr_union addr = { .in6 = sin6_test };
+	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6), mark);
 }
 
 static int
-_have_ipv4() {
+_have_ipv4(unsigned mark) {
 	static const struct sockaddr_in sin_test = {
 		.sin_family = AF_INET,
 		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
 	};
-        sockaddr_union addr = { .in = sin_test };
-        return _test_connect(PF_INET, &addr.generic, sizeof(addr.in));
+	sockaddr_union addr = { .in = sin_test };
+	return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
 }
 
 // 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, const char *iface)
+    const struct addrinfo *hints, struct addrinfo **res, unsigned netid)
 {
 	int sock;
 	const int one = 1;
@@ -447,14 +451,14 @@
 
 	// Send the request.
 	proxy = fdopen(sock, "r+");
-	if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %s",
+	if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %u",
 		    hostname == NULL ? "^" : hostname,
 		    servname == NULL ? "^" : servname,
 		    hints == NULL ? -1 : hints->ai_flags,
 		    hints == NULL ? -1 : hints->ai_family,
 		    hints == NULL ? -1 : hints->ai_socktype,
 		    hints == NULL ? -1 : hints->ai_protocol,
-		    iface == NULL ? "^" : iface) < 0) {
+		    netid) < 0) {
 		goto exit;
 	}
 	// literal NULL byte at end, required by FrameworkListener
@@ -578,12 +582,12 @@
 getaddrinfo(const char *hostname, const char *servname,
     const struct addrinfo *hints, struct addrinfo **res)
 {
-	return android_getaddrinfoforiface(hostname, servname, hints, NULL, 0, res);
+	return android_getaddrinfofornet(hostname, servname, hints, NETID_UNSET, MARK_UNSET, res);
 }
 
 int
-android_getaddrinfoforiface(const char *hostname, const char *servname,
-    const struct addrinfo *hints, const char *iface, int mark, struct addrinfo **res)
+android_getaddrinfofornet(const char *hostname, const char *servname,
+    const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
 {
 	struct addrinfo sentinel;
 	struct addrinfo *cur;
@@ -732,7 +736,7 @@
          */
 	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, iface);
+		return android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
 	}
 
 	/*
@@ -762,7 +766,7 @@
 			pai->ai_protocol = ex->e_protocol;
 
 		error = explore_fqdn(pai, hostname, servname,
-			&cur->ai_next, iface, mark);
+			&cur->ai_next, netid, mark);
 
 		while (cur && cur->ai_next)
 			cur = cur->ai_next;
@@ -795,7 +799,7 @@
  */
 static int
 explore_fqdn(const struct addrinfo *pai, const char *hostname,
-    const char *servname, struct addrinfo **res, const char *iface, int mark)
+    const char *servname, struct addrinfo **res, unsigned netid, unsigned mark)
 {
 	struct addrinfo *result;
 	struct addrinfo *cur;
@@ -821,7 +825,7 @@
 		return 0;
 
 	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
-			default_dns_files, hostname, pai, iface, mark)) {
+			default_dns_files, hostname, pai, netid, mark)) {
 	case NS_TRYAGAIN:
 		error = EAI_AGAIN;
 		goto free;
@@ -1767,7 +1771,7 @@
 
 /*ARGSUSED*/
 static int
-_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr)
+_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark)
 {
 	int sock;
 	int ret;
@@ -1793,7 +1797,8 @@
 			return -1;
 		}
 	}
-
+	if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
+		return 0;
 	do {
 		ret = connect(sock, addr, len);
 	} while (ret == -1 && errno == EINTR);
@@ -1818,7 +1823,7 @@
 
 /*ARGSUSED*/
 static void
-_rfc6724_sort(struct addrinfo *list_sentinel)
+_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark)
 {
 	struct addrinfo *cur;
 	int nelem = 0, i;
@@ -1845,7 +1850,7 @@
 		elems[i].ai = cur;
 		elems[i].original_order = i;
 
-		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic);
+		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark);
 		if (has_src_addr == -1) {
 			goto error;
 		}
@@ -1865,21 +1870,6 @@
 	free(elems);
 }
 
-static bool _using_default_dns(const char *iface)
-{
-	char buf[IF_NAMESIZE+1];
-	size_t if_len;
-
-	// common case
-	if (iface == NULL || *iface == '\0') return true;
-
-	if_len = _resolv_get_default_iface(buf, sizeof(buf));
-	if (if_len != 0 && if_len + 1 <= sizeof(buf)) {
-		if (strcmp(buf, iface) == 0) return true;
-	}
-	return false;
-}
-
 /*ARGSUSED*/
 static int
 _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
@@ -1891,13 +1881,12 @@
 	struct addrinfo sentinel, *cur;
 	struct res_target q, q2;
 	res_state res;
-	const char* iface;
-	int mark;
+	unsigned netid, mark;
 
 	name = va_arg(ap, char *);
 	pai = va_arg(ap, const struct addrinfo *);
-	iface = va_arg(ap, char *);
-	mark = va_arg(ap, int);
+	netid = va_arg(ap, unsigned);
+	mark = va_arg(ap, unsigned);
 	//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
 
 	memset(&q, 0, sizeof(q));
@@ -1926,13 +1915,8 @@
 		q.anslen = sizeof(buf->buf);
 		int query_ipv6 = 1, query_ipv4 = 1;
 		if (pai->ai_flags & AI_ADDRCONFIG) {
-			// Only implement AI_ADDRCONFIG if the application is not
-			// using its own DNS servers, since our implementation
-			// only works on the default connection.
-			if (_using_default_dns(iface)) {
-				query_ipv6 = _have_ipv6();
-				query_ipv4 = _have_ipv4();
-			}
+			query_ipv6 = _have_ipv6(mark);
+			query_ipv4 = _have_ipv4(mark);
 		}
 		if (query_ipv6) {
 			q.qtype = T_AAAA;
@@ -1979,12 +1963,12 @@
 		return NS_NOTFOUND;
 	}
 
-	/* this just sets our iface val in the thread private data so we don't have to
+	/* this just sets our netid val in the thread private data so we don't have to
 	 * modify the api's all the way down to res_send.c's res_nsend.  We could
 	 * fully populate the thread private data here, but if we get down there
 	 * and have a cache hit that would be wasted, so we do the rest there on miss
 	 */
-	res_setiface(res, iface);
+	res_setnetid(res, netid);
 	res_setmark(res, mark);
 	if (res_searchN(name, &q, res) < 0) {
 		__res_put_state(res);
@@ -2017,7 +2001,7 @@
 		}
 	}
 
-	_rfc6724_sort(&sentinel);
+	_rfc6724_sort(&sentinel, netid);
 
 	__res_put_state(res);
 
@@ -2320,7 +2304,7 @@
 		 * the domain stuff is tried.  Will have a better
 		 * fix after thread pools are used.
 		 */
-		_resolv_populate_res_for_iface(res);
+		_resolv_populate_res_for_net(res);
 
 		for (domain = (const char * const *)res->dnsrch;
 		   *domain && !done;
diff --git a/libc/dns/net/getnameinfo.c b/libc/dns/net/getnameinfo.c
index f940109..b9c0280 100644
--- a/libc/dns/net/getnameinfo.c
+++ b/libc/dns/net/getnameinfo.c
@@ -62,6 +62,7 @@
 #include <limits.h>
 #include <netdb.h>
 #include <arpa/nameser.h>
+#include "resolv_netid.h"
 #include "resolv_private.h"
 #include <sys/system_properties.h>
 #include <stdlib.h>
@@ -92,7 +93,7 @@
 };
 
 static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
-    socklen_t, char *, socklen_t, int, const char*, int);
+    socklen_t, char *, socklen_t, int, unsigned, unsigned);
 #ifdef INET6
 static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
 				 socklen_t, int);
@@ -105,18 +106,22 @@
  * Top-level getnameinfo() code.  Look at the address family, and pick an
  * appropriate function to call.
  */
-int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags)
+int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen,
+		char* serv, size_t servlen, int flags)
 {
-	return android_getnameinfoforiface(sa, salen, host, hostlen, serv, servlen, flags, NULL, 0);
+	return android_getnameinfofornet(sa, salen, host, hostlen, serv, servlen, flags,
+			NETID_UNSET, MARK_UNSET);
 }
 
-int android_getnameinfoforiface(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags, const char* iface, int mark)
+int android_getnameinfofornet(const struct sockaddr* sa, socklen_t salen, char* host,
+		size_t hostlen, char* serv, size_t servlen, int flags, unsigned netid,
+		unsigned mark)
 {
 	switch (sa->sa_family) {
 	case AF_INET:
 	case AF_INET6:
 		return getnameinfo_inet(sa, salen, host, hostlen,
-				serv, servlen, flags, iface, mark);
+				serv, servlen, flags, netid, mark);
 	case AF_LOCAL:
 		return getnameinfo_local(sa, salen, host, hostlen,
 		    serv, servlen, flags);
@@ -152,24 +157,6 @@
        return 0;
 }
 
-/* On success length of the host name is returned. A return
- * value of 0 means there's no host name associated with
- * the address. On failure -1 is returned in which case
- * normal execution flow shall continue. */
-static int
-android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily, const char* iface, int mark)
-{
-	struct hostent *hostResult =
-			android_gethostbyaddrforiface_proxy(addr, addrLen, addrFamily, iface, mark);
-
-	if (hostResult == NULL) return 0;
-
-	int lengthResult = strlen(hostResult->h_name);
-
-	if (nameBuf) strncpy(nameBuf, hostResult->h_name, nameBufLen);
-	return lengthResult;
-}
-
 /*
  * getnameinfo_inet():
  * Format an IPv4 or IPv6 sockaddr into a printable string.
@@ -178,7 +165,7 @@
 getnameinfo_inet(const struct sockaddr* sa, socklen_t salen,
        char *host, socklen_t hostlen,
        char *serv, socklen_t servlen,
-       int flags, const char* iface, int mark)
+       int flags, unsigned netid, unsigned mark)
 {
 	const struct afd *afd;
 	struct servent *sp;
@@ -316,21 +303,7 @@
 			break;
 		}
 	} else {
-		struct hostent android_proxy_hostent;
-		char android_proxy_buf[MAXDNAME];
-
-		int hostnamelen = android_gethostbyaddr_proxy(android_proxy_buf,
-				MAXDNAME, addr, afd->a_addrlen, afd->a_af, iface, mark);
-		if (hostnamelen > 0) {
-			hp = &android_proxy_hostent;
-			hp->h_name = android_proxy_buf;
-		} else if (!hostnamelen) {
-			hp = NULL;
-		} else {
-			hp = android_gethostbyaddrforiface(addr, afd->a_addrlen, afd->a_af,
-					iface, mark);
-		}
-
+		hp = android_gethostbyaddrfornet_proxy(addr, afd->a_addrlen, afd->a_af, netid);
 		if (hp) {
 #if 0
 			/*
@@ -341,6 +314,7 @@
 				char *p;
 				p = strchr(hp->h_name, '.');
 				if (p)
+					TODO: Before uncommenting rewrite to avoid modifying hp.
 					*p = '\0';
 			}
 #endif