aboutsummaryrefslogtreecommitdiffstats
path: root/libc/netbsd/net/getnameinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/netbsd/net/getnameinfo.c')
-rw-r--r--libc/netbsd/net/getnameinfo.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/libc/netbsd/net/getnameinfo.c b/libc/netbsd/net/getnameinfo.c
index 36664435d..5479481a8 100644
--- a/libc/netbsd/net/getnameinfo.c
+++ b/libc/netbsd/net/getnameinfo.c
@@ -45,6 +45,7 @@
* beware on merge.
*/
+#include <pthread.h>
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $");
@@ -64,11 +65,17 @@ __RCSID("$NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $");
#include <netdb.h>
#ifdef ANDROID_CHANGES
#include "resolv_private.h"
+#include <sys/system_properties.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <errno.h>
#else
#include <resolv.h>
#endif
#include <stddef.h>
#include <string.h>
+#include "dnsproxyd_lock.h"
static const struct afd {
int a_af;
@@ -124,7 +131,108 @@ int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t h
}
}
+#ifdef ANDROID_CHANGES
+/* 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(struct hostent* hp, const void *addr, socklen_t addrLen, int addrFamily) {
+
+ int sock;
+ const int one = 1;
+ struct sockaddr_un proxy_addr;
+ const char* cache_mode = getenv("ANDROID_DNS_MODE");
+ FILE* proxy = NULL;
+ int result = -1;
+
+ if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
+ // Don't use the proxy in local mode. This is used by the
+ // proxy itself.
+ return -1;
+ }
+
+ // Temporary cautious hack to disable the DNS proxy for processes
+ // requesting special treatment. Ideally the DNS proxy should
+ // accomodate these apps, though.
+ char propname[PROP_NAME_MAX];
+ char propvalue[PROP_VALUE_MAX];
+ snprintf(propname, sizeof(propname), "net.dns1.%d", getpid());
+ if (__system_property_get(propname, propvalue) > 0) {
+ return -1;
+ }
+ // create socket
+ // Lock here to prevent android_getaddrinfo_proxy from trying to
+ // write to the same socket at the same time.
+ pthread_mutex_lock(&dnsproxyd_lock);
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ pthread_mutex_unlock(&dnsproxyd_lock);
+ return -1;
+ }
+
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
+ pthread_mutex_unlock(&dnsproxyd_lock);
+ return -1;
+ }
+
+ 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 (connect(sock, (const struct sockaddr*) (void*) &proxy_addr,
+ sizeof(proxy_addr)) != 0) {
+ pthread_mutex_unlock(&dnsproxyd_lock);
+ close(sock);
+ return -1;
+ }
+
+ // send request to DnsProxyListener
+ proxy = fdopen(sock,"r+");
+ if (proxy == NULL) {
+ goto exit;
+ }
+
+ char buf[INET6_ADDRSTRLEN]; // big enough for IPv4 and IPv6
+ const char* addrStr = inet_ntop(addrFamily, addr, &buf, sizeof(buf));
+ if (addrStr == NULL) {
+ goto exit;
+ }
+ if (fprintf(proxy, "gethostbyaddr %s %d %d", addrStr, addrLen, addrFamily) < 0) {
+ goto exit;
+ }
+
+ // literal NULL byte at end, required by FrameworkListener
+ if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
+ goto exit;
+ }
+
+ result = 0;
+ uint32_t name_len;
+ if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
+ goto exit;
+ }
+
+ name_len = ntohl(name_len);
+ if (name_len <= 0) {
+ goto exit;
+ }
+
+ if (fread(hp->h_name, name_len, 1, proxy) != 1) {
+ goto exit;
+ }
+
+ result = name_len;
+ exit:
+ pthread_mutex_unlock(&dnsproxyd_lock);
+ if (proxy != NULL) {
+ fclose(proxy);
+ }
+
+ return result;
+}
+#endif
/*
* getnameinfo_inet():
* Format an IPv4 or IPv6 sockaddr into a printable string.
@@ -277,7 +385,21 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags)
break;
}
} else {
+#ifdef ANDROID_CHANGES
+ struct hostent android_proxy_hostent;
+ char android_proxy_buf[MAXDNAME];
+ android_proxy_hostent.h_name = android_proxy_buf;
+
+ int hostnamelen = android_gethostbyaddr_proxy(&android_proxy_hostent,
+ addr, afd->a_addrlen, afd->a_af);
+ if (hostnamelen >= 0) {
+ hp = (hostnamelen > 0) ? &android_proxy_hostent : NULL;
+ } else {
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ }
+#else
hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+#endif
if (hp) {
#if 0