Add dns_open_proxy for connecting to DnsProxyd
dns_open_proxy is a similar function to android_open_proxy.
dns_open_proxy returns fd of the connection.
libc will register dns_open_proxy in netdClientInitImpl.
libc calls dns_open_proxy in below function
-gethostbyname_internal
-android_getaddrinfo_proxy
-android_gethostbyaddrfornetcontext_proxy_internal
Test: build, dns works fine
Change-Id: Ic17f91866b85437b711648d24e72d2b4c82f1ad5
diff --git a/client/NetdClient.cpp b/client/NetdClient.cpp
index c4e7e2f..4497877 100644
--- a/client/NetdClient.cpp
+++ b/client/NetdClient.cpp
@@ -19,7 +19,9 @@
#include <arpa/inet.h>
#include <errno.h>
#include <math.h>
+#include <stdlib.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <unistd.h>
#include <atomic>
@@ -39,6 +41,7 @@
typedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t);
typedef int (*SocketFunctionType)(int, int, int);
typedef unsigned (*NetIdForResolvFunctionType)(unsigned);
+typedef int (*DnsOpenProxyType)();
// These variables are only modified at startup (when libc.so is loaded) and never afterwards, so
// it's okay that they are read later at runtime without a lock.
@@ -144,12 +147,9 @@
// Verify that we are allowed to use |netId|, by creating a socket and trying to have it marked
// with the netId. Call libcSocket() directly; else the socket creation (via netdClientSocket())
// might itself cause another check with the fwmark server, which would be wasteful.
- int socketFd;
- if (libcSocket) {
- socketFd = libcSocket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- } else {
- socketFd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- }
+
+ const auto socketFunc = libcSocket ? libcSocket : socket;
+ int socketFd = socketFunc(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (socketFd < 0) {
return -errno;
}
@@ -176,6 +176,36 @@
return 0;
}
+int dns_open_proxy() {
+ const char* cache_mode = getenv("ANDROID_DNS_MODE");
+ const bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
+ if (!use_proxy) {
+ return -1;
+ }
+
+ const auto socketFunc = libcSocket ? libcSocket : socket;
+ int s = socketFunc(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (s == -1) {
+ return -1;
+ }
+ const int one = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+
+ static const struct sockaddr_un proxy_addr = {
+ .sun_family = AF_UNIX,
+ .sun_path = "/dev/socket/dnsproxyd",
+ };
+
+ const auto connectFunc = libcConnect ? libcConnect : connect;
+ if (TEMP_FAILURE_RETRY(
+ connectFunc(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
+ close(s);
+ return -1;
+ }
+
+ return s;
+}
+
} // namespace
#define CHECK_SOCKET_IS_MARKABLE(sock) \
@@ -214,6 +244,12 @@
}
}
+extern "C" void netdClientInitDnsOpenProxy(DnsOpenProxyType* function) {
+ if (function) {
+ *function = dns_open_proxy;
+ }
+}
+
extern "C" int getNetworkForSocket(unsigned* netId, int socketFd) {
if (!netId || socketFd < 0) {
return -EBADF;