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