1f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran/* 2f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * Copyright (C) 2014 The Android Open Source Project 3f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * 4f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * Licensed under the Apache License, Version 2.0 (the "License"); 5f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * you may not use this file except in compliance with the License. 6f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * You may obtain a copy of the License at 7f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * 8f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * http://www.apache.org/licenses/LICENSE-2.0 9f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * 10f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * Unless required by applicable law or agreed to in writing, software 11f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * distributed under the License is distributed on an "AS IS" BASIS, 12f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * See the License for the specific language governing permissions and 14f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * limitations under the License. 15f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran */ 16f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 17efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran#include "NetdClient.h" 18efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 194b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski#include <arpa/inet.h> 20aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <errno.h> 214b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski#include <math.h> 22aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <sys/socket.h> 23aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <unistd.h> 24aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert 25aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <atomic> 26aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert 274d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran#include "Fwmark.h" 28f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include "FwmarkClient.h" 29f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include "FwmarkCommand.h" 30efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran#include "resolv_netid.h" 31cc544162e08dd0df271cd77a3f2c85dbaaa461e2Robin Lee#include "Stopwatch.h" 32f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 33f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandrannamespace { 34f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 359fa2b130d86fa74eefdb847cf9694059205fd4cbSreeram Ramachandranstd::atomic_uint netIdForProcess(NETID_UNSET); 369fa2b130d86fa74eefdb847cf9694059205fd4cbSreeram Ramachandranstd::atomic_uint netIdForResolv(NETID_UNSET); 37f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 385fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandrantypedef int (*Accept4FunctionType)(int, sockaddr*, socklen_t*, int); 39f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandrantypedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t); 405fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandrantypedef int (*SocketFunctionType)(int, int, int); 41efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandrantypedef unsigned (*NetIdForResolvFunctionType)(unsigned); 42f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 43efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran// These variables are only modified at startup (when libc.so is loaded) and never afterwards, so 44efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran// it's okay that they are read later at runtime without a lock. 455fc275794ab41d110abbdb7683ed9db45918985fSreeram RamachandranAccept4FunctionType libcAccept4 = 0; 46f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram RamachandranConnectFunctionType libcConnect = 0; 475fc275794ab41d110abbdb7683ed9db45918985fSreeram RamachandranSocketFunctionType libcSocket = 0; 48f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 4931f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandranint closeFdAndSetErrno(int fd, int error) { 505fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran close(fd); 513a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran errno = -error; 525fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran return -1; 53f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 54f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 555fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandranint netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) { 565fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran int acceptedSocket = libcAccept4(sockfd, addr, addrlen, flags); 57f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (acceptedSocket == -1) { 58f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return -1; 59f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 605fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran int family; 615fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran if (addr) { 625fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran family = addr->sa_family; 635fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } else { 645fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran socklen_t familyLen = sizeof(family); 655fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran if (getsockopt(acceptedSocket, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) { 663a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return closeFdAndSetErrno(acceptedSocket, -errno); 67f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 68f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 695fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran if (FwmarkClient::shouldSetFwmark(family)) { 70a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0}; 714b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski if (int error = FwmarkClient().send(&command, acceptedSocket, nullptr)) { 7231f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran return closeFdAndSetErrno(acceptedSocket, error); 73f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 74f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 75f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return acceptedSocket; 76f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 77f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 785fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandranint netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) { 794b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski const bool shouldSetFwmark = (sockfd >= 0) && addr 804b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski && FwmarkClient::shouldSetFwmark(addr->sa_family); 814b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski if (shouldSetFwmark) { 82a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran FwmarkCommand command = {FwmarkCommand::ON_CONNECT, 0, 0}; 834b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski if (int error = FwmarkClient().send(&command, sockfd, nullptr)) { 843a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran errno = -error; 855fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran return -1; 865fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } 875fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } 884b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski // Latency measurement does not include time of sending commands to Fwmark 894b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski Stopwatch s; 90794c5c714a4d4cf169769ec956845a6fb24e7ebcHugo Benichi const int ret = libcConnect(sockfd, addr, addrlen); 914b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski // Save errno so it isn't clobbered by sending ON_CONNECT_COMPLETE 924b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski const int connectErrno = errno; 934b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski const unsigned latencyMs = lround(s.timeTaken()); 944b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski // Send an ON_CONNECT_COMPLETE command that includes sockaddr and connect latency for reporting 954b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski if (shouldSetFwmark && FwmarkClient::shouldReportConnectComplete(addr->sa_family)) { 96794c5c714a4d4cf169769ec956845a6fb24e7ebcHugo Benichi FwmarkConnectInfo connectInfo(ret == 0 ? 0 : connectErrno, latencyMs, addr); 974b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski // TODO: get the netId from the socket mark once we have continuous benchmark runs 984b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski FwmarkCommand command = {FwmarkCommand::ON_CONNECT_COMPLETE, /* netId (ignored) */ 0, 994b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski /* uid (filled in by the server) */ 0}; 1004b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski // Ignore return value since it's only used for logging 1014b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski FwmarkClient().send(&command, sockfd, &connectInfo); 1024b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski } 1034b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski errno = connectErrno; 1044b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski return ret; 1055fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran} 1065fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran 1075fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandranint netdClientSocket(int domain, int type, int protocol) { 1085fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran int socketFd = libcSocket(domain, type, protocol); 1095fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran if (socketFd == -1) { 1105fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran return -1; 1115fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } 1125fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran unsigned netId = netIdForProcess; 1135fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran if (netId != NETID_UNSET && FwmarkClient::shouldSetFwmark(domain)) { 114d36c49c1d66585769d33d95f0eb2c9c524b337a4Sreeram Ramachandran if (int error = setNetworkForSocket(netId, socketFd)) { 11531f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran return closeFdAndSetErrno(socketFd, error); 1165fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } 1175fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } 1185fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran return socketFd; 1195fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran} 120efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 121efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandranunsigned getNetworkForResolv(unsigned netId) { 122efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran if (netId != NETID_UNSET) { 123efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran return netId; 124efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 125efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran netId = netIdForProcess; 126efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran if (netId != NETID_UNSET) { 127efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran return netId; 128efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 129efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran return netIdForResolv; 130efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 131efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 13231f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandranint setNetworkForTarget(unsigned netId, std::atomic_uint* target) { 133efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran if (netId == NETID_UNSET) { 134efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran *target = netId; 13531f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran return 0; 136efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 137efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran // Verify that we are allowed to use |netId|, by creating a socket and trying to have it marked 1382756045bebaac342f7cb70dad11519f896d44833Sreeram Ramachandran // with the netId. Call libcSocket() directly; else the socket creation (via netdClientSocket()) 1392756045bebaac342f7cb70dad11519f896d44833Sreeram Ramachandran // might itself cause another check with the fwmark server, which would be wasteful. 1402756045bebaac342f7cb70dad11519f896d44833Sreeram Ramachandran int socketFd; 1412756045bebaac342f7cb70dad11519f896d44833Sreeram Ramachandran if (libcSocket) { 14253ea9cadf6cc5f8be1c16b5b6b660cd7366fd3f0Nick Kralevich socketFd = libcSocket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); 1432756045bebaac342f7cb70dad11519f896d44833Sreeram Ramachandran } else { 14453ea9cadf6cc5f8be1c16b5b6b660cd7366fd3f0Nick Kralevich socketFd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); 1452756045bebaac342f7cb70dad11519f896d44833Sreeram Ramachandran } 146efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran if (socketFd < 0) { 1473a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -errno; 148efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 14931f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran int error = setNetworkForSocket(netId, socketFd); 15031f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran if (!error) { 151efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran *target = netId; 152efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 15331f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran close(socketFd); 15431f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran return error; 155efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 156efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 157f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} // namespace 158f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 1595fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran// accept() just calls accept4(..., 0), so there's no need to handle accept() separately. 1605fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandranextern "C" void netdClientInitAccept4(Accept4FunctionType* function) { 1615fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran if (function && *function) { 1625fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran libcAccept4 = *function; 1635fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran *function = netdClientAccept4; 1645fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran } 1655fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran} 1665fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran 167f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandranextern "C" void netdClientInitConnect(ConnectFunctionType* function) { 168f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (function && *function) { 169f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran libcConnect = *function; 170f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran *function = netdClientConnect; 171f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 172f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 173f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 1745fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandranextern "C" void netdClientInitSocket(SocketFunctionType* function) { 175f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (function && *function) { 1765fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran libcSocket = *function; 1775fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandran *function = netdClientSocket; 178f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 179f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 180efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 181efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandranextern "C" void netdClientInitNetIdForResolv(NetIdForResolvFunctionType* function) { 182efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran if (function) { 183efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran *function = getNetworkForResolv; 184efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 185efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 186efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 1874d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandranextern "C" int getNetworkForSocket(unsigned* netId, int socketFd) { 1884d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran if (!netId || socketFd < 0) { 1893a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -EBADF; 1904d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran } 1914d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran Fwmark fwmark; 1924d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran socklen_t fwmarkLen = sizeof(fwmark.intValue); 1934d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran if (getsockopt(socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue, &fwmarkLen) == -1) { 1943a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -errno; 1954d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran } 1964d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran *netId = fwmark.netId; 1974d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran return 0; 1984d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran} 1994d4c8b7e294d845103ecb10f968713717a3e6406Sreeram Ramachandran 200efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandranextern "C" unsigned getNetworkForProcess() { 201efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran return netIdForProcess; 202efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 203efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 20431f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandranextern "C" int setNetworkForSocket(unsigned netId, int socketFd) { 205efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran if (socketFd < 0) { 2063a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -EBADF; 207efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran } 208a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran FwmarkCommand command = {FwmarkCommand::SELECT_NETWORK, netId, 0}; 2094b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski return FwmarkClient().send(&command, socketFd, nullptr); 210efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 211efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 21231f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandranextern "C" int setNetworkForProcess(unsigned netId) { 213efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran return setNetworkForTarget(netId, &netIdForProcess); 214efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 215efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran 21631f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandranextern "C" int setNetworkForResolv(unsigned netId) { 217efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran return setNetworkForTarget(netId, &netIdForResolv); 218efbe05d203f2f1cc3c24ddc111be159a1ff1f292Sreeram Ramachandran} 219d794e580dbe1a8b4192850b0e117654401514af8Sreeram Ramachandran 22031f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandranextern "C" int protectFromVpn(int socketFd) { 221d794e580dbe1a8b4192850b0e117654401514af8Sreeram Ramachandran if (socketFd < 0) { 2223a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -EBADF; 223d794e580dbe1a8b4192850b0e117654401514af8Sreeram Ramachandran } 224a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran FwmarkCommand command = {FwmarkCommand::PROTECT_FROM_VPN, 0, 0}; 2254b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski return FwmarkClient().send(&command, socketFd, nullptr); 226a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran} 227a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran 228a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandranextern "C" int setNetworkForUser(uid_t uid, int socketFd) { 229a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran if (socketFd < 0) { 230a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran return -EBADF; 231a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran } 232a69d9472ac48d4e09f049fb740e60b7217e03861Sreeram Ramachandran FwmarkCommand command = {FwmarkCommand::SELECT_FOR_USER, 0, uid}; 2334b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski return FwmarkClient().send(&command, socketFd, nullptr); 234d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen} 235d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen 236d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensenextern "C" int queryUserAccess(uid_t uid, unsigned netId) { 237d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen FwmarkCommand command = {FwmarkCommand::QUERY_USER_ACCESS, netId, uid}; 2384b9b78aa02336de9291e5085401cef44c03c3bbaMichal Karpinski return FwmarkClient().send(&command, -1, nullptr); 239d794e580dbe1a8b4192850b0e117654401514af8Sreeram Ramachandran} 240