Merge "Pass around struct android_net_context for better behaviour"
This commit is contained in:
		@@ -53,10 +53,37 @@ struct addrinfo;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define __used_in_netd __attribute__((visibility ("default")))
 | 
					#define __used_in_netd __attribute__((visibility ("default")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * A struct to capture context relevant to network operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Application and DNS netids/marks can differ from one another under certain
 | 
				
			||||||
 | 
					 * circumstances, notably when a VPN applies to the given uid's traffic but the
 | 
				
			||||||
 | 
					 * VPN network does not have its own DNS servers explicitly provisioned.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The introduction of per-UID routing means the uid is also an essential part
 | 
				
			||||||
 | 
					 * of the evaluation context. Its proper uninitialized value is
 | 
				
			||||||
 | 
					 * NET_CONTEXT_INVALID_UID.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct android_net_context {
 | 
				
			||||||
 | 
					    unsigned app_netid;
 | 
				
			||||||
 | 
					    unsigned app_mark;
 | 
				
			||||||
 | 
					    unsigned dns_netid;
 | 
				
			||||||
 | 
					    unsigned dns_mark;
 | 
				
			||||||
 | 
					    uid_t uid;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NET_CONTEXT_INVALID_UID ((uid_t)-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct hostent *android_gethostbyaddrfornet(const void *, socklen_t, int, unsigned, unsigned) __used_in_netd;
 | 
					struct hostent *android_gethostbyaddrfornet(const void *, socklen_t, int, unsigned, unsigned) __used_in_netd;
 | 
				
			||||||
struct hostent *android_gethostbynamefornet(const char *, int, unsigned, unsigned) __used_in_netd;
 | 
					struct hostent *android_gethostbynamefornet(const char *, int, unsigned, unsigned) __used_in_netd;
 | 
				
			||||||
int android_getaddrinfofornet(const char *, const char *, const struct addrinfo *, unsigned,
 | 
					int android_getaddrinfofornet(const char *, const char *, const struct addrinfo *, unsigned,
 | 
				
			||||||
    unsigned, struct addrinfo **) __used_in_netd;
 | 
					    unsigned, struct addrinfo **) __used_in_netd;
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * TODO: consider refactoring android_getaddrinfo_proxy() to serve as an
 | 
				
			||||||
 | 
					 * explore_fqdn() dispatch table method, with the below function only making DNS calls.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int android_getaddrinfofornetcontext(const char *, const char *, const struct addrinfo *,
 | 
				
			||||||
 | 
					    const struct android_net_context *, struct addrinfo **) __used_in_netd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* set name servers for a network */
 | 
					/* set name servers for a network */
 | 
				
			||||||
extern void _resolv_set_nameservers_for_net(unsigned netid,
 | 
					extern void _resolv_set_nameservers_for_net(unsigned netid,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -218,7 +218,7 @@ struct res_target {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int str2number(const char *);
 | 
					static int str2number(const char *);
 | 
				
			||||||
static int explore_fqdn(const struct addrinfo *, const char *,
 | 
					static int explore_fqdn(const struct addrinfo *, const char *,
 | 
				
			||||||
	const char *, struct addrinfo **, unsigned netid, unsigned mark);
 | 
						const char *, struct addrinfo **, const struct android_net_context *);
 | 
				
			||||||
static int explore_null(const struct addrinfo *,
 | 
					static int explore_null(const struct addrinfo *,
 | 
				
			||||||
	const char *, struct addrinfo **);
 | 
						const char *, struct addrinfo **);
 | 
				
			||||||
static int explore_numeric(const struct addrinfo *, const char *,
 | 
					static int explore_numeric(const struct addrinfo *, const char *,
 | 
				
			||||||
@@ -244,6 +244,7 @@ static void _endhtent(FILE **);
 | 
				
			|||||||
static struct addrinfo *_gethtent(FILE **, const char *,
 | 
					static struct addrinfo *_gethtent(FILE **, const char *,
 | 
				
			||||||
    const struct addrinfo *);
 | 
					    const struct addrinfo *);
 | 
				
			||||||
static int _files_getaddrinfo(void *, void *, va_list);
 | 
					static int _files_getaddrinfo(void *, void *, va_list);
 | 
				
			||||||
 | 
					static int _find_src_addr(const struct sockaddr *, struct sockaddr *, unsigned , uid_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int res_queryN(const char *, struct res_target *, res_state);
 | 
					static int res_queryN(const char *, struct res_target *, res_state);
 | 
				
			||||||
static int res_searchN(const char *, struct res_target *, res_state);
 | 
					static int res_searchN(const char *, struct res_target *, res_state);
 | 
				
			||||||
@@ -359,29 +360,6 @@ str2number(const char *p)
 | 
				
			|||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Connect a UDP socket to a given unicast address. This will cause no network
 | 
					 | 
				
			||||||
 * traffic, but will fail fast if the system has no or limited reachability to
 | 
					 | 
				
			||||||
 * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
_test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
 | 
					 | 
				
			||||||
	int s = socket(pf, SOCK_DGRAM | SOCK_CLOEXEC, 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);
 | 
					 | 
				
			||||||
	} while (ret < 0 && errno == EINTR);
 | 
					 | 
				
			||||||
	int success = (ret == 0);
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		ret = close(s);
 | 
					 | 
				
			||||||
	} while (ret < 0 && errno == EINTR);
 | 
					 | 
				
			||||||
	return success;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The following functions determine whether IPv4 or IPv6 connectivity is
 | 
					 * The following functions determine whether IPv4 or IPv6 connectivity is
 | 
				
			||||||
 * available in order to implement AI_ADDRCONFIG.
 | 
					 * available in order to implement AI_ADDRCONFIG.
 | 
				
			||||||
@@ -392,24 +370,24 @@ _test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
 | 
				
			|||||||
 * so checking for connectivity is the next best thing.
 | 
					 * so checking for connectivity is the next best thing.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
_have_ipv6(unsigned mark) {
 | 
					_have_ipv6(unsigned mark, uid_t uid) {
 | 
				
			||||||
	static const struct sockaddr_in6 sin6_test = {
 | 
						static const struct sockaddr_in6 sin6_test = {
 | 
				
			||||||
		.sin6_family = AF_INET6,
 | 
							.sin6_family = AF_INET6,
 | 
				
			||||||
		.sin6_addr.s6_addr = {  // 2000::
 | 
							.sin6_addr.s6_addr = {  // 2000::
 | 
				
			||||||
			0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
								0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	sockaddr_union addr = { .in6 = sin6_test };
 | 
						sockaddr_union addr = { .in6 = sin6_test };
 | 
				
			||||||
	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6), mark);
 | 
						return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
_have_ipv4(unsigned mark) {
 | 
					_have_ipv4(unsigned mark, uid_t uid) {
 | 
				
			||||||
	static const struct sockaddr_in sin_test = {
 | 
						static const struct sockaddr_in sin_test = {
 | 
				
			||||||
		.sin_family = AF_INET,
 | 
							.sin_family = AF_INET,
 | 
				
			||||||
		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
 | 
							.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	sockaddr_union addr = { .in = sin_test };
 | 
						sockaddr_union addr = { .in = sin_test };
 | 
				
			||||||
	return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
 | 
						return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool readBE32(FILE* fp, int32_t* result) {
 | 
					bool readBE32(FILE* fp, int32_t* result) {
 | 
				
			||||||
@@ -588,6 +566,21 @@ getaddrinfo(const char *hostname, const char *servname,
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
					android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
				
			||||||
    const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
 | 
					    const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct android_net_context netcontext = {
 | 
				
			||||||
 | 
							.app_netid = netid,
 | 
				
			||||||
 | 
							.app_mark = mark,
 | 
				
			||||||
 | 
							.dns_netid = netid,
 | 
				
			||||||
 | 
							.dns_mark = mark,
 | 
				
			||||||
 | 
							.uid = NET_CONTEXT_INVALID_UID,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
						return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					android_getaddrinfofornetcontext(const char *hostname, const char *servname,
 | 
				
			||||||
 | 
					    const struct addrinfo *hints, const struct android_net_context *netcontext,
 | 
				
			||||||
 | 
					    struct addrinfo **res)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct addrinfo sentinel;
 | 
						struct addrinfo sentinel;
 | 
				
			||||||
	struct addrinfo *cur;
 | 
						struct addrinfo *cur;
 | 
				
			||||||
@@ -601,6 +594,7 @@ android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
				
			|||||||
	/* servname is allowed to be NULL */
 | 
						/* servname is allowed to be NULL */
 | 
				
			||||||
	/* hints is allowed to be NULL */
 | 
						/* hints is allowed to be NULL */
 | 
				
			||||||
	assert(res != NULL);
 | 
						assert(res != NULL);
 | 
				
			||||||
 | 
						assert(netcontext != NULL);
 | 
				
			||||||
	memset(&sentinel, 0, sizeof(sentinel));
 | 
						memset(&sentinel, 0, sizeof(sentinel));
 | 
				
			||||||
	cur = &sentinel;
 | 
						cur = &sentinel;
 | 
				
			||||||
	pai = &ai;
 | 
						pai = &ai;
 | 
				
			||||||
@@ -731,7 +725,8 @@ android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
				
			|||||||
		ERR(EAI_NONAME);
 | 
							ERR(EAI_NONAME);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__ANDROID__)
 | 
					#if defined(__ANDROID__)
 | 
				
			||||||
	int gai_error = android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
 | 
						int gai_error = android_getaddrinfo_proxy(
 | 
				
			||||||
 | 
							hostname, servname, hints, res, netcontext->app_netid);
 | 
				
			||||||
	if (gai_error != EAI_SYSTEM) {
 | 
						if (gai_error != EAI_SYSTEM) {
 | 
				
			||||||
		return gai_error;
 | 
							return gai_error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -763,8 +758,8 @@ android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
				
			|||||||
		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
 | 
							if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
 | 
				
			||||||
			pai->ai_protocol = ex->e_protocol;
 | 
								pai->ai_protocol = ex->e_protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		error = explore_fqdn(pai, hostname, servname,
 | 
							error = explore_fqdn(
 | 
				
			||||||
			&cur->ai_next, netid, mark);
 | 
								pai, hostname, servname, &cur->ai_next, netcontext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		while (cur && cur->ai_next)
 | 
							while (cur && cur->ai_next)
 | 
				
			||||||
			cur = cur->ai_next;
 | 
								cur = cur->ai_next;
 | 
				
			||||||
@@ -797,7 +792,8 @@ android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
explore_fqdn(const struct addrinfo *pai, const char *hostname,
 | 
					explore_fqdn(const struct addrinfo *pai, const char *hostname,
 | 
				
			||||||
    const char *servname, struct addrinfo **res, unsigned netid, unsigned mark)
 | 
					    const char *servname, struct addrinfo **res,
 | 
				
			||||||
 | 
					    const struct android_net_context *netcontext)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct addrinfo *result;
 | 
						struct addrinfo *result;
 | 
				
			||||||
	struct addrinfo *cur;
 | 
						struct addrinfo *cur;
 | 
				
			||||||
@@ -823,7 +819,7 @@ explore_fqdn(const struct addrinfo *pai, const char *hostname,
 | 
				
			|||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
 | 
						switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
 | 
				
			||||||
			default_dns_files, hostname, pai, netid, mark)) {
 | 
								default_dns_files, hostname, pai, netcontext)) {
 | 
				
			||||||
	case NS_TRYAGAIN:
 | 
						case NS_TRYAGAIN:
 | 
				
			||||||
		error = EAI_AGAIN;
 | 
							error = EAI_AGAIN;
 | 
				
			||||||
		goto free;
 | 
							goto free;
 | 
				
			||||||
@@ -1763,13 +1759,13 @@ _rfc6724_compare(const void *ptr1, const void* ptr2)
 | 
				
			|||||||
 * address. src_addr must be large enough to hold a struct sockaddr_in6.
 | 
					 * address. src_addr must be large enough to hold a struct sockaddr_in6.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns 1 if a source address was found, 0 if the address is unreachable,
 | 
					 * Returns 1 if a source address was found, 0 if the address is unreachable,
 | 
				
			||||||
 * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
 | 
					 * and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are
 | 
				
			||||||
 * undefined.
 | 
					 * undefined.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*ARGSUSED*/
 | 
					/*ARGSUSED*/
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark)
 | 
					_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark, uid_t uid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int sock;
 | 
						int sock;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
@@ -1797,6 +1793,8 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
 | 
						if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
						if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		ret = __connect(sock, addr, len);
 | 
							ret = __connect(sock, addr, len);
 | 
				
			||||||
	} while (ret == -1 && errno == EINTR);
 | 
						} while (ret == -1 && errno == EINTR);
 | 
				
			||||||
@@ -1806,7 +1804,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
 | 
				
			|||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (getsockname(sock, src_addr, &len) == -1) {
 | 
						if (src_addr && getsockname(sock, src_addr, &len) == -1) {
 | 
				
			||||||
		close(sock);
 | 
							close(sock);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1821,7 +1819,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/*ARGSUSED*/
 | 
					/*ARGSUSED*/
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark)
 | 
					_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct addrinfo *cur;
 | 
						struct addrinfo *cur;
 | 
				
			||||||
	int nelem = 0, i;
 | 
						int nelem = 0, i;
 | 
				
			||||||
@@ -1848,7 +1846,7 @@ _rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark)
 | 
				
			|||||||
		elems[i].ai = cur;
 | 
							elems[i].ai = cur;
 | 
				
			||||||
		elems[i].original_order = i;
 | 
							elems[i].original_order = i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark);
 | 
							has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark, uid);
 | 
				
			||||||
		if (has_src_addr == -1) {
 | 
							if (has_src_addr == -1) {
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -1879,12 +1877,11 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
				
			|||||||
	struct addrinfo sentinel, *cur;
 | 
						struct addrinfo sentinel, *cur;
 | 
				
			||||||
	struct res_target q, q2;
 | 
						struct res_target q, q2;
 | 
				
			||||||
	res_state res;
 | 
						res_state res;
 | 
				
			||||||
	unsigned netid, mark;
 | 
						const struct android_net_context *netcontext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	name = va_arg(ap, char *);
 | 
						name = va_arg(ap, char *);
 | 
				
			||||||
	pai = va_arg(ap, const struct addrinfo *);
 | 
						pai = va_arg(ap, const struct addrinfo *);
 | 
				
			||||||
	netid = va_arg(ap, unsigned);
 | 
						netcontext = va_arg(ap, const struct android_net_context *);
 | 
				
			||||||
	mark = va_arg(ap, unsigned);
 | 
					 | 
				
			||||||
	//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
 | 
						//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&q, 0, sizeof(q));
 | 
						memset(&q, 0, sizeof(q));
 | 
				
			||||||
@@ -1913,8 +1910,8 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
				
			|||||||
		q.anslen = sizeof(buf->buf);
 | 
							q.anslen = sizeof(buf->buf);
 | 
				
			||||||
		int query_ipv6 = 1, query_ipv4 = 1;
 | 
							int query_ipv6 = 1, query_ipv4 = 1;
 | 
				
			||||||
		if (pai->ai_flags & AI_ADDRCONFIG) {
 | 
							if (pai->ai_flags & AI_ADDRCONFIG) {
 | 
				
			||||||
			query_ipv6 = _have_ipv6(mark);
 | 
								query_ipv6 = _have_ipv6(netcontext->app_mark, netcontext->uid);
 | 
				
			||||||
			query_ipv4 = _have_ipv4(mark);
 | 
								query_ipv4 = _have_ipv4(netcontext->app_mark, netcontext->uid);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (query_ipv6) {
 | 
							if (query_ipv6) {
 | 
				
			||||||
			q.qtype = T_AAAA;
 | 
								q.qtype = T_AAAA;
 | 
				
			||||||
@@ -1966,8 +1963,8 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
				
			|||||||
	 * fully populate the thread private data here, but if we get down there
 | 
						 * 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
 | 
						 * and have a cache hit that would be wasted, so we do the rest there on miss
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	res_setnetid(res, netid);
 | 
						res_setnetid(res, netcontext->dns_netid);
 | 
				
			||||||
	res_setmark(res, mark);
 | 
						res_setmark(res, netcontext->dns_mark);
 | 
				
			||||||
	if (res_searchN(name, &q, res) < 0) {
 | 
						if (res_searchN(name, &q, res) < 0) {
 | 
				
			||||||
		__res_put_state(res);
 | 
							__res_put_state(res);
 | 
				
			||||||
		free(buf);
 | 
							free(buf);
 | 
				
			||||||
@@ -1999,7 +1996,7 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_rfc6724_sort(&sentinel, netid);
 | 
						_rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__res_put_state(res);
 | 
						__res_put_state(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -306,6 +306,7 @@ LIBC {
 | 
				
			|||||||
    alphasort;
 | 
					    alphasort;
 | 
				
			||||||
    alphasort64;
 | 
					    alphasort64;
 | 
				
			||||||
    android_getaddrinfofornet;
 | 
					    android_getaddrinfofornet;
 | 
				
			||||||
 | 
					    android_getaddrinfofornetcontext;
 | 
				
			||||||
    android_gethostbyaddrfornet;
 | 
					    android_gethostbyaddrfornet;
 | 
				
			||||||
    android_gethostbynamefornet;
 | 
					    android_gethostbynamefornet;
 | 
				
			||||||
    android_set_abort_message;
 | 
					    android_set_abort_message;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user