1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker */
16*8542734aSAndroid Build Coastguard Worker
17*8542734aSAndroid Build Coastguard Worker #include "NetdClient.h"
18*8542734aSAndroid Build Coastguard Worker
19*8542734aSAndroid Build Coastguard Worker #include <arpa/inet.h>
20*8542734aSAndroid Build Coastguard Worker #include <errno.h>
21*8542734aSAndroid Build Coastguard Worker #include <math.h>
22*8542734aSAndroid Build Coastguard Worker #include <resolv.h>
23*8542734aSAndroid Build Coastguard Worker #include <stdlib.h>
24*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
25*8542734aSAndroid Build Coastguard Worker #include <sys/system_properties.h>
26*8542734aSAndroid Build Coastguard Worker #include <sys/un.h>
27*8542734aSAndroid Build Coastguard Worker #include <unistd.h>
28*8542734aSAndroid Build Coastguard Worker
29*8542734aSAndroid Build Coastguard Worker #include <atomic>
30*8542734aSAndroid Build Coastguard Worker #include <string>
31*8542734aSAndroid Build Coastguard Worker #include <vector>
32*8542734aSAndroid Build Coastguard Worker
33*8542734aSAndroid Build Coastguard Worker #include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
34*8542734aSAndroid Build Coastguard Worker #include <android-base/parseint.h>
35*8542734aSAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
36*8542734aSAndroid Build Coastguard Worker
37*8542734aSAndroid Build Coastguard Worker #include "Fwmark.h"
38*8542734aSAndroid Build Coastguard Worker #include "FwmarkClient.h"
39*8542734aSAndroid Build Coastguard Worker #include "FwmarkCommand.h"
40*8542734aSAndroid Build Coastguard Worker #include "netdclient_priv.h"
41*8542734aSAndroid Build Coastguard Worker #include "netdutils/ResponseCode.h"
42*8542734aSAndroid Build Coastguard Worker #include "netdutils/Stopwatch.h"
43*8542734aSAndroid Build Coastguard Worker #include "netid_client.h"
44*8542734aSAndroid Build Coastguard Worker
45*8542734aSAndroid Build Coastguard Worker using android::base::ParseInt;
46*8542734aSAndroid Build Coastguard Worker using android::base::unique_fd;
47*8542734aSAndroid Build Coastguard Worker using android::netdutils::ResponseCode;
48*8542734aSAndroid Build Coastguard Worker using android::netdutils::Stopwatch;
49*8542734aSAndroid Build Coastguard Worker
50*8542734aSAndroid Build Coastguard Worker namespace {
51*8542734aSAndroid Build Coastguard Worker
52*8542734aSAndroid Build Coastguard Worker // Keep this in sync with CMD_BUF_SIZE in FrameworkListener.cpp.
53*8542734aSAndroid Build Coastguard Worker constexpr size_t MAX_CMD_SIZE = 4096;
54*8542734aSAndroid Build Coastguard Worker // Whether sendto(), sendmsg(), sendmmsg() in libc are shimmed or not. This property is evaluated at
55*8542734aSAndroid Build Coastguard Worker // process start time and cannot change at runtime on a given device.
56*8542734aSAndroid Build Coastguard Worker constexpr char PROPERTY_REDIRECT_SOCKET_CALLS[] = "ro.vendor.redirect_socket_calls";
57*8542734aSAndroid Build Coastguard Worker // Whether some shimmed functions dispatch FwmarkCommand or not. The property can be changed by
58*8542734aSAndroid Build Coastguard Worker // System Server at runtime. Note: accept4(), socket(), connect() are always shimmed.
59*8542734aSAndroid Build Coastguard Worker constexpr char PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED[] = "net.redirect_socket_calls.hooked";
60*8542734aSAndroid Build Coastguard Worker
61*8542734aSAndroid Build Coastguard Worker std::atomic_uint netIdForProcess(NETID_UNSET);
62*8542734aSAndroid Build Coastguard Worker std::atomic_uint netIdForResolv(NETID_UNSET);
63*8542734aSAndroid Build Coastguard Worker std::atomic_bool allowNetworkingForProcess(true);
64*8542734aSAndroid Build Coastguard Worker
65*8542734aSAndroid Build Coastguard Worker typedef int (*Accept4FunctionType)(int, sockaddr*, socklen_t*, int);
66*8542734aSAndroid Build Coastguard Worker typedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t);
67*8542734aSAndroid Build Coastguard Worker typedef int (*SocketFunctionType)(int, int, int);
68*8542734aSAndroid Build Coastguard Worker typedef unsigned (*NetIdForResolvFunctionType)(unsigned);
69*8542734aSAndroid Build Coastguard Worker typedef int (*DnsOpenProxyType)();
70*8542734aSAndroid Build Coastguard Worker typedef int (*SendmmsgFunctionType)(int, const mmsghdr*, unsigned int, int);
71*8542734aSAndroid Build Coastguard Worker typedef ssize_t (*SendmsgFunctionType)(int, const msghdr*, unsigned int);
72*8542734aSAndroid Build Coastguard Worker typedef int (*SendtoFunctionType)(int, const void*, size_t, int, const sockaddr*, socklen_t);
73*8542734aSAndroid Build Coastguard Worker
74*8542734aSAndroid Build Coastguard Worker // These variables are only modified at startup (when libc.so is loaded) and never afterwards, so
75*8542734aSAndroid Build Coastguard Worker // it's okay that they are read later at runtime without a lock.
76*8542734aSAndroid Build Coastguard Worker Accept4FunctionType libcAccept4 = nullptr;
77*8542734aSAndroid Build Coastguard Worker ConnectFunctionType libcConnect = nullptr;
78*8542734aSAndroid Build Coastguard Worker SocketFunctionType libcSocket = nullptr;
79*8542734aSAndroid Build Coastguard Worker SendmmsgFunctionType libcSendmmsg = nullptr;
80*8542734aSAndroid Build Coastguard Worker SendmsgFunctionType libcSendmsg = nullptr;
81*8542734aSAndroid Build Coastguard Worker SendtoFunctionType libcSendto = nullptr;
82*8542734aSAndroid Build Coastguard Worker
propertyValueIsTrue(const char * prop_name)83*8542734aSAndroid Build Coastguard Worker static bool propertyValueIsTrue(const char* prop_name) {
84*8542734aSAndroid Build Coastguard Worker char prop_value[PROP_VALUE_MAX] = {0};
85*8542734aSAndroid Build Coastguard Worker if (__system_property_get(prop_name, prop_value) > 0) {
86*8542734aSAndroid Build Coastguard Worker if (strcmp(prop_value, "true") == 0) {
87*8542734aSAndroid Build Coastguard Worker return true;
88*8542734aSAndroid Build Coastguard Worker }
89*8542734aSAndroid Build Coastguard Worker }
90*8542734aSAndroid Build Coastguard Worker return false;
91*8542734aSAndroid Build Coastguard Worker }
92*8542734aSAndroid Build Coastguard Worker
93*8542734aSAndroid Build Coastguard Worker // whether to hook sendmmsg/sendmsg/sendto
redirectSendX()94*8542734aSAndroid Build Coastguard Worker static bool redirectSendX() {
95*8542734aSAndroid Build Coastguard Worker static bool cached_result = propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS);
96*8542734aSAndroid Build Coastguard Worker return cached_result;
97*8542734aSAndroid Build Coastguard Worker }
98*8542734aSAndroid Build Coastguard Worker
checkSocket(int socketFd)99*8542734aSAndroid Build Coastguard Worker int checkSocket(int socketFd) {
100*8542734aSAndroid Build Coastguard Worker if (socketFd < 0) {
101*8542734aSAndroid Build Coastguard Worker return -EBADF;
102*8542734aSAndroid Build Coastguard Worker }
103*8542734aSAndroid Build Coastguard Worker int family;
104*8542734aSAndroid Build Coastguard Worker socklen_t familyLen = sizeof(family);
105*8542734aSAndroid Build Coastguard Worker if (getsockopt(socketFd, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) {
106*8542734aSAndroid Build Coastguard Worker return -errno;
107*8542734aSAndroid Build Coastguard Worker }
108*8542734aSAndroid Build Coastguard Worker if (!FwmarkClient::shouldSetFwmark(family)) {
109*8542734aSAndroid Build Coastguard Worker return -EAFNOSUPPORT;
110*8542734aSAndroid Build Coastguard Worker }
111*8542734aSAndroid Build Coastguard Worker return 0;
112*8542734aSAndroid Build Coastguard Worker }
113*8542734aSAndroid Build Coastguard Worker
shouldMarkSocket(int socketFd,const sockaddr * dst)114*8542734aSAndroid Build Coastguard Worker bool shouldMarkSocket(int socketFd, const sockaddr* dst) {
115*8542734aSAndroid Build Coastguard Worker // Only mark inet sockets that are connecting to inet destinations. This excludes, for example,
116*8542734aSAndroid Build Coastguard Worker // inet sockets connecting to AF_UNSPEC (i.e., being disconnected), and non-inet sockets that
117*8542734aSAndroid Build Coastguard Worker // for some reason the caller wants to attempt to connect to an inet destination.
118*8542734aSAndroid Build Coastguard Worker return dst && FwmarkClient::shouldSetFwmark(dst->sa_family) && (checkSocket(socketFd) == 0);
119*8542734aSAndroid Build Coastguard Worker }
120*8542734aSAndroid Build Coastguard Worker
closeFdAndSetErrno(int fd,int error)121*8542734aSAndroid Build Coastguard Worker int closeFdAndSetErrno(int fd, int error) {
122*8542734aSAndroid Build Coastguard Worker close(fd);
123*8542734aSAndroid Build Coastguard Worker errno = -error;
124*8542734aSAndroid Build Coastguard Worker return -1;
125*8542734aSAndroid Build Coastguard Worker }
126*8542734aSAndroid Build Coastguard Worker
netdClientAccept4(int sockfd,sockaddr * addr,socklen_t * addrlen,int flags)127*8542734aSAndroid Build Coastguard Worker int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) {
128*8542734aSAndroid Build Coastguard Worker int acceptedSocket = libcAccept4(sockfd, addr, addrlen, flags);
129*8542734aSAndroid Build Coastguard Worker if (acceptedSocket == -1) {
130*8542734aSAndroid Build Coastguard Worker return -1;
131*8542734aSAndroid Build Coastguard Worker }
132*8542734aSAndroid Build Coastguard Worker int family;
133*8542734aSAndroid Build Coastguard Worker if (addr) {
134*8542734aSAndroid Build Coastguard Worker family = addr->sa_family;
135*8542734aSAndroid Build Coastguard Worker } else {
136*8542734aSAndroid Build Coastguard Worker socklen_t familyLen = sizeof(family);
137*8542734aSAndroid Build Coastguard Worker if (getsockopt(acceptedSocket, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) {
138*8542734aSAndroid Build Coastguard Worker return closeFdAndSetErrno(acceptedSocket, -errno);
139*8542734aSAndroid Build Coastguard Worker }
140*8542734aSAndroid Build Coastguard Worker }
141*8542734aSAndroid Build Coastguard Worker if (FwmarkClient::shouldSetFwmark(family)) {
142*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0, 0};
143*8542734aSAndroid Build Coastguard Worker if (int error = FwmarkClient().send(&command, acceptedSocket, nullptr)) {
144*8542734aSAndroid Build Coastguard Worker return closeFdAndSetErrno(acceptedSocket, error);
145*8542734aSAndroid Build Coastguard Worker }
146*8542734aSAndroid Build Coastguard Worker }
147*8542734aSAndroid Build Coastguard Worker return acceptedSocket;
148*8542734aSAndroid Build Coastguard Worker }
149*8542734aSAndroid Build Coastguard Worker
netdClientConnect(int sockfd,const sockaddr * addr,socklen_t addrlen)150*8542734aSAndroid Build Coastguard Worker int netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
151*8542734aSAndroid Build Coastguard Worker const bool shouldSetFwmark = shouldMarkSocket(sockfd, addr);
152*8542734aSAndroid Build Coastguard Worker if (shouldSetFwmark) {
153*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::ON_CONNECT, 0, 0, 0};
154*8542734aSAndroid Build Coastguard Worker FwmarkConnectInfo connectInfo(0, 0, addr);
155*8542734aSAndroid Build Coastguard Worker int error = FwmarkClient().send(&command, sockfd, &connectInfo);
156*8542734aSAndroid Build Coastguard Worker
157*8542734aSAndroid Build Coastguard Worker if (error) {
158*8542734aSAndroid Build Coastguard Worker errno = -error;
159*8542734aSAndroid Build Coastguard Worker return -1;
160*8542734aSAndroid Build Coastguard Worker }
161*8542734aSAndroid Build Coastguard Worker }
162*8542734aSAndroid Build Coastguard Worker // Latency measurement does not include time of sending commands to Fwmark
163*8542734aSAndroid Build Coastguard Worker Stopwatch s;
164*8542734aSAndroid Build Coastguard Worker const int ret = libcConnect(sockfd, addr, addrlen);
165*8542734aSAndroid Build Coastguard Worker // Save errno so it isn't clobbered by sending ON_CONNECT_COMPLETE
166*8542734aSAndroid Build Coastguard Worker const int connectErrno = errno;
167*8542734aSAndroid Build Coastguard Worker const auto latencyMs = static_cast<unsigned>(s.timeTakenUs() / 1000);
168*8542734aSAndroid Build Coastguard Worker // Send an ON_CONNECT_COMPLETE command that includes sockaddr and connect latency for reporting
169*8542734aSAndroid Build Coastguard Worker if (shouldSetFwmark) {
170*8542734aSAndroid Build Coastguard Worker FwmarkConnectInfo connectInfo(ret == 0 ? 0 : connectErrno, latencyMs, addr);
171*8542734aSAndroid Build Coastguard Worker // TODO: get the netId from the socket mark once we have continuous benchmark runs
172*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::ON_CONNECT_COMPLETE, /* netId (ignored) */ 0,
173*8542734aSAndroid Build Coastguard Worker /* uid (filled in by the server) */ 0, 0};
174*8542734aSAndroid Build Coastguard Worker // Ignore return value since it's only used for logging
175*8542734aSAndroid Build Coastguard Worker FwmarkClient().send(&command, sockfd, &connectInfo);
176*8542734aSAndroid Build Coastguard Worker }
177*8542734aSAndroid Build Coastguard Worker errno = connectErrno;
178*8542734aSAndroid Build Coastguard Worker return ret;
179*8542734aSAndroid Build Coastguard Worker }
180*8542734aSAndroid Build Coastguard Worker
netdClientSocket(int domain,int type,int protocol)181*8542734aSAndroid Build Coastguard Worker int netdClientSocket(int domain, int type, int protocol) {
182*8542734aSAndroid Build Coastguard Worker // Block creating AF_INET/AF_INET6 socket if networking is not allowed.
183*8542734aSAndroid Build Coastguard Worker if (FwmarkCommand::isSupportedFamily(domain) && !allowNetworkingForProcess.load()) {
184*8542734aSAndroid Build Coastguard Worker errno = EPERM;
185*8542734aSAndroid Build Coastguard Worker return -1;
186*8542734aSAndroid Build Coastguard Worker }
187*8542734aSAndroid Build Coastguard Worker int socketFd = libcSocket(domain, type, protocol);
188*8542734aSAndroid Build Coastguard Worker if (socketFd == -1) {
189*8542734aSAndroid Build Coastguard Worker return -1;
190*8542734aSAndroid Build Coastguard Worker }
191*8542734aSAndroid Build Coastguard Worker unsigned netId = netIdForProcess & ~NETID_USE_LOCAL_NAMESERVERS;
192*8542734aSAndroid Build Coastguard Worker if (netId != NETID_UNSET && FwmarkClient::shouldSetFwmark(domain)) {
193*8542734aSAndroid Build Coastguard Worker if (int error = setNetworkForSocket(netId, socketFd)) {
194*8542734aSAndroid Build Coastguard Worker return closeFdAndSetErrno(socketFd, error);
195*8542734aSAndroid Build Coastguard Worker }
196*8542734aSAndroid Build Coastguard Worker }
197*8542734aSAndroid Build Coastguard Worker return socketFd;
198*8542734aSAndroid Build Coastguard Worker }
199*8542734aSAndroid Build Coastguard Worker
netdClientSendmmsg(int sockfd,const mmsghdr * msgs,unsigned int msgcount,int flags)200*8542734aSAndroid Build Coastguard Worker int netdClientSendmmsg(int sockfd, const mmsghdr* msgs, unsigned int msgcount, int flags) {
201*8542734aSAndroid Build Coastguard Worker if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
202*8542734aSAndroid Build Coastguard Worker const sockaddr* addr = nullptr;
203*8542734aSAndroid Build Coastguard Worker if ((msgcount > 0) && (msgs != nullptr) && (msgs[0].msg_hdr.msg_name != nullptr)) {
204*8542734aSAndroid Build Coastguard Worker addr = reinterpret_cast<const sockaddr*>(msgs[0].msg_hdr.msg_name);
205*8542734aSAndroid Build Coastguard Worker if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
206*8542734aSAndroid Build Coastguard Worker FwmarkConnectInfo sendmmsgInfo(0, 0, addr);
207*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::ON_SENDMMSG, 0, 0, 0};
208*8542734aSAndroid Build Coastguard Worker FwmarkClient().send(&command, sockfd, &sendmmsgInfo);
209*8542734aSAndroid Build Coastguard Worker }
210*8542734aSAndroid Build Coastguard Worker }
211*8542734aSAndroid Build Coastguard Worker }
212*8542734aSAndroid Build Coastguard Worker return libcSendmmsg(sockfd, msgs, msgcount, flags);
213*8542734aSAndroid Build Coastguard Worker }
214*8542734aSAndroid Build Coastguard Worker
netdClientSendmsg(int sockfd,const msghdr * msg,unsigned int flags)215*8542734aSAndroid Build Coastguard Worker ssize_t netdClientSendmsg(int sockfd, const msghdr* msg, unsigned int flags) {
216*8542734aSAndroid Build Coastguard Worker if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
217*8542734aSAndroid Build Coastguard Worker const sockaddr* addr = nullptr;
218*8542734aSAndroid Build Coastguard Worker if ((msg != nullptr) && (msg->msg_name != nullptr)) {
219*8542734aSAndroid Build Coastguard Worker addr = reinterpret_cast<const sockaddr*>(msg->msg_name);
220*8542734aSAndroid Build Coastguard Worker if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
221*8542734aSAndroid Build Coastguard Worker FwmarkConnectInfo sendmsgInfo(0, 0, addr);
222*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::ON_SENDMSG, 0, 0, 0};
223*8542734aSAndroid Build Coastguard Worker FwmarkClient().send(&command, sockfd, &sendmsgInfo);
224*8542734aSAndroid Build Coastguard Worker }
225*8542734aSAndroid Build Coastguard Worker }
226*8542734aSAndroid Build Coastguard Worker }
227*8542734aSAndroid Build Coastguard Worker return libcSendmsg(sockfd, msg, flags);
228*8542734aSAndroid Build Coastguard Worker }
229*8542734aSAndroid Build Coastguard Worker
netdClientSendto(int sockfd,const void * buf,size_t bufsize,int flags,const sockaddr * addr,socklen_t addrlen)230*8542734aSAndroid Build Coastguard Worker int netdClientSendto(int sockfd, const void* buf, size_t bufsize, int flags, const sockaddr* addr,
231*8542734aSAndroid Build Coastguard Worker socklen_t addrlen) {
232*8542734aSAndroid Build Coastguard Worker if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
233*8542734aSAndroid Build Coastguard Worker if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
234*8542734aSAndroid Build Coastguard Worker FwmarkConnectInfo sendtoInfo(0, 0, addr);
235*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::ON_SENDTO, 0, 0, 0};
236*8542734aSAndroid Build Coastguard Worker FwmarkClient().send(&command, sockfd, &sendtoInfo);
237*8542734aSAndroid Build Coastguard Worker }
238*8542734aSAndroid Build Coastguard Worker }
239*8542734aSAndroid Build Coastguard Worker return libcSendto(sockfd, buf, bufsize, flags, addr, addrlen);
240*8542734aSAndroid Build Coastguard Worker }
241*8542734aSAndroid Build Coastguard Worker
getNetworkForResolv(unsigned netId)242*8542734aSAndroid Build Coastguard Worker unsigned getNetworkForResolv(unsigned netId) {
243*8542734aSAndroid Build Coastguard Worker if (netId != NETID_UNSET) {
244*8542734aSAndroid Build Coastguard Worker return netId;
245*8542734aSAndroid Build Coastguard Worker }
246*8542734aSAndroid Build Coastguard Worker // Special case for DNS-over-TLS bypass; b/72345192 .
247*8542734aSAndroid Build Coastguard Worker if ((netIdForResolv & ~NETID_USE_LOCAL_NAMESERVERS) != NETID_UNSET) {
248*8542734aSAndroid Build Coastguard Worker return netIdForResolv;
249*8542734aSAndroid Build Coastguard Worker }
250*8542734aSAndroid Build Coastguard Worker netId = netIdForProcess;
251*8542734aSAndroid Build Coastguard Worker if (netId != NETID_UNSET) {
252*8542734aSAndroid Build Coastguard Worker return netId;
253*8542734aSAndroid Build Coastguard Worker }
254*8542734aSAndroid Build Coastguard Worker return netIdForResolv;
255*8542734aSAndroid Build Coastguard Worker }
256*8542734aSAndroid Build Coastguard Worker
setNetworkForTarget(unsigned netId,std::atomic_uint * target)257*8542734aSAndroid Build Coastguard Worker int setNetworkForTarget(unsigned netId, std::atomic_uint* target) {
258*8542734aSAndroid Build Coastguard Worker const unsigned requestedNetId = netId;
259*8542734aSAndroid Build Coastguard Worker netId &= ~NETID_USE_LOCAL_NAMESERVERS;
260*8542734aSAndroid Build Coastguard Worker
261*8542734aSAndroid Build Coastguard Worker if (netId == NETID_UNSET) {
262*8542734aSAndroid Build Coastguard Worker *target = netId;
263*8542734aSAndroid Build Coastguard Worker return 0;
264*8542734aSAndroid Build Coastguard Worker }
265*8542734aSAndroid Build Coastguard Worker // Verify that we are allowed to use |netId|, by creating a socket and trying to have it marked
266*8542734aSAndroid Build Coastguard Worker // with the netId. Call libcSocket() directly; else the socket creation (via netdClientSocket())
267*8542734aSAndroid Build Coastguard Worker // might itself cause another check with the fwmark server, which would be wasteful.
268*8542734aSAndroid Build Coastguard Worker
269*8542734aSAndroid Build Coastguard Worker const auto socketFunc = libcSocket ? libcSocket : socket;
270*8542734aSAndroid Build Coastguard Worker int socketFd = socketFunc(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
271*8542734aSAndroid Build Coastguard Worker if (socketFd < 0) {
272*8542734aSAndroid Build Coastguard Worker return -errno;
273*8542734aSAndroid Build Coastguard Worker }
274*8542734aSAndroid Build Coastguard Worker int error = setNetworkForSocket(netId, socketFd);
275*8542734aSAndroid Build Coastguard Worker if (!error) {
276*8542734aSAndroid Build Coastguard Worker *target = requestedNetId;
277*8542734aSAndroid Build Coastguard Worker }
278*8542734aSAndroid Build Coastguard Worker close(socketFd);
279*8542734aSAndroid Build Coastguard Worker return error;
280*8542734aSAndroid Build Coastguard Worker }
281*8542734aSAndroid Build Coastguard Worker
dns_open_proxy()282*8542734aSAndroid Build Coastguard Worker int dns_open_proxy() {
283*8542734aSAndroid Build Coastguard Worker const char* cache_mode = getenv("ANDROID_DNS_MODE");
284*8542734aSAndroid Build Coastguard Worker const bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
285*8542734aSAndroid Build Coastguard Worker if (!use_proxy) {
286*8542734aSAndroid Build Coastguard Worker errno = ENOSYS;
287*8542734aSAndroid Build Coastguard Worker return -1;
288*8542734aSAndroid Build Coastguard Worker }
289*8542734aSAndroid Build Coastguard Worker
290*8542734aSAndroid Build Coastguard Worker // If networking is not allowed, dns_open_proxy should just fail here.
291*8542734aSAndroid Build Coastguard Worker // Then eventually, the DNS related functions in local mode will get
292*8542734aSAndroid Build Coastguard Worker // EPERM while creating socket.
293*8542734aSAndroid Build Coastguard Worker if (!allowNetworkingForProcess.load()) {
294*8542734aSAndroid Build Coastguard Worker errno = EPERM;
295*8542734aSAndroid Build Coastguard Worker return -1;
296*8542734aSAndroid Build Coastguard Worker }
297*8542734aSAndroid Build Coastguard Worker const auto socketFunc = libcSocket ? libcSocket : socket;
298*8542734aSAndroid Build Coastguard Worker int s = socketFunc(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
299*8542734aSAndroid Build Coastguard Worker if (s == -1) {
300*8542734aSAndroid Build Coastguard Worker return -1;
301*8542734aSAndroid Build Coastguard Worker }
302*8542734aSAndroid Build Coastguard Worker const int one = 1;
303*8542734aSAndroid Build Coastguard Worker setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
304*8542734aSAndroid Build Coastguard Worker
305*8542734aSAndroid Build Coastguard Worker static const struct sockaddr_un proxy_addr = {
306*8542734aSAndroid Build Coastguard Worker .sun_family = AF_UNIX,
307*8542734aSAndroid Build Coastguard Worker .sun_path = "/dev/socket/dnsproxyd",
308*8542734aSAndroid Build Coastguard Worker };
309*8542734aSAndroid Build Coastguard Worker
310*8542734aSAndroid Build Coastguard Worker const auto connectFunc = libcConnect ? libcConnect : connect;
311*8542734aSAndroid Build Coastguard Worker if (TEMP_FAILURE_RETRY(
312*8542734aSAndroid Build Coastguard Worker connectFunc(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
313*8542734aSAndroid Build Coastguard Worker // Store the errno for connect because we only care about why we can't connect to dnsproxyd
314*8542734aSAndroid Build Coastguard Worker int storedErrno = errno;
315*8542734aSAndroid Build Coastguard Worker close(s);
316*8542734aSAndroid Build Coastguard Worker errno = storedErrno;
317*8542734aSAndroid Build Coastguard Worker return -1;
318*8542734aSAndroid Build Coastguard Worker }
319*8542734aSAndroid Build Coastguard Worker
320*8542734aSAndroid Build Coastguard Worker return s;
321*8542734aSAndroid Build Coastguard Worker }
322*8542734aSAndroid Build Coastguard Worker
divCeil(size_t dividend,size_t divisor)323*8542734aSAndroid Build Coastguard Worker auto divCeil(size_t dividend, size_t divisor) {
324*8542734aSAndroid Build Coastguard Worker return ((dividend + divisor - 1) / divisor);
325*8542734aSAndroid Build Coastguard Worker }
326*8542734aSAndroid Build Coastguard Worker
327*8542734aSAndroid Build Coastguard Worker // FrameworkListener only does only read() call, and fails if the read doesn't contain \0
328*8542734aSAndroid Build Coastguard Worker // Do single write here
sendData(int fd,const void * buf,size_t size)329*8542734aSAndroid Build Coastguard Worker int sendData(int fd, const void* buf, size_t size) {
330*8542734aSAndroid Build Coastguard Worker if (fd < 0) {
331*8542734aSAndroid Build Coastguard Worker return -EBADF;
332*8542734aSAndroid Build Coastguard Worker }
333*8542734aSAndroid Build Coastguard Worker
334*8542734aSAndroid Build Coastguard Worker ssize_t rc = TEMP_FAILURE_RETRY(write(fd, (char*) buf, size));
335*8542734aSAndroid Build Coastguard Worker if (rc > 0) {
336*8542734aSAndroid Build Coastguard Worker return rc;
337*8542734aSAndroid Build Coastguard Worker } else if (rc == 0) {
338*8542734aSAndroid Build Coastguard Worker return -EIO;
339*8542734aSAndroid Build Coastguard Worker } else {
340*8542734aSAndroid Build Coastguard Worker return -errno;
341*8542734aSAndroid Build Coastguard Worker }
342*8542734aSAndroid Build Coastguard Worker }
343*8542734aSAndroid Build Coastguard Worker
readData(int fd,void * buf,size_t size)344*8542734aSAndroid Build Coastguard Worker int readData(int fd, void* buf, size_t size) {
345*8542734aSAndroid Build Coastguard Worker if (fd < 0) {
346*8542734aSAndroid Build Coastguard Worker return -EBADF;
347*8542734aSAndroid Build Coastguard Worker }
348*8542734aSAndroid Build Coastguard Worker
349*8542734aSAndroid Build Coastguard Worker size_t current = 0;
350*8542734aSAndroid Build Coastguard Worker for (;;) {
351*8542734aSAndroid Build Coastguard Worker ssize_t rc = TEMP_FAILURE_RETRY(read(fd, (char*) buf + current, size - current));
352*8542734aSAndroid Build Coastguard Worker if (rc > 0) {
353*8542734aSAndroid Build Coastguard Worker current += rc;
354*8542734aSAndroid Build Coastguard Worker if (current == size) {
355*8542734aSAndroid Build Coastguard Worker break;
356*8542734aSAndroid Build Coastguard Worker }
357*8542734aSAndroid Build Coastguard Worker } else if (rc == 0) {
358*8542734aSAndroid Build Coastguard Worker return -EIO;
359*8542734aSAndroid Build Coastguard Worker } else {
360*8542734aSAndroid Build Coastguard Worker return -errno;
361*8542734aSAndroid Build Coastguard Worker }
362*8542734aSAndroid Build Coastguard Worker }
363*8542734aSAndroid Build Coastguard Worker return 0;
364*8542734aSAndroid Build Coastguard Worker }
365*8542734aSAndroid Build Coastguard Worker
readBE32(int fd,int32_t * result)366*8542734aSAndroid Build Coastguard Worker bool readBE32(int fd, int32_t* result) {
367*8542734aSAndroid Build Coastguard Worker int32_t tmp;
368*8542734aSAndroid Build Coastguard Worker ssize_t n = TEMP_FAILURE_RETRY(read(fd, &tmp, sizeof(tmp)));
369*8542734aSAndroid Build Coastguard Worker if (n < static_cast<ssize_t>(sizeof(tmp))) {
370*8542734aSAndroid Build Coastguard Worker return false;
371*8542734aSAndroid Build Coastguard Worker }
372*8542734aSAndroid Build Coastguard Worker *result = ntohl(tmp);
373*8542734aSAndroid Build Coastguard Worker return true;
374*8542734aSAndroid Build Coastguard Worker }
375*8542734aSAndroid Build Coastguard Worker
readResponseCode(int fd,int * result)376*8542734aSAndroid Build Coastguard Worker bool readResponseCode(int fd, int* result) {
377*8542734aSAndroid Build Coastguard Worker char buf[4];
378*8542734aSAndroid Build Coastguard Worker ssize_t n = TEMP_FAILURE_RETRY(read(fd, &buf, sizeof(buf)));
379*8542734aSAndroid Build Coastguard Worker if (n < static_cast<ssize_t>(sizeof(buf))) {
380*8542734aSAndroid Build Coastguard Worker return false;
381*8542734aSAndroid Build Coastguard Worker }
382*8542734aSAndroid Build Coastguard Worker
383*8542734aSAndroid Build Coastguard Worker // The format of response code is 3 bytes followed by a space.
384*8542734aSAndroid Build Coastguard Worker buf[3] = '\0';
385*8542734aSAndroid Build Coastguard Worker if (!ParseInt(buf, result)) {
386*8542734aSAndroid Build Coastguard Worker errno = EINVAL;
387*8542734aSAndroid Build Coastguard Worker return false;
388*8542734aSAndroid Build Coastguard Worker }
389*8542734aSAndroid Build Coastguard Worker
390*8542734aSAndroid Build Coastguard Worker return true;
391*8542734aSAndroid Build Coastguard Worker }
392*8542734aSAndroid Build Coastguard Worker
393*8542734aSAndroid Build Coastguard Worker } // namespace
394*8542734aSAndroid Build Coastguard Worker
395*8542734aSAndroid Build Coastguard Worker #define CHECK_SOCKET_IS_MARKABLE(sock) \
396*8542734aSAndroid Build Coastguard Worker do { \
397*8542734aSAndroid Build Coastguard Worker int err = checkSocket(sock); \
398*8542734aSAndroid Build Coastguard Worker if (err) return err; \
399*8542734aSAndroid Build Coastguard Worker } while (false)
400*8542734aSAndroid Build Coastguard Worker
401*8542734aSAndroid Build Coastguard Worker #define HOOK_ON_FUNC(remoteFunc, nativeFunc, localFunc) \
402*8542734aSAndroid Build Coastguard Worker do { \
403*8542734aSAndroid Build Coastguard Worker if ((remoteFunc) && *(remoteFunc)) { \
404*8542734aSAndroid Build Coastguard Worker (nativeFunc) = *(remoteFunc); \
405*8542734aSAndroid Build Coastguard Worker *(remoteFunc) = (localFunc); \
406*8542734aSAndroid Build Coastguard Worker } \
407*8542734aSAndroid Build Coastguard Worker } while (false)
408*8542734aSAndroid Build Coastguard Worker
409*8542734aSAndroid Build Coastguard Worker // accept() just calls accept4(..., 0), so there's no need to handle accept() separately.
netdClientInitAccept4(Accept4FunctionType * function)410*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitAccept4(Accept4FunctionType* function) {
411*8542734aSAndroid Build Coastguard Worker HOOK_ON_FUNC(function, libcAccept4, netdClientAccept4);
412*8542734aSAndroid Build Coastguard Worker }
413*8542734aSAndroid Build Coastguard Worker
netdClientInitConnect(ConnectFunctionType * function)414*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitConnect(ConnectFunctionType* function) {
415*8542734aSAndroid Build Coastguard Worker HOOK_ON_FUNC(function, libcConnect, netdClientConnect);
416*8542734aSAndroid Build Coastguard Worker }
417*8542734aSAndroid Build Coastguard Worker
netdClientInitSocket(SocketFunctionType * function)418*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitSocket(SocketFunctionType* function) {
419*8542734aSAndroid Build Coastguard Worker HOOK_ON_FUNC(function, libcSocket, netdClientSocket);
420*8542734aSAndroid Build Coastguard Worker }
421*8542734aSAndroid Build Coastguard Worker
netdClientInitSendmmsg(SendmmsgFunctionType * function)422*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitSendmmsg(SendmmsgFunctionType* function) {
423*8542734aSAndroid Build Coastguard Worker if (redirectSendX()) HOOK_ON_FUNC(function, libcSendmmsg, netdClientSendmmsg);
424*8542734aSAndroid Build Coastguard Worker }
425*8542734aSAndroid Build Coastguard Worker
netdClientInitSendmsg(SendmsgFunctionType * function)426*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitSendmsg(SendmsgFunctionType* function) {
427*8542734aSAndroid Build Coastguard Worker if (redirectSendX()) HOOK_ON_FUNC(function, libcSendmsg, netdClientSendmsg);
428*8542734aSAndroid Build Coastguard Worker }
429*8542734aSAndroid Build Coastguard Worker
netdClientInitSendto(SendtoFunctionType * function)430*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitSendto(SendtoFunctionType* function) {
431*8542734aSAndroid Build Coastguard Worker if (redirectSendX()) HOOK_ON_FUNC(function, libcSendto, netdClientSendto);
432*8542734aSAndroid Build Coastguard Worker }
433*8542734aSAndroid Build Coastguard Worker
netdClientInitNetIdForResolv(NetIdForResolvFunctionType * function)434*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitNetIdForResolv(NetIdForResolvFunctionType* function) {
435*8542734aSAndroid Build Coastguard Worker if (function) {
436*8542734aSAndroid Build Coastguard Worker *function = getNetworkForResolv;
437*8542734aSAndroid Build Coastguard Worker }
438*8542734aSAndroid Build Coastguard Worker }
439*8542734aSAndroid Build Coastguard Worker
netdClientInitDnsOpenProxy(DnsOpenProxyType * function)440*8542734aSAndroid Build Coastguard Worker extern "C" void netdClientInitDnsOpenProxy(DnsOpenProxyType* function) {
441*8542734aSAndroid Build Coastguard Worker if (function) {
442*8542734aSAndroid Build Coastguard Worker *function = dns_open_proxy;
443*8542734aSAndroid Build Coastguard Worker }
444*8542734aSAndroid Build Coastguard Worker }
445*8542734aSAndroid Build Coastguard Worker
getNetworkForSocket(unsigned * netId,int socketFd)446*8542734aSAndroid Build Coastguard Worker extern "C" int getNetworkForSocket(unsigned* netId, int socketFd) {
447*8542734aSAndroid Build Coastguard Worker if (!netId || socketFd < 0) {
448*8542734aSAndroid Build Coastguard Worker return -EBADF;
449*8542734aSAndroid Build Coastguard Worker }
450*8542734aSAndroid Build Coastguard Worker Fwmark fwmark;
451*8542734aSAndroid Build Coastguard Worker socklen_t fwmarkLen = sizeof(fwmark.intValue);
452*8542734aSAndroid Build Coastguard Worker if (getsockopt(socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue, &fwmarkLen) == -1) {
453*8542734aSAndroid Build Coastguard Worker return -errno;
454*8542734aSAndroid Build Coastguard Worker }
455*8542734aSAndroid Build Coastguard Worker *netId = fwmark.netId;
456*8542734aSAndroid Build Coastguard Worker return 0;
457*8542734aSAndroid Build Coastguard Worker }
458*8542734aSAndroid Build Coastguard Worker
getNetworkForProcess()459*8542734aSAndroid Build Coastguard Worker extern "C" unsigned getNetworkForProcess() {
460*8542734aSAndroid Build Coastguard Worker return netIdForProcess & ~NETID_USE_LOCAL_NAMESERVERS;
461*8542734aSAndroid Build Coastguard Worker }
462*8542734aSAndroid Build Coastguard Worker
setNetworkForSocket(unsigned netId,int socketFd)463*8542734aSAndroid Build Coastguard Worker extern "C" int setNetworkForSocket(unsigned netId, int socketFd) {
464*8542734aSAndroid Build Coastguard Worker CHECK_SOCKET_IS_MARKABLE(socketFd);
465*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::SELECT_NETWORK, netId, 0, 0};
466*8542734aSAndroid Build Coastguard Worker return FwmarkClient().send(&command, socketFd, nullptr);
467*8542734aSAndroid Build Coastguard Worker }
468*8542734aSAndroid Build Coastguard Worker
setNetworkForProcess(unsigned netId)469*8542734aSAndroid Build Coastguard Worker extern "C" int setNetworkForProcess(unsigned netId) {
470*8542734aSAndroid Build Coastguard Worker return setNetworkForTarget(netId, &netIdForProcess);
471*8542734aSAndroid Build Coastguard Worker }
472*8542734aSAndroid Build Coastguard Worker
setNetworkForResolv(unsigned netId)473*8542734aSAndroid Build Coastguard Worker extern "C" int setNetworkForResolv(unsigned netId) {
474*8542734aSAndroid Build Coastguard Worker return setNetworkForTarget(netId, &netIdForResolv);
475*8542734aSAndroid Build Coastguard Worker }
476*8542734aSAndroid Build Coastguard Worker
protectFromVpn(int socketFd)477*8542734aSAndroid Build Coastguard Worker extern "C" int protectFromVpn(int socketFd) {
478*8542734aSAndroid Build Coastguard Worker CHECK_SOCKET_IS_MARKABLE(socketFd);
479*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::PROTECT_FROM_VPN, 0, 0, 0};
480*8542734aSAndroid Build Coastguard Worker return FwmarkClient().send(&command, socketFd, nullptr);
481*8542734aSAndroid Build Coastguard Worker }
482*8542734aSAndroid Build Coastguard Worker
setNetworkForUser(uid_t uid,int socketFd)483*8542734aSAndroid Build Coastguard Worker extern "C" int setNetworkForUser(uid_t uid, int socketFd) {
484*8542734aSAndroid Build Coastguard Worker CHECK_SOCKET_IS_MARKABLE(socketFd);
485*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::SELECT_FOR_USER, 0, uid, 0};
486*8542734aSAndroid Build Coastguard Worker return FwmarkClient().send(&command, socketFd, nullptr);
487*8542734aSAndroid Build Coastguard Worker }
488*8542734aSAndroid Build Coastguard Worker
queryUserAccess(uid_t uid,unsigned netId)489*8542734aSAndroid Build Coastguard Worker extern "C" int queryUserAccess(uid_t uid, unsigned netId) {
490*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::QUERY_USER_ACCESS, netId, uid, 0};
491*8542734aSAndroid Build Coastguard Worker return FwmarkClient().send(&command, -1, nullptr);
492*8542734aSAndroid Build Coastguard Worker }
493*8542734aSAndroid Build Coastguard Worker
tagSocket(int socketFd,uint32_t tag,uid_t uid)494*8542734aSAndroid Build Coastguard Worker extern "C" int tagSocket(int socketFd, uint32_t tag, uid_t uid) {
495*8542734aSAndroid Build Coastguard Worker CHECK_SOCKET_IS_MARKABLE(socketFd);
496*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::TAG_SOCKET, 0, uid, tag};
497*8542734aSAndroid Build Coastguard Worker return FwmarkClient().send(&command, socketFd, nullptr);
498*8542734aSAndroid Build Coastguard Worker }
499*8542734aSAndroid Build Coastguard Worker
untagSocket(int socketFd)500*8542734aSAndroid Build Coastguard Worker extern "C" int untagSocket(int socketFd) {
501*8542734aSAndroid Build Coastguard Worker CHECK_SOCKET_IS_MARKABLE(socketFd);
502*8542734aSAndroid Build Coastguard Worker FwmarkCommand command = {FwmarkCommand::UNTAG_SOCKET, 0, 0, 0};
503*8542734aSAndroid Build Coastguard Worker return FwmarkClient().send(&command, socketFd, nullptr);
504*8542734aSAndroid Build Coastguard Worker }
505*8542734aSAndroid Build Coastguard Worker
resNetworkQuery(unsigned netId,const char * dname,int ns_class,int ns_type,uint32_t flags)506*8542734aSAndroid Build Coastguard Worker extern "C" int resNetworkQuery(unsigned netId, const char* dname, int ns_class, int ns_type,
507*8542734aSAndroid Build Coastguard Worker uint32_t flags) {
508*8542734aSAndroid Build Coastguard Worker std::vector<uint8_t> buf(MAX_CMD_SIZE, 0);
509*8542734aSAndroid Build Coastguard Worker int len = res_mkquery(ns_o_query, dname, ns_class, ns_type, nullptr, 0, nullptr, buf.data(),
510*8542734aSAndroid Build Coastguard Worker MAX_CMD_SIZE);
511*8542734aSAndroid Build Coastguard Worker
512*8542734aSAndroid Build Coastguard Worker return resNetworkSend(netId, buf.data(), len, flags);
513*8542734aSAndroid Build Coastguard Worker }
514*8542734aSAndroid Build Coastguard Worker
resNetworkSend(unsigned netId,const uint8_t * msg,size_t msglen,uint32_t flags)515*8542734aSAndroid Build Coastguard Worker extern "C" int resNetworkSend(unsigned netId, const uint8_t* msg, size_t msglen, uint32_t flags) {
516*8542734aSAndroid Build Coastguard Worker // Encode
517*8542734aSAndroid Build Coastguard Worker // Base 64 encodes every 3 bytes into 4 characters, but then adds padding to the next
518*8542734aSAndroid Build Coastguard Worker // multiple of 4 and a \0
519*8542734aSAndroid Build Coastguard Worker const size_t encodedLen = divCeil(msglen, 3) * 4 + 1;
520*8542734aSAndroid Build Coastguard Worker std::string encodedQuery(encodedLen - 1, 0);
521*8542734aSAndroid Build Coastguard Worker int enLen = b64_ntop(msg, msglen, encodedQuery.data(), encodedLen);
522*8542734aSAndroid Build Coastguard Worker
523*8542734aSAndroid Build Coastguard Worker if (enLen < 0) {
524*8542734aSAndroid Build Coastguard Worker // Unexpected behavior, encode failed
525*8542734aSAndroid Build Coastguard Worker // b64_ntop only fails when size is too long.
526*8542734aSAndroid Build Coastguard Worker return -EMSGSIZE;
527*8542734aSAndroid Build Coastguard Worker }
528*8542734aSAndroid Build Coastguard Worker // Send
529*8542734aSAndroid Build Coastguard Worker netId = getNetworkForResolv(netId);
530*8542734aSAndroid Build Coastguard Worker const std::string cmd = "resnsend " + std::to_string(netId) + " " + std::to_string(flags) +
531*8542734aSAndroid Build Coastguard Worker " " + encodedQuery + '\0';
532*8542734aSAndroid Build Coastguard Worker if (cmd.size() > MAX_CMD_SIZE) {
533*8542734aSAndroid Build Coastguard Worker // Cmd size must less than buffer size of FrameworkListener
534*8542734aSAndroid Build Coastguard Worker return -EMSGSIZE;
535*8542734aSAndroid Build Coastguard Worker }
536*8542734aSAndroid Build Coastguard Worker int fd = dns_open_proxy();
537*8542734aSAndroid Build Coastguard Worker if (fd == -1) {
538*8542734aSAndroid Build Coastguard Worker return -errno;
539*8542734aSAndroid Build Coastguard Worker }
540*8542734aSAndroid Build Coastguard Worker ssize_t rc = sendData(fd, cmd.c_str(), cmd.size());
541*8542734aSAndroid Build Coastguard Worker if (rc < 0) {
542*8542734aSAndroid Build Coastguard Worker close(fd);
543*8542734aSAndroid Build Coastguard Worker return rc;
544*8542734aSAndroid Build Coastguard Worker }
545*8542734aSAndroid Build Coastguard Worker shutdown(fd, SHUT_WR);
546*8542734aSAndroid Build Coastguard Worker return fd;
547*8542734aSAndroid Build Coastguard Worker }
548*8542734aSAndroid Build Coastguard Worker
resNetworkResult(int fd,int * rcode,uint8_t * answer,size_t anslen)549*8542734aSAndroid Build Coastguard Worker extern "C" int resNetworkResult(int fd, int* rcode, uint8_t* answer, size_t anslen) {
550*8542734aSAndroid Build Coastguard Worker int32_t result = 0;
551*8542734aSAndroid Build Coastguard Worker unique_fd ufd(fd);
552*8542734aSAndroid Build Coastguard Worker // Read -errno/rcode
553*8542734aSAndroid Build Coastguard Worker if (!readBE32(fd, &result)) {
554*8542734aSAndroid Build Coastguard Worker // Unexpected behavior, read -errno/rcode fail
555*8542734aSAndroid Build Coastguard Worker return -errno;
556*8542734aSAndroid Build Coastguard Worker }
557*8542734aSAndroid Build Coastguard Worker if (result < 0) {
558*8542734aSAndroid Build Coastguard Worker // result < 0, it's -errno
559*8542734aSAndroid Build Coastguard Worker return result;
560*8542734aSAndroid Build Coastguard Worker }
561*8542734aSAndroid Build Coastguard Worker // result >= 0, it's rcode
562*8542734aSAndroid Build Coastguard Worker *rcode = result;
563*8542734aSAndroid Build Coastguard Worker
564*8542734aSAndroid Build Coastguard Worker // Read answer
565*8542734aSAndroid Build Coastguard Worker int32_t size = 0;
566*8542734aSAndroid Build Coastguard Worker if (!readBE32(fd, &size)) {
567*8542734aSAndroid Build Coastguard Worker // Unexpected behavior, read ans len fail
568*8542734aSAndroid Build Coastguard Worker return -EREMOTEIO;
569*8542734aSAndroid Build Coastguard Worker }
570*8542734aSAndroid Build Coastguard Worker if (anslen < static_cast<size_t>(size)) {
571*8542734aSAndroid Build Coastguard Worker // Answer buffer is too small
572*8542734aSAndroid Build Coastguard Worker return -EMSGSIZE;
573*8542734aSAndroid Build Coastguard Worker }
574*8542734aSAndroid Build Coastguard Worker int rc = readData(fd, answer, size);
575*8542734aSAndroid Build Coastguard Worker if (rc < 0) {
576*8542734aSAndroid Build Coastguard Worker // Reading the answer failed.
577*8542734aSAndroid Build Coastguard Worker return rc;
578*8542734aSAndroid Build Coastguard Worker }
579*8542734aSAndroid Build Coastguard Worker return size;
580*8542734aSAndroid Build Coastguard Worker }
581*8542734aSAndroid Build Coastguard Worker
resNetworkCancel(int fd)582*8542734aSAndroid Build Coastguard Worker extern "C" void resNetworkCancel(int fd) {
583*8542734aSAndroid Build Coastguard Worker close(fd);
584*8542734aSAndroid Build Coastguard Worker }
585*8542734aSAndroid Build Coastguard Worker
setAllowNetworkingForProcess(bool allowNetworking)586*8542734aSAndroid Build Coastguard Worker extern "C" void setAllowNetworkingForProcess(bool allowNetworking) {
587*8542734aSAndroid Build Coastguard Worker allowNetworkingForProcess.store(allowNetworking);
588*8542734aSAndroid Build Coastguard Worker }
589*8542734aSAndroid Build Coastguard Worker
getNetworkForDns(unsigned * dnsNetId)590*8542734aSAndroid Build Coastguard Worker extern "C" int getNetworkForDns(unsigned* dnsNetId) {
591*8542734aSAndroid Build Coastguard Worker if (dnsNetId == nullptr) return -EFAULT;
592*8542734aSAndroid Build Coastguard Worker int fd = dns_open_proxy();
593*8542734aSAndroid Build Coastguard Worker if (fd == -1) {
594*8542734aSAndroid Build Coastguard Worker return -errno;
595*8542734aSAndroid Build Coastguard Worker }
596*8542734aSAndroid Build Coastguard Worker unique_fd ufd(fd);
597*8542734aSAndroid Build Coastguard Worker return getNetworkForDnsInternal(fd, dnsNetId);
598*8542734aSAndroid Build Coastguard Worker }
599*8542734aSAndroid Build Coastguard Worker
getNetworkForDnsInternal(int fd,unsigned * dnsNetId)600*8542734aSAndroid Build Coastguard Worker int getNetworkForDnsInternal(int fd, unsigned* dnsNetId) {
601*8542734aSAndroid Build Coastguard Worker if (fd == -1) {
602*8542734aSAndroid Build Coastguard Worker return -EBADF;
603*8542734aSAndroid Build Coastguard Worker }
604*8542734aSAndroid Build Coastguard Worker
605*8542734aSAndroid Build Coastguard Worker unsigned resolvNetId = getNetworkForResolv(NETID_UNSET);
606*8542734aSAndroid Build Coastguard Worker
607*8542734aSAndroid Build Coastguard Worker const std::string cmd = "getdnsnetid " + std::to_string(resolvNetId);
608*8542734aSAndroid Build Coastguard Worker ssize_t rc = sendData(fd, cmd.c_str(), cmd.size() + 1);
609*8542734aSAndroid Build Coastguard Worker if (rc < 0) {
610*8542734aSAndroid Build Coastguard Worker return rc;
611*8542734aSAndroid Build Coastguard Worker }
612*8542734aSAndroid Build Coastguard Worker
613*8542734aSAndroid Build Coastguard Worker int responseCode = 0;
614*8542734aSAndroid Build Coastguard Worker // Read responseCode
615*8542734aSAndroid Build Coastguard Worker if (!readResponseCode(fd, &responseCode)) {
616*8542734aSAndroid Build Coastguard Worker // Unexpected behavior, read responseCode fail
617*8542734aSAndroid Build Coastguard Worker return -errno;
618*8542734aSAndroid Build Coastguard Worker }
619*8542734aSAndroid Build Coastguard Worker
620*8542734aSAndroid Build Coastguard Worker if (responseCode != ResponseCode::DnsProxyQueryResult) {
621*8542734aSAndroid Build Coastguard Worker return -EOPNOTSUPP;
622*8542734aSAndroid Build Coastguard Worker }
623*8542734aSAndroid Build Coastguard Worker
624*8542734aSAndroid Build Coastguard Worker int32_t result = 0;
625*8542734aSAndroid Build Coastguard Worker // Read -errno/dnsnetid
626*8542734aSAndroid Build Coastguard Worker if (!readBE32(fd, &result)) {
627*8542734aSAndroid Build Coastguard Worker // Unexpected behavior, read -errno/dnsnetid fail
628*8542734aSAndroid Build Coastguard Worker return -errno;
629*8542734aSAndroid Build Coastguard Worker }
630*8542734aSAndroid Build Coastguard Worker
631*8542734aSAndroid Build Coastguard Worker *dnsNetId = result;
632*8542734aSAndroid Build Coastguard Worker
633*8542734aSAndroid Build Coastguard Worker return 0;
634*8542734aSAndroid Build Coastguard Worker }
635