blob: 643188bd2261224744f0bef4fc4c4f77d3c92093 [file] [log] [blame]
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -070017#include "NetdClient.h"
18
Michal Karpinski4b9b78a2016-10-06 19:33:55 +010019#include <arpa/inet.h>
Dan Albertaa1be2b2015-01-06 09:36:17 -080020#include <errno.h>
Michal Karpinski4b9b78a2016-10-06 19:33:55 +010021#include <math.h>
Luke Huangc68f1b92018-11-21 20:13:38 +080022#include <resolv.h>
Luke Huangc5efae92018-11-19 17:45:13 +080023#include <stdlib.h>
Dan Albertaa1be2b2015-01-06 09:36:17 -080024#include <sys/socket.h>
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -080025#include <sys/system_properties.h>
Luke Huangc5efae92018-11-19 17:45:13 +080026#include <sys/un.h>
Dan Albertaa1be2b2015-01-06 09:36:17 -080027#include <unistd.h>
28
29#include <atomic>
Luke Huangc68f1b92018-11-21 20:13:38 +080030#include <string>
31#include <vector>
Dan Albertaa1be2b2015-01-06 09:36:17 -080032
Luke Huang63df9482019-05-25 18:24:03 +080033#include <android-base/parseint.h>
34#include <android-base/unique_fd.h>
35
Sreeram Ramachandran4d4c8b72014-06-20 11:59:40 -070036#include "Fwmark.h"
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -070037#include "FwmarkClient.h"
38#include "FwmarkCommand.h"
Luke Huang63df9482019-05-25 18:24:03 +080039#include "netdclient_priv.h"
Luke Huang185098d2019-05-20 16:17:12 +080040#include "netdutils/ResponseCode.h"
Mike Yue7e332f2019-03-13 17:15:48 +080041#include "netdutils/Stopwatch.h"
Bernie Innocenti189eb502018-10-01 23:10:18 +090042#include "netid_client.h"
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -070043
Luke Huang185098d2019-05-20 16:17:12 +080044using android::base::ParseInt;
Luke Huangc68f1b92018-11-21 20:13:38 +080045using android::base::unique_fd;
Luke Huang185098d2019-05-20 16:17:12 +080046using android::netdutils::ResponseCode;
Mike Yue7e332f2019-03-13 17:15:48 +080047using android::netdutils::Stopwatch;
Luke Huangc68f1b92018-11-21 20:13:38 +080048
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -070049namespace {
50
Luke Huangc68f1b92018-11-21 20:13:38 +080051// Keep this in sync with CMD_BUF_SIZE in FrameworkListener.cpp.
Luke Huange92b75e2019-03-26 17:56:49 +080052constexpr size_t MAX_CMD_SIZE = 4096;
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -080053// Whether sendto(), sendmsg(), sendmmsg() in libc are shimmed or not. This property is evaluated at
Ken Chen1782aea2020-02-21 16:30:47 +080054// process start time and cannot change at runtime on a given device.
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -080055constexpr char PROPERTY_REDIRECT_SOCKET_CALLS[] = "ro.vendor.redirect_socket_calls";
56// Whether some shimmed functions dispatch FwmarkCommand or not. The property can be changed by
57// System Server at runtime. Note: accept4(), socket(), connect() are always shimmed.
58constexpr char PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED[] = "net.redirect_socket_calls.hooked";
Luke Huangc68f1b92018-11-21 20:13:38 +080059
Sreeram Ramachandran9fa2b132014-06-03 12:51:08 -070060std::atomic_uint netIdForProcess(NETID_UNSET);
61std::atomic_uint netIdForResolv(NETID_UNSET);
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -070062
63typedef int (*Accept4FunctionType)(int, sockaddr*, socklen_t*, int);
64typedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t);
65typedef int (*SocketFunctionType)(int, int, int);
66typedef unsigned (*NetIdForResolvFunctionType)(unsigned);
Luke Huangc5efae92018-11-19 17:45:13 +080067typedef int (*DnsOpenProxyType)();
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -080068typedef int (*SendmmsgFunctionType)(int, const mmsghdr*, unsigned int, int);
69typedef ssize_t (*SendmsgFunctionType)(int, const msghdr*, unsigned int);
70typedef int (*SendtoFunctionType)(int, const void*, size_t, int, const sockaddr*, socklen_t);
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -070071
72// These variables are only modified at startup (when libc.so is loaded) and never afterwards, so
73// it's okay that they are read later at runtime without a lock.
Yi Kongbdfd57e2018-07-25 13:26:10 -070074Accept4FunctionType libcAccept4 = nullptr;
75ConnectFunctionType libcConnect = nullptr;
76SocketFunctionType libcSocket = nullptr;
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -080077SendmmsgFunctionType libcSendmmsg = nullptr;
78SendmsgFunctionType libcSendmsg = nullptr;
79SendtoFunctionType libcSendto = nullptr;
80
81static bool propertyValueIsTrue(const char* prop_name) {
82 char prop_value[PROP_VALUE_MAX] = {0};
Ken Chen1782aea2020-02-21 16:30:47 +080083 if (__system_property_get(prop_name, prop_value) > 0) {
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -080084 if (strcmp(prop_value, "true") == 0) {
85 return true;
86 }
87 }
88 return false;
89}
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -070090
Ken Chen1782aea2020-02-21 16:30:47 +080091static bool redirectSocketCallsIsTrue() {
92 static bool cached_result = propertyValueIsTrue("ro.vendor.redirect_socket_calls");
93 return cached_result;
94}
95
Lorenzo Colitti24601da2019-02-14 00:48:36 +090096int checkSocket(int socketFd) {
97 if (socketFd < 0) {
98 return -EBADF;
99 }
100 int family;
101 socklen_t familyLen = sizeof(family);
102 if (getsockopt(socketFd, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) {
103 return -errno;
104 }
105 if (!FwmarkClient::shouldSetFwmark(family)) {
106 return -EAFNOSUPPORT;
107 }
108 return 0;
109}
110
111bool shouldMarkSocket(int socketFd, const sockaddr* dst) {
112 // Only mark inet sockets that are connecting to inet destinations. This excludes, for example,
113 // inet sockets connecting to AF_UNSPEC (i.e., being disconnected), and non-inet sockets that
114 // for some reason the caller wants to attempt to connect to an inet destination.
115 return dst && FwmarkClient::shouldSetFwmark(dst->sa_family) && (checkSocket(socketFd) == 0);
116}
117
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700118int closeFdAndSetErrno(int fd, int error) {
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700119 close(fd);
Sreeram Ramachandran3a069e62014-06-22 11:02:57 -0700120 errno = -error;
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700121 return -1;
122}
123
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700124int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) {
125 int acceptedSocket = libcAccept4(sockfd, addr, addrlen, flags);
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700126 if (acceptedSocket == -1) {
127 return -1;
128 }
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700129 int family;
130 if (addr) {
131 family = addr->sa_family;
132 } else {
133 socklen_t familyLen = sizeof(family);
134 if (getsockopt(acceptedSocket, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) {
Sreeram Ramachandran3a069e62014-06-22 11:02:57 -0700135 return closeFdAndSetErrno(acceptedSocket, -errno);
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700136 }
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700137 }
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700138 if (FwmarkClient::shouldSetFwmark(family)) {
Chenbo Feng9944ba82017-10-10 17:33:20 -0700139 FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0, 0};
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100140 if (int error = FwmarkClient().send(&command, acceptedSocket, nullptr)) {
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700141 return closeFdAndSetErrno(acceptedSocket, error);
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700142 }
143 }
144 return acceptedSocket;
145}
146
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700147int netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
Lorenzo Colitti24601da2019-02-14 00:48:36 +0900148 const bool shouldSetFwmark = shouldMarkSocket(sockfd, addr);
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100149 if (shouldSetFwmark) {
Chenbo Feng9944ba82017-10-10 17:33:20 -0700150 FwmarkCommand command = {FwmarkCommand::ON_CONNECT, 0, 0, 0};
Ken Chen1782aea2020-02-21 16:30:47 +0800151 int error;
152 if (redirectSocketCallsIsTrue()) {
153 FwmarkConnectInfo connectInfo(0, 0, addr);
154 error = FwmarkClient().send(&command, sockfd, &connectInfo);
155 } else {
156 error = FwmarkClient().send(&command, sockfd, nullptr);
157 }
158
159 if (error) {
Sreeram Ramachandran3a069e62014-06-22 11:02:57 -0700160 errno = -error;
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700161 return -1;
162 }
163 }
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100164 // Latency measurement does not include time of sending commands to Fwmark
165 Stopwatch s;
Hugo Benichi794c5c72016-10-31 15:07:23 +0900166 const int ret = libcConnect(sockfd, addr, addrlen);
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100167 // Save errno so it isn't clobbered by sending ON_CONNECT_COMPLETE
168 const int connectErrno = errno;
Bernie Innocenti196f1b82019-05-20 16:34:16 +0900169 const auto latencyMs = static_cast<unsigned>(s.timeTakenUs() / 1000);
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100170 // Send an ON_CONNECT_COMPLETE command that includes sockaddr and connect latency for reporting
markchien3a976372019-07-02 16:20:08 +0800171 if (shouldSetFwmark) {
Hugo Benichi794c5c72016-10-31 15:07:23 +0900172 FwmarkConnectInfo connectInfo(ret == 0 ? 0 : connectErrno, latencyMs, addr);
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100173 // TODO: get the netId from the socket mark once we have continuous benchmark runs
174 FwmarkCommand command = {FwmarkCommand::ON_CONNECT_COMPLETE, /* netId (ignored) */ 0,
Chenbo Feng9944ba82017-10-10 17:33:20 -0700175 /* uid (filled in by the server) */ 0, 0};
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100176 // Ignore return value since it's only used for logging
177 FwmarkClient().send(&command, sockfd, &connectInfo);
178 }
179 errno = connectErrno;
180 return ret;
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700181}
182
183int netdClientSocket(int domain, int type, int protocol) {
184 int socketFd = libcSocket(domain, type, protocol);
185 if (socketFd == -1) {
186 return -1;
187 }
Lorenzo Colitti6b001262019-01-30 22:43:36 +0900188 unsigned netId = netIdForProcess & ~NETID_USE_LOCAL_NAMESERVERS;
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700189 if (netId != NETID_UNSET && FwmarkClient::shouldSetFwmark(domain)) {
Sreeram Ramachandrand36c49c2014-07-02 14:49:33 -0700190 if (int error = setNetworkForSocket(netId, socketFd)) {
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700191 return closeFdAndSetErrno(socketFd, error);
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700192 }
193 }
194 return socketFd;
195}
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700196
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800197int netdClientSendmmsg(int sockfd, const mmsghdr* msgs, unsigned int msgcount, int flags) {
Treehugger Robot1b966652020-04-07 05:50:41 +0000198 if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800199 const sockaddr* addr = nullptr;
200 if ((msgcount > 0) && (msgs != nullptr) && (msgs[0].msg_hdr.msg_name != nullptr)) {
201 addr = reinterpret_cast<const sockaddr*>(msgs[0].msg_hdr.msg_name);
202 if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
203 FwmarkConnectInfo sendmmsgInfo(0, 0, addr);
204 FwmarkCommand command = {FwmarkCommand::ON_SENDMMSG, 0, 0, 0};
205 FwmarkClient().send(&command, sockfd, &sendmmsgInfo);
206 }
207 }
208 }
209 return libcSendmmsg(sockfd, msgs, msgcount, flags);
210}
211
212ssize_t netdClientSendmsg(int sockfd, const msghdr* msg, unsigned int flags) {
Treehugger Robot1b966652020-04-07 05:50:41 +0000213 if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800214 const sockaddr* addr = nullptr;
215 if ((msg != nullptr) && (msg->msg_name != nullptr)) {
216 addr = reinterpret_cast<const sockaddr*>(msg->msg_name);
217 if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
218 FwmarkConnectInfo sendmsgInfo(0, 0, addr);
219 FwmarkCommand command = {FwmarkCommand::ON_SENDMSG, 0, 0, 0};
220 FwmarkClient().send(&command, sockfd, &sendmsgInfo);
221 }
222 }
223 }
224 return libcSendmsg(sockfd, msg, flags);
225}
226
227int netdClientSendto(int sockfd, const void* buf, size_t bufsize, int flags, const sockaddr* addr,
228 socklen_t addrlen) {
Treehugger Robot1b966652020-04-07 05:50:41 +0000229 if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800230 if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
231 FwmarkConnectInfo sendtoInfo(0, 0, addr);
232 FwmarkCommand command = {FwmarkCommand::ON_SENDTO, 0, 0, 0};
233 FwmarkClient().send(&command, sockfd, &sendtoInfo);
234 }
235 }
236 return libcSendto(sockfd, buf, bufsize, flags, addr, addrlen);
237}
238
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700239unsigned getNetworkForResolv(unsigned netId) {
240 if (netId != NETID_UNSET) {
241 return netId;
242 }
Erik Kline1564d482018-03-07 17:09:35 +0900243 // Special case for DNS-over-TLS bypass; b/72345192 .
244 if ((netIdForResolv & ~NETID_USE_LOCAL_NAMESERVERS) != NETID_UNSET) {
245 return netIdForResolv;
246 }
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700247 netId = netIdForProcess;
248 if (netId != NETID_UNSET) {
249 return netId;
250 }
251 return netIdForResolv;
252}
253
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700254int setNetworkForTarget(unsigned netId, std::atomic_uint* target) {
Erik Kline1564d482018-03-07 17:09:35 +0900255 const unsigned requestedNetId = netId;
256 netId &= ~NETID_USE_LOCAL_NAMESERVERS;
257
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700258 if (netId == NETID_UNSET) {
259 *target = netId;
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700260 return 0;
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700261 }
262 // Verify that we are allowed to use |netId|, by creating a socket and trying to have it marked
Sreeram Ramachandran27560452014-05-30 19:59:51 -0700263 // with the netId. Call libcSocket() directly; else the socket creation (via netdClientSocket())
264 // might itself cause another check with the fwmark server, which would be wasteful.
Luke Huangc5efae92018-11-19 17:45:13 +0800265
266 const auto socketFunc = libcSocket ? libcSocket : socket;
267 int socketFd = socketFunc(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700268 if (socketFd < 0) {
Sreeram Ramachandran3a069e62014-06-22 11:02:57 -0700269 return -errno;
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700270 }
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700271 int error = setNetworkForSocket(netId, socketFd);
272 if (!error) {
Lorenzo Colitti6b001262019-01-30 22:43:36 +0900273 *target = requestedNetId;
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700274 }
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700275 close(socketFd);
276 return error;
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700277}
278
Luke Huangc5efae92018-11-19 17:45:13 +0800279int dns_open_proxy() {
280 const char* cache_mode = getenv("ANDROID_DNS_MODE");
281 const bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
282 if (!use_proxy) {
Luke Huang63df9482019-05-25 18:24:03 +0800283 errno = ENOSYS;
Luke Huangc5efae92018-11-19 17:45:13 +0800284 return -1;
285 }
286
287 const auto socketFunc = libcSocket ? libcSocket : socket;
288 int s = socketFunc(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
289 if (s == -1) {
290 return -1;
291 }
292 const int one = 1;
293 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
294
295 static const struct sockaddr_un proxy_addr = {
296 .sun_family = AF_UNIX,
297 .sun_path = "/dev/socket/dnsproxyd",
298 };
299
300 const auto connectFunc = libcConnect ? libcConnect : connect;
301 if (TEMP_FAILURE_RETRY(
302 connectFunc(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
Luke Huang63df9482019-05-25 18:24:03 +0800303 // Store the errno for connect because we only care about why we can't connect to dnsproxyd
304 int storedErrno = errno;
Luke Huangc5efae92018-11-19 17:45:13 +0800305 close(s);
Luke Huang63df9482019-05-25 18:24:03 +0800306 errno = storedErrno;
Luke Huangc5efae92018-11-19 17:45:13 +0800307 return -1;
308 }
309
310 return s;
311}
312
Luke Huangc68f1b92018-11-21 20:13:38 +0800313auto divCeil(size_t dividend, size_t divisor) {
314 return ((dividend + divisor - 1) / divisor);
315}
316
317// FrameworkListener only does only read() call, and fails if the read doesn't contain \0
318// Do single write here
319int sendData(int fd, const void* buf, size_t size) {
320 if (fd < 0) {
321 return -EBADF;
322 }
323
324 ssize_t rc = TEMP_FAILURE_RETRY(write(fd, (char*) buf, size));
325 if (rc > 0) {
326 return rc;
327 } else if (rc == 0) {
328 return -EIO;
329 } else {
330 return -errno;
331 }
332}
333
334int readData(int fd, void* buf, size_t size) {
335 if (fd < 0) {
336 return -EBADF;
337 }
338
339 size_t current = 0;
340 for (;;) {
341 ssize_t rc = TEMP_FAILURE_RETRY(read(fd, (char*) buf + current, size - current));
342 if (rc > 0) {
343 current += rc;
344 if (current == size) {
345 break;
346 }
347 } else if (rc == 0) {
348 return -EIO;
349 } else {
350 return -errno;
351 }
352 }
353 return 0;
354}
355
356bool readBE32(int fd, int32_t* result) {
357 int32_t tmp;
Luke Huang63df9482019-05-25 18:24:03 +0800358 ssize_t n = TEMP_FAILURE_RETRY(read(fd, &tmp, sizeof(tmp)));
359 if (n < static_cast<ssize_t>(sizeof(tmp))) {
Luke Huangc68f1b92018-11-21 20:13:38 +0800360 return false;
361 }
362 *result = ntohl(tmp);
363 return true;
364}
365
Luke Huang63df9482019-05-25 18:24:03 +0800366bool readResponseCode(int fd, int* result) {
Luke Huang185098d2019-05-20 16:17:12 +0800367 char buf[4];
Luke Huang63df9482019-05-25 18:24:03 +0800368 ssize_t n = TEMP_FAILURE_RETRY(read(fd, &buf, sizeof(buf)));
369 if (n < static_cast<ssize_t>(sizeof(buf))) {
Luke Huang185098d2019-05-20 16:17:12 +0800370 return false;
371 }
372
373 // The format of response code is 3 bytes followed by a space.
374 buf[3] = '\0';
375 if (!ParseInt(buf, result)) {
376 errno = EINVAL;
377 return false;
378 }
379
380 return true;
381}
382
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700383} // namespace
384
Treehugger Robot1b966652020-04-07 05:50:41 +0000385#define CHECK_SOCKET_IS_MARKABLE(sock) \
386 do { \
387 int err = checkSocket(sock); \
388 if (err) return err; \
389 } while (false)
Remi NGUYEN VANeabc5da2018-04-24 18:54:58 +0900390
Ken Chen1782aea2020-02-21 16:30:47 +0800391#define HOOK_ON_FUNC(remoteFunc, nativeFunc, localFunc) \
392 do { \
Treehugger Robot1b966652020-04-07 05:50:41 +0000393 if ((remoteFunc) && *(remoteFunc)) { \
394 (nativeFunc) = *(remoteFunc); \
395 *(remoteFunc) = (localFunc); \
Ken Chen1782aea2020-02-21 16:30:47 +0800396 } \
397 } while (false)
398
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700399// accept() just calls accept4(..., 0), so there's no need to handle accept() separately.
400extern "C" void netdClientInitAccept4(Accept4FunctionType* function) {
Ken Chen1782aea2020-02-21 16:30:47 +0800401 HOOK_ON_FUNC(function, libcAccept4, netdClientAccept4);
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700402}
403
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700404extern "C" void netdClientInitConnect(ConnectFunctionType* function) {
Ken Chen1782aea2020-02-21 16:30:47 +0800405 HOOK_ON_FUNC(function, libcConnect, netdClientConnect);
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700406}
407
Sreeram Ramachandran5fc27572014-05-21 13:08:34 -0700408extern "C" void netdClientInitSocket(SocketFunctionType* function) {
Ken Chen1782aea2020-02-21 16:30:47 +0800409 HOOK_ON_FUNC(function, libcSocket, netdClientSocket);
Sreeram Ramachandranf4cfad32014-05-21 08:54:07 -0700410}
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700411
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800412extern "C" void netdClientInitSendmmsg(SendmmsgFunctionType* function) {
413 if (!propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS)) {
414 return;
415 }
Ken Chen1782aea2020-02-21 16:30:47 +0800416 HOOK_ON_FUNC(function, libcSendmmsg, netdClientSendmmsg);
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800417}
418
419extern "C" void netdClientInitSendmsg(SendmsgFunctionType* function) {
420 if (!propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS)) {
421 return;
422 }
Ken Chen1782aea2020-02-21 16:30:47 +0800423 HOOK_ON_FUNC(function, libcSendmsg, netdClientSendmsg);
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800424}
425
426extern "C" void netdClientInitSendto(SendtoFunctionType* function) {
427 if (!propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS)) {
428 return;
429 }
Ken Chen1782aea2020-02-21 16:30:47 +0800430 HOOK_ON_FUNC(function, libcSendto, netdClientSendto);
Praveen Moongalam Thyagarajanf24eb882019-12-18 11:59:47 -0800431}
432
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700433extern "C" void netdClientInitNetIdForResolv(NetIdForResolvFunctionType* function) {
434 if (function) {
435 *function = getNetworkForResolv;
436 }
437}
438
Luke Huangc5efae92018-11-19 17:45:13 +0800439extern "C" void netdClientInitDnsOpenProxy(DnsOpenProxyType* function) {
440 if (function) {
441 *function = dns_open_proxy;
442 }
443}
444
Sreeram Ramachandran4d4c8b72014-06-20 11:59:40 -0700445extern "C" int getNetworkForSocket(unsigned* netId, int socketFd) {
446 if (!netId || socketFd < 0) {
Sreeram Ramachandran3a069e62014-06-22 11:02:57 -0700447 return -EBADF;
Sreeram Ramachandran4d4c8b72014-06-20 11:59:40 -0700448 }
449 Fwmark fwmark;
450 socklen_t fwmarkLen = sizeof(fwmark.intValue);
451 if (getsockopt(socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue, &fwmarkLen) == -1) {
Sreeram Ramachandran3a069e62014-06-22 11:02:57 -0700452 return -errno;
Sreeram Ramachandran4d4c8b72014-06-20 11:59:40 -0700453 }
454 *netId = fwmark.netId;
455 return 0;
456}
457
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700458extern "C" unsigned getNetworkForProcess() {
Lorenzo Colitti6b001262019-01-30 22:43:36 +0900459 return netIdForProcess & ~NETID_USE_LOCAL_NAMESERVERS;
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700460}
461
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700462extern "C" int setNetworkForSocket(unsigned netId, int socketFd) {
Remi NGUYEN VANeabc5da2018-04-24 18:54:58 +0900463 CHECK_SOCKET_IS_MARKABLE(socketFd);
Chenbo Feng9944ba82017-10-10 17:33:20 -0700464 FwmarkCommand command = {FwmarkCommand::SELECT_NETWORK, netId, 0, 0};
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100465 return FwmarkClient().send(&command, socketFd, nullptr);
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700466}
467
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700468extern "C" int setNetworkForProcess(unsigned netId) {
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700469 return setNetworkForTarget(netId, &netIdForProcess);
470}
471
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700472extern "C" int setNetworkForResolv(unsigned netId) {
Sreeram Ramachandranefbe05d2014-05-21 11:41:39 -0700473 return setNetworkForTarget(netId, &netIdForResolv);
474}
Sreeram Ramachandrand794e582014-06-19 10:03:07 -0700475
Sreeram Ramachandran31f42102014-06-20 11:51:48 -0700476extern "C" int protectFromVpn(int socketFd) {
Treehugger Robot1b966652020-04-07 05:50:41 +0000477 CHECK_SOCKET_IS_MARKABLE(socketFd);
Chenbo Feng9944ba82017-10-10 17:33:20 -0700478 FwmarkCommand command = {FwmarkCommand::PROTECT_FROM_VPN, 0, 0, 0};
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100479 return FwmarkClient().send(&command, socketFd, nullptr);
Sreeram Ramachandrana69d9472014-07-11 16:27:02 -0700480}
481
482extern "C" int setNetworkForUser(uid_t uid, int socketFd) {
Remi NGUYEN VANeabc5da2018-04-24 18:54:58 +0900483 CHECK_SOCKET_IS_MARKABLE(socketFd);
Chenbo Feng9944ba82017-10-10 17:33:20 -0700484 FwmarkCommand command = {FwmarkCommand::SELECT_FOR_USER, 0, uid, 0};
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100485 return FwmarkClient().send(&command, socketFd, nullptr);
Paul Jensend1df5972015-05-06 07:29:56 -0400486}
487
488extern "C" int queryUserAccess(uid_t uid, unsigned netId) {
Chenbo Feng9944ba82017-10-10 17:33:20 -0700489 FwmarkCommand command = {FwmarkCommand::QUERY_USER_ACCESS, netId, uid, 0};
490 return FwmarkClient().send(&command, -1, nullptr);
491}
492
493extern "C" int tagSocket(int socketFd, uint32_t tag, uid_t uid) {
Remi NGUYEN VANeabc5da2018-04-24 18:54:58 +0900494 CHECK_SOCKET_IS_MARKABLE(socketFd);
Chenbo Feng9944ba82017-10-10 17:33:20 -0700495 FwmarkCommand command = {FwmarkCommand::TAG_SOCKET, 0, uid, tag};
496 return FwmarkClient().send(&command, socketFd, nullptr);
497}
498
499extern "C" int untagSocket(int socketFd) {
Remi NGUYEN VANeabc5da2018-04-24 18:54:58 +0900500 CHECK_SOCKET_IS_MARKABLE(socketFd);
Chenbo Feng9944ba82017-10-10 17:33:20 -0700501 FwmarkCommand command = {FwmarkCommand::UNTAG_SOCKET, 0, 0, 0};
502 return FwmarkClient().send(&command, socketFd, nullptr);
503}
504
505extern "C" int setCounterSet(uint32_t counterSet, uid_t uid) {
506 FwmarkCommand command = {FwmarkCommand::SET_COUNTERSET, 0, uid, counterSet};
507 return FwmarkClient().send(&command, -1, nullptr);
508}
509
510extern "C" int deleteTagData(uint32_t tag, uid_t uid) {
511 FwmarkCommand command = {FwmarkCommand::DELETE_TAGDATA, 0, uid, tag};
Michal Karpinski4b9b78a2016-10-06 19:33:55 +0100512 return FwmarkClient().send(&command, -1, nullptr);
Sreeram Ramachandrand794e582014-06-19 10:03:07 -0700513}
Luke Huangc68f1b92018-11-21 20:13:38 +0800514
Luke Huang110c54e2018-12-20 14:39:58 +0800515extern "C" int resNetworkQuery(unsigned netId, const char* dname, int ns_class, int ns_type,
516 uint32_t flags) {
Luke Huange48fbcb2018-12-17 16:37:33 +0800517 std::vector<uint8_t> buf(MAX_CMD_SIZE, 0);
518 int len = res_mkquery(ns_o_query, dname, ns_class, ns_type, nullptr, 0, nullptr, buf.data(),
519 MAX_CMD_SIZE);
Luke Huangc68f1b92018-11-21 20:13:38 +0800520
Luke Huang110c54e2018-12-20 14:39:58 +0800521 return resNetworkSend(netId, buf.data(), len, flags);
Luke Huangc68f1b92018-11-21 20:13:38 +0800522}
523
Luke Huang952d0942018-12-26 16:53:03 +0800524extern "C" int resNetworkSend(unsigned netId, const uint8_t* msg, size_t msglen, uint32_t flags) {
Luke Huangc68f1b92018-11-21 20:13:38 +0800525 // Encode
526 // Base 64 encodes every 3 bytes into 4 characters, but then adds padding to the next
527 // multiple of 4 and a \0
528 const size_t encodedLen = divCeil(msglen, 3) * 4 + 1;
Luke Huange48fbcb2018-12-17 16:37:33 +0800529 std::string encodedQuery(encodedLen - 1, 0);
Luke Huangc68f1b92018-11-21 20:13:38 +0800530 int enLen = b64_ntop(msg, msglen, encodedQuery.data(), encodedLen);
531
532 if (enLen < 0) {
533 // Unexpected behavior, encode failed
534 // b64_ntop only fails when size is too long.
535 return -EMSGSIZE;
536 }
537 // Send
538 netId = getNetworkForResolv(netId);
Luke Huang952d0942018-12-26 16:53:03 +0800539 const std::string cmd = "resnsend " + std::to_string(netId) + " " + std::to_string(flags) +
540 " " + encodedQuery + '\0';
Luke Huangc68f1b92018-11-21 20:13:38 +0800541 if (cmd.size() > MAX_CMD_SIZE) {
542 // Cmd size must less than buffer size of FrameworkListener
543 return -EMSGSIZE;
544 }
545 int fd = dns_open_proxy();
546 if (fd == -1) {
547 return -errno;
548 }
549 ssize_t rc = sendData(fd, cmd.c_str(), cmd.size());
550 if (rc < 0) {
551 close(fd);
552 return rc;
553 }
554 shutdown(fd, SHUT_WR);
555 return fd;
556}
557
Luke Huange48fbcb2018-12-17 16:37:33 +0800558extern "C" int resNetworkResult(int fd, int* rcode, uint8_t* answer, size_t anslen) {
Luke Huangc68f1b92018-11-21 20:13:38 +0800559 int32_t result = 0;
560 unique_fd ufd(fd);
561 // Read -errno/rcode
562 if (!readBE32(fd, &result)) {
563 // Unexpected behavior, read -errno/rcode fail
564 return -errno;
565 }
566 if (result < 0) {
567 // result < 0, it's -errno
568 return result;
569 }
570 // result >= 0, it's rcode
571 *rcode = result;
572
573 // Read answer
574 int32_t size = 0;
575 if (!readBE32(fd, &size)) {
576 // Unexpected behavior, read ans len fail
577 return -EREMOTEIO;
578 }
Luke Huange48fbcb2018-12-17 16:37:33 +0800579 if (anslen < static_cast<size_t>(size)) {
Luke Huangc68f1b92018-11-21 20:13:38 +0800580 // Answer buffer is too small
581 return -EMSGSIZE;
582 }
583 int rc = readData(fd, answer, size);
584 if (rc < 0) {
585 // Reading the answer failed.
586 return rc;
587 }
588 return size;
589}
590
591extern "C" void resNetworkCancel(int fd) {
592 close(fd);
Lorenzo Colitti6b001262019-01-30 22:43:36 +0900593}
Luke Huang185098d2019-05-20 16:17:12 +0800594
Luke Huang63df9482019-05-25 18:24:03 +0800595extern "C" int getNetworkForDns(unsigned* dnsNetId) {
596 if (dnsNetId == nullptr) return -EFAULT;
Luke Huang185098d2019-05-20 16:17:12 +0800597 int fd = dns_open_proxy();
598 if (fd == -1) {
599 return -errno;
600 }
601 unique_fd ufd(fd);
Luke Huang63df9482019-05-25 18:24:03 +0800602 return getNetworkForDnsInternal(fd, dnsNetId);
603}
604
605int getNetworkForDnsInternal(int fd, unsigned* dnsNetId) {
606 if (fd == -1) {
607 return -EBADF;
608 }
609
610 unsigned resolvNetId = getNetworkForResolv(NETID_UNSET);
611
612 const std::string cmd = "getdnsnetid " + std::to_string(resolvNetId);
Luke Huang185098d2019-05-20 16:17:12 +0800613 ssize_t rc = sendData(fd, cmd.c_str(), cmd.size() + 1);
614 if (rc < 0) {
615 return rc;
616 }
617
618 int responseCode = 0;
619 // Read responseCode
Luke Huang63df9482019-05-25 18:24:03 +0800620 if (!readResponseCode(fd, &responseCode)) {
Luke Huang185098d2019-05-20 16:17:12 +0800621 // Unexpected behavior, read responseCode fail
622 return -errno;
623 }
624
625 if (responseCode != ResponseCode::DnsProxyQueryResult) {
626 return -EOPNOTSUPP;
627 }
628
629 int32_t result = 0;
630 // Read -errno/dnsnetid
631 if (!readBE32(fd, &result)) {
632 // Unexpected behavior, read -errno/dnsnetid fail
633 return -errno;
634 }
635
Luke Huang63df9482019-05-25 18:24:03 +0800636 *dnsNetId = result;
637
638 return 0;
Luke Huang185098d2019-05-20 16:17:12 +0800639}