2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "NetdClient.h"
20 #include <sys/socket.h>
26 #include "FwmarkClient.h"
27 #include "FwmarkCommand.h"
28 #include "resolv_netid.h"
31 #include "codeaurora/PropClientDispatch.h"
36 std::atomic_uint netIdForProcess(NETID_UNSET);
37 std::atomic_uint netIdForResolv(NETID_UNSET);
39 typedef int (*Accept4FunctionType)(int, sockaddr*, socklen_t*, int);
40 typedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t);
41 typedef int (*SocketFunctionType)(int, int, int);
42 typedef unsigned (*NetIdForResolvFunctionType)(unsigned);
45 typedef void (*SetConnectFunc) (ConnectFunctionType*);
48 // These variables are only modified at startup (when libc.so is loaded) and never afterwards, so
49 // it's okay that they are read later at runtime without a lock.
50 Accept4FunctionType libcAccept4 = 0;
51 ConnectFunctionType libcConnect = 0;
52 SocketFunctionType libcSocket = 0;
54 int closeFdAndSetErrno(int fd, int error) {
60 int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) {
61 int acceptedSocket = libcAccept4(sockfd, addr, addrlen, flags);
62 if (acceptedSocket == -1) {
67 family = addr->sa_family;
69 socklen_t familyLen = sizeof(family);
70 if (getsockopt(acceptedSocket, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) {
71 return closeFdAndSetErrno(acceptedSocket, -errno);
74 if (FwmarkClient::shouldSetFwmark(family)) {
75 FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0};
76 if (int error = FwmarkClient().send(&command, acceptedSocket)) {
77 return closeFdAndSetErrno(acceptedSocket, error);
80 return acceptedSocket;
83 int netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
84 if (sockfd >= 0 && addr && FwmarkClient::shouldSetFwmark(addr->sa_family)) {
85 FwmarkCommand command = {FwmarkCommand::ON_CONNECT, 0, 0};
86 if (int error = FwmarkClient().send(&command, sockfd)) {
93 if ( FwmarkClient::shouldSetFwmark(addr->sa_family)) {
94 if( __propClientDispatch.propConnect ) {
95 return __propClientDispatch.propConnect(sockfd, addr, addrlen);
97 return libcConnect(sockfd, addr, addrlen);
101 return libcConnect(sockfd, addr, addrlen);
104 int netdClientSocket(int domain, int type, int protocol) {
108 socketFd = libcSocket(domain, type, protocol);
110 if( __propClientDispatch.propSocket ) {
111 socketFd = __propClientDispatch.propSocket(domain, type, protocol);
113 socketFd = libcSocket(domain, type, protocol);
116 if (socketFd == -1) {
119 unsigned netId = netIdForProcess;
120 if (netId != NETID_UNSET && FwmarkClient::shouldSetFwmark(domain)) {
121 if (int error = setNetworkForSocket(netId, socketFd)) {
122 return closeFdAndSetErrno(socketFd, error);
128 unsigned getNetworkForResolv(unsigned netId) {
129 if (netId != NETID_UNSET) {
132 netId = netIdForProcess;
133 if (netId != NETID_UNSET) {
136 return netIdForResolv;
139 int setNetworkForTarget(unsigned netId, std::atomic_uint* target) {
140 if (netId == NETID_UNSET) {
144 // Verify that we are allowed to use |netId|, by creating a socket and trying to have it marked
145 // with the netId. Call libcSocket() directly; else the socket creation (via netdClientSocket())
146 // might itself cause another check with the fwmark server, which would be wasteful.
149 socketFd = libcSocket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
151 socketFd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
156 int error = setNetworkForSocket(netId, socketFd);
166 // accept() just calls accept4(..., 0), so there's no need to handle accept() separately.
167 extern "C" void netdClientInitAccept4(Accept4FunctionType* function) {
168 if (function && *function) {
169 libcAccept4 = *function;
170 *function = netdClientAccept4;
174 extern "C" void netdClientInitConnect(ConnectFunctionType* function) {
175 if (function && *function) {
176 libcConnect = *function;
177 *function = netdClientConnect;
181 extern "C" void netdClientInitSocket(SocketFunctionType* function) {
182 if (function && *function) {
183 libcSocket = *function;
184 *function = netdClientSocket;
188 extern "C" void netdClientInitNetIdForResolv(NetIdForResolvFunctionType* function) {
190 *function = getNetworkForResolv;
194 extern "C" int getNetworkForSocket(unsigned* netId, int socketFd) {
195 if (!netId || socketFd < 0) {
199 socklen_t fwmarkLen = sizeof(fwmark.intValue);
200 if (getsockopt(socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue, &fwmarkLen) == -1) {
203 *netId = fwmark.netId;
207 extern "C" unsigned getNetworkForProcess() {
208 return netIdForProcess;
211 extern "C" int setNetworkForSocket(unsigned netId, int socketFd) {
215 FwmarkCommand command = {FwmarkCommand::SELECT_NETWORK, netId, 0};
216 return FwmarkClient().send(&command, socketFd);
219 extern "C" int setNetworkForProcess(unsigned netId) {
220 return setNetworkForTarget(netId, &netIdForProcess);
223 extern "C" int setNetworkForResolv(unsigned netId) {
224 return setNetworkForTarget(netId, &netIdForResolv);
227 extern "C" int protectFromVpn(int socketFd) {
231 FwmarkCommand command = {FwmarkCommand::PROTECT_FROM_VPN, 0, 0};
232 return FwmarkClient().send(&command, socketFd);
235 extern "C" int setNetworkForUser(uid_t uid, int socketFd) {
239 FwmarkCommand command = {FwmarkCommand::SELECT_FOR_USER, 0, uid};
240 return FwmarkClient().send(&command, socketFd);
243 extern "C" int queryUserAccess(uid_t uid, unsigned netId) {
244 FwmarkCommand command = {FwmarkCommand::QUERY_USER_ACCESS, netId, uid};
245 return FwmarkClient().send(&command, -1);