1a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak/* 2a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * Copyright (C) 2014 The Android Open Source Project 3a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * 4a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * Licensed under the Apache License, Version 2.0 (the "License"); 5a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * you may not use this file except in compliance with the License. 6a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * You may obtain a copy of the License at 7a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * 8a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * http://www.apache.org/licenses/LICENSE-2.0 9a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * 10a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * Unless required by applicable law or agreed to in writing, software 11a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * distributed under the License is distributed on an "AS IS" BASIS, 12a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * See the License for the specific language governing permissions and 14a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * limitations under the License. 15a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak */ 16a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 1772604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// THREAD-SAFETY 1872604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// ------------- 1972604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// The methods in this file are called from multiple threads (from CommandListener, FwmarkServer 2072604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// and DnsProxyListener). So, all accesses to shared state are guarded by a lock. 2172604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 2272604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// In some cases, a single non-const method acquires and releases the lock several times, like so: 2372604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// if (isValidNetwork(...)) { // isValidNetwork() acquires and releases the lock. 2472604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// setDefaultNetwork(...); // setDefaultNetwork() also acquires and releases the lock. 2572604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 2672604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// It might seem that this allows races where the state changes between the two statements, but in 2772604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// fact there are no races because: 2872604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 1. This pattern only occurs in non-const methods (i.e., those that mutate state). 2972604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 2. Only CommandListener calls these non-const methods. The others call only const methods. 3072604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 3. CommandListener only processes one command at a time. I.e., it's serialized. 3172604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// Thus, no other mutation can occur in between the two statements above. 32a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 33a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak#include "NetworkController.h" 34a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 352d3a163433c435ff053402ae8965f8602c7ac6daErik Kline#define LOG_TAG "Netd" 362d3a163433c435ff053402ae8965f8602c7ac6daErik Kline#include "log/log.h" 372d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 382d3a163433c435ff053402ae8965f8602c7ac6daErik Kline#include "cutils/misc.h" 392d3a163433c435ff053402ae8965f8602c7ac6daErik Kline#include "resolv_netid.h" 402d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 413a272070fc318ef1a7a5a04e500483f1a7c629a8Pierre Imai#include "Controllers.h" 423667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitti#include "DummyNetwork.h" 432d3a163433c435ff053402ae8965f8602c7ac6daErik Kline#include "DumpWriter.h" 441011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran#include "Fwmark.h" 456a773534e7f8541f221f27fb8063af079b1a5936Sreeram Ramachandran#include "LocalNetwork.h" 46f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#include "PhysicalNetwork.h" 475c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "RouteController.h" 484043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#include "VirtualNetwork.h" 495c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 505c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandrannamespace { 515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran// Keep these in sync with ConnectivityService.java. 53bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned MIN_NET_ID = 100; 54f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranconst unsigned MAX_NET_ID = 65535; 555c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 565c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} // namespace 575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 58bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MIN_OEM_ID = 1; 59bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MAX_OEM_ID = 50; 603667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitticonst unsigned NetworkController::DUMMY_NET_ID = 51; 613667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitti// NetIds 52..98 are reserved for future use. 62bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::LOCAL_NET_ID = 99; 63bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran 6448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran// All calls to methods here are made while holding a write lock on mRWLock. 6548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranclass NetworkController::DelegateImpl : public PhysicalNetwork::Delegate { 6648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranpublic: 6748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran explicit DelegateImpl(NetworkController* networkController); 6848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran virtual ~DelegateImpl(); 6948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(unsigned vpnNetId, const std::string& physicalInterface, 7148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) WARN_UNUSED_RESULT; 7248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranprivate: 7448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int addFallthrough(const std::string& physicalInterface, 7548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 7648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int removeFallthrough(const std::string& physicalInterface, 7748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 7848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(const std::string& physicalInterface, Permission permission, 8048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran bool add) WARN_UNUSED_RESULT; 8148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran NetworkController* const mNetworkController; 8348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}; 8448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8548e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::DelegateImpl(NetworkController* networkController) : 8648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran mNetworkController(networkController) { 8748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 8848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8948e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::~DelegateImpl() { 9048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 9148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 9248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(unsigned vpnNetId, 9348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran const std::string& physicalInterface, 9448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 9548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (add) { 9648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::addVirtualNetworkFallthrough(vpnNetId, 9748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 9848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 9948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to add fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 10048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 10148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 10248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 10348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else { 10448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::removeVirtualNetworkFallthrough(vpnNetId, 10548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 10648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 10748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to remove fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 10848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 10948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 11048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 11148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 11248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 11348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 11448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 11548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::addFallthrough(const std::string& physicalInterface, 11648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 11748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, true); 11848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 11948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 12048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::removeFallthrough(const std::string& physicalInterface, 12148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 12248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, false); 12348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 12448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 12548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(const std::string& physicalInterface, 12648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 12748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& entry : mNetworkController->mNetworks) { 12848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 12948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthrough(entry.first, physicalInterface, permission, add)) { 13048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 13148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 13248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 13348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 13448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 13548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 13648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 13748e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::NetworkController() : 1386be561952ca91e19bc1ba6195ec47e33b43ae7fdPierre Imai mDelegateImpl(new NetworkController::DelegateImpl(this)), mDefaultNetId(NETID_UNSET), 1396be561952ca91e19bc1ba6195ec47e33b43ae7fdPierre Imai mProtectableUsers({AID_VPN}) { 14087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran mNetworks[LOCAL_NET_ID] = new LocalNetwork(LOCAL_NET_ID); 1413667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitti mNetworks[DUMMY_NET_ID] = new DummyNetwork(DUMMY_NET_ID); 142a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 143a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 144a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczakunsigned NetworkController::getDefaultNetwork() const { 1459c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 146a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak return mDefaultNetId; 147a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 148a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 149f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setDefaultNetwork(unsigned netId) { 150f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 1519c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 152f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId == mDefaultNetId) { 153f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 1549c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1559c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 156f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId != NETID_UNSET) { 15736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 158738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 159738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 160738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 161738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 162738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 163738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set default to non-physical network with netId %u", netId); 164f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EINVAL; 165f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 16636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) { 167f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1689c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1699c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1709c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 171f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId != NETID_UNSET) { 17236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 17336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (!network || network->getType() != Network::PHYSICAL) { 174f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 175f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -ESRCH; 176f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 17736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 178f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1799c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1809c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1819c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 182f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = netId; 183f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 184a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 185a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 1861011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranuint32_t NetworkController::getNetworkForDns(unsigned* netId, uid_t uid) const { 1871011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 1881011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Fwmark fwmark; 1891011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.protectedFromVpn = true; 1901011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.permission = PERMISSION_SYSTEM; 191a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (checkUserNetworkAccessLocked(uid, *netId) == 0) { 1921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If a non-zero NetId was explicitly specified, and the user has permission for that 1931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // network, use that network's DNS servers. Do not fall through to the default network even 194c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // if the explicitly selected network is a split tunnel VPN: the explicitlySelected bit 195c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // ensures that the VPN fallthrough rule does not match. 1961011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.explicitlySelected = true; 197c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti 198c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // If the network is a VPN and it doesn't have DNS servers, use the default network's DNS 199c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // servers (through the default network). Otherwise, the query is guaranteed to fail. 200c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // http://b/29498052 201c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti Network *network = getNetworkLocked(*netId); 202c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti if (network && network->getType() == Network::VIRTUAL && 203c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti !static_cast<VirtualNetwork *>(network)->getHasDns()) { 204c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti *netId = mDefaultNetId; 205c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti } 2061011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 2071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If the user is subject to a VPN and the VPN provides DNS servers, use those servers 2081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (possibly falling through to the default network if the VPN doesn't provide a route to 2091011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // them). Otherwise, use the default network's DNS servers. 2101011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 2111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->getHasDns()) { 2121011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = virtualNetwork->getNetId(); 2131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 214c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // TODO: return an error instead of silently doing the DNS lookup on the wrong network. 215c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // http://b/27560555 2161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = mDefaultNetId; 2171011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2191011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.netId = *netId; 2201011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return fwmark.intValue; 2211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2231011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that a given UID would use if no network is explicitly selected. Specifically, 2241011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the VPN that applies to the UID if any; otherwise, the default network. 2251011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForUser(uid_t uid) const { 2261011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 2271011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid)) { 2281011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return virtualNetwork->getNetId(); 2291011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2301011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 2311011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2321011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2331011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that will be set when a socket connect()s. This is the bypassable VPN that 2341011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// applies to the user if any; otherwise, the default network. 2351011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2361011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// In general, we prefer to always set the default network's NetId in connect(), so that if the VPN 2371011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// is a split-tunnel and disappears later, the socket continues working (since the default network's 2381011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// NetId is still valid). Secure VPNs will correctly grab the socket's traffic since they have a 2391011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// high-priority routing rule that doesn't care what NetId the socket has. 2401011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2411011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// But bypassable VPNs have a very low priority rule, so we need to mark the socket with the 2421011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// bypassable VPN's NetId if we expect it to get any traffic at all. If the bypassable VPN is a 2431011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// split-tunnel, that's okay, because we have fallthrough rules that will direct the fallthrough 2441011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// traffic to the default network. But it does mean that if the bypassable VPN goes away (and thus 2451011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the fallthrough rules also go away), the socket that used to fallthrough to the default network 2461011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// will stop working. 2471011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForConnect(uid_t uid) const { 248a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak android::RWLock::AutoRLock lock(mRWLock); 249e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 2501011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && !virtualNetwork->isSecure()) { 251e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork->getNetId(); 252a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak } 2531011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 254a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 255a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 256cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Klinevoid NetworkController::getNetworkContext( 257cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline unsigned netId, uid_t uid, struct android_net_context* netcontext) const { 258cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline struct android_net_context nc = { 259cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .app_netid = netId, 260cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .app_mark = MARK_UNSET, 261cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .dns_netid = netId, 262cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .dns_mark = MARK_UNSET, 263cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .uid = uid, 264cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline }; 265cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 266492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // |netId| comes directly (via dnsproxyd) from the value returned by netIdForResolv() in the 267492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // client process. This value is nonzero iff.: 268492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 269492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 1. The app specified a netid/nethandle to a DNS resolution method such as: 270492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [Java] android.net.Network#getAllByName() 271492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [C/++] android_getaddrinfofornetwork() 272492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 2. The app specified a netid/nethandle to be used as a process default via: 273492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [Java] android.net.ConnectivityManager#bindProcessToNetwork() 274492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [C/++] android_setprocnetwork() 275492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 3. The app called android.net.ConnectivityManager#startUsingNetworkFeature(). 276492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 277492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // In all these cases (with the possible exception of #3), the right thing to do is to treat 278492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // such cases as explicitlySelected. 279492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline const bool explicitlySelected = (nc.app_netid != NETID_UNSET); 280492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline if (!explicitlySelected) { 281cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline nc.app_netid = getNetworkForConnect(uid); 282cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline } 283492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline 284cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline Fwmark fwmark; 285cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline fwmark.netId = nc.app_netid; 286492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline fwmark.explicitlySelected = explicitlySelected; 287492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline fwmark.protectedFromVpn = canProtect(uid); 288492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline fwmark.permission = getPermissionForUser(uid); 289cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline nc.app_mark = fwmark.intValue; 290cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 291cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline nc.dns_mark = getNetworkForDns(&(nc.dns_netid), uid); 292cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 293cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline if (netcontext) { 294cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline *netcontext = nc; 295cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline } 296cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline} 297cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 298e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranunsigned NetworkController::getNetworkForInterface(const char* interface) const { 299f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 30036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran for (const auto& entry : mNetworks) { 3014043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (entry.second->hasInterface(interface)) { 3024043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return entry.first; 3034043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 3044043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 30535c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen return NETID_UNSET; 306a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 307a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 308070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandranbool NetworkController::isVirtualNetwork(unsigned netId) const { 309070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 310070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran Network* network = getNetworkLocked(netId); 311070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran return network && network->getType() == Network::VIRTUAL; 312070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran} 313070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran 314e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranint NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) { 315bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran if (!((MIN_NET_ID <= netId && netId <= MAX_NET_ID) || 316bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran (MIN_OEM_ID <= netId && netId <= MAX_OEM_ID))) { 317f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("invalid netId %u", netId); 31896f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 3195c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3205c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 321f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (isValidNetwork(netId)) { 322f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 323f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EEXIST; 3245c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3255c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 32648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId, mDelegateImpl); 327f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (int ret = physicalNetwork->setPermission(permission)) { 328f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! setPermission cannot fail on an empty network"); 329f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete physicalNetwork; 33096f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return ret; 331ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 332ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 333f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 33436ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks[netId] = physicalNetwork; 33596f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 3365c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 3375c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 33895684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandranint NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) { 339bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) { 3404043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("invalid netId %u", netId); 3414043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EINVAL; 3424043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 3434043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 3444043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (isValidNetwork(netId)) { 3454043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 3464043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EEXIST; 3474043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 3484043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 3494043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 35048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthroughLocked(netId, true)) { 35148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 35248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 35395684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran mNetworks[netId] = new VirtualNetwork(netId, hasDns, secure); 3544043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return 0; 3554043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran} 3564043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 357f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::destroyNetwork(unsigned netId) { 358738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (netId == LOCAL_NET_ID) { 359738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot destroy local network"); 36096f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 361ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 362738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 363738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 364738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 365738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 366ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 367f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network. 36896f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti 369f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 370f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran Network* network = getNetworkLocked(netId); 37199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti 37299286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // If we fail to destroy a network, things will get stuck badly. Therefore, unlike most of the 37399286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // other network code, ignore failures and attempt to clear out as much state as possible, even 37499286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // if we hit an error on the way. Return the first error that we see. 37599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti int ret = network->clearInterfaces(); 37699286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti 377f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId == netId) { 37899286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (int err = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 379f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! removeAsDefault cannot fail on an empty network"); 38099286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (!ret) { 38199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti ret = err; 38299286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti } 383f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 384f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = NETID_UNSET; 38548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else if (network->getType() == Network::VIRTUAL) { 38699286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (int err = modifyFallthroughLocked(netId, false)) { 38799286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (!ret) { 38899286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti ret = err; 38999286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti } 39048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 391f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 39236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks.erase(netId); 393f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete network; 394f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran _resolv_delete_cache_for_net(netId); 39599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti return ret; 396f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 397ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 398f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) { 399f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (!isValidNetwork(netId)) { 400738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 401738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 402ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 403ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 404e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 405f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (existingNetId != NETID_UNSET && existingNetId != netId) { 406f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s already assigned to netId %u", interface, existingNetId); 407f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EBUSY; 408a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen } 409a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen 410f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 411f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->addInterface(interface); 412ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen} 413ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 414f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) { 41572604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran if (!isValidNetwork(netId)) { 416738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 417738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 4185c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 4195c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 420f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 421f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->removeInterface(interface); 422f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 4235c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 424f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranPermission NetworkController::getPermissionForUser(uid_t uid) const { 425f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 426ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return getPermissionForUserLocked(uid); 427f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 4285c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 429f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranvoid NetworkController::setPermissionForUsers(Permission permission, 430f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<uid_t>& uids) { 431f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 432f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (uid_t uid : uids) { 433ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran mUsers[uid] = permission; 4345c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 4355c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 4365c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 437a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccess(uid_t uid, unsigned netId) const { 438f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 439a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return checkUserNetworkAccessLocked(uid, netId); 440379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 441379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 442f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setPermissionForNetworks(Permission permission, 443f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<unsigned>& netIds) { 444f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 445f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (unsigned netId : netIds) { 44636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 447738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 448738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 449738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 450738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 451738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 452738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set permissions on non-physical network with netId %u", netId); 45396f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 454379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 455379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 456f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission. 457379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 45836ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) { 459f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 460379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 461379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 46296f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 463379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 464379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 465b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) { 466b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 46736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 468738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 469738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 470738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 471738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 472738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 473738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot add users to non-virtual network with netId %u", netId); 474b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 475b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 476fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges, mProtectableUsers)) { 477b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 478b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 479b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 480b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 481b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 482b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) { 483b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 48436ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 485738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 486738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 487738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 488738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 489738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 490738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot remove users from non-virtual network with netId %u", netId); 491b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 492b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 493fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges, 494fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti mProtectableUsers)) { 495b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 496b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 497b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 498b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 499b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 500f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::addRoute(unsigned netId, const char* interface, const char* destination, 501f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 50238b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid); 5037619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 5047619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 505f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination, 506f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 50738b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid); 5087619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 5097619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 510e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::canProtect(uid_t uid) const { 511e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 512e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) || 513e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran mProtectableUsers.find(uid) != mProtectableUsers.end(); 514e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 515e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 51689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::allowProtect(const std::vector<uid_t>& uids) { 51789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 51889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.insert(uids.begin(), uids.end()); 51989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 52089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 52189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::denyProtect(const std::vector<uid_t>& uids) { 52289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 52389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran for (uid_t uid : uids) { 52489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.erase(uid); 52589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran } 52689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 52789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 5282d3a163433c435ff053402ae8965f8602c7ac6daErik Klinevoid NetworkController::dump(DumpWriter& dw) { 5292d3a163433c435ff053402ae8965f8602c7ac6daErik Kline android::RWLock::AutoRLock lock(mRWLock); 5302d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5312d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.incIndent(); 5322d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println("NetworkController"); 5332d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5342d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.incIndent(); 5352d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println("Default network: %u", mDefaultNetId); 5362d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5372d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.blankline(); 5382d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println("Networks:"); 5392d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.incIndent(); 5402d3a163433c435ff053402ae8965f8602c7ac6daErik Kline for (const auto& i : mNetworks) { 5412d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println(i.second->toString().c_str()); 5423a272070fc318ef1a7a5a04e500483f1a7c629a8Pierre Imai android::net::gCtls->resolverCtrl.dump(dw, i.first); 5433a272070fc318ef1a7a5a04e500483f1a7c629a8Pierre Imai dw.blankline(); 5442d3a163433c435ff053402ae8965f8602c7ac6daErik Kline } 5452d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.decIndent(); 5462d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5472d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.decIndent(); 5482d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5492d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.decIndent(); 5502d3a163433c435ff053402ae8965f8602c7ac6daErik Kline} 5512d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 552e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::isValidNetwork(unsigned netId) const { 553e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 554e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return getNetworkLocked(netId); 555e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 556e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 557f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranNetwork* NetworkController::getNetworkLocked(unsigned netId) const { 55836ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran auto iter = mNetworks.find(netId); 55936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran return iter == mNetworks.end() ? NULL : iter->second; 5607619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 5617619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 562e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram RamachandranVirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const { 563e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran for (const auto& entry : mNetworks) { 564e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 565e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second); 566e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (virtualNetwork->appliesToUser(uid)) { 567e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork; 568e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 569e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 570e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 571e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return NULL; 572e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 573e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 574ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission NetworkController::getPermissionForUserLocked(uid_t uid) const { 575ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran auto iter = mUsers.find(uid); 576ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if (iter != mUsers.end()) { 577ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return iter->second; 578ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran } 579ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE; 580ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran} 581ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran 582a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) const { 5831011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Network* network = getNetworkLocked(netId); 584a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (!network) { 585a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -ENONET; 586a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti } 587a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti 5881011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If uid is INVALID_UID, this likely means that we were unable to retrieve the UID of the peer 5891011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (using SO_PEERCRED). Be safe and deny access to the network, even if it's valid. 590a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (uid == INVALID_UID) { 591a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -EREMOTEIO; 5921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission userPermission = getPermissionForUserLocked(uid); 5941011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 595a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return 0; 5961011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (network->getType() == Network::VIRTUAL) { 598a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return static_cast<VirtualNetwork*>(network)->appliesToUser(uid) ? 0 : -EPERM; 5991011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 6001011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 6011011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->isSecure() && 6021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran mProtectableUsers.find(uid) == mProtectableUsers.end()) { 603a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -EPERM; 6041011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 6051011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission(); 606a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return ((userPermission & networkPermission) == networkPermission) ? 0 : -EACCES; 6071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 6081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 609f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination, 610f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool add, bool legacy, uid_t uid) { 611738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 612738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 613738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 614738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 615e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 616738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId == NETID_UNSET) { 617738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("interface %s not assigned to any netId", interface); 618738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENODEV; 619738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 620738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId != netId) { 621f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId); 622f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colitti return -ENOENT; 6237619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran } 6247619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 62538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran RouteController::TableType tableType; 62687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran if (netId == LOCAL_NET_ID) { 62787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran tableType = RouteController::LOCAL_NETWORK; 62887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran } else if (legacy) { 629ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 6305009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_SYSTEM; 63138b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 6325009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_NETWORK; 63338b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 63438b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 63538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran tableType = RouteController::INTERFACE; 63638b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 63738b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran 638eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran return add ? RouteController::addRoute(interface, destination, nexthop, tableType) : 639eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran RouteController::removeRoute(interface, destination, nexthop, tableType); 6407619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 64148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 64248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::modifyFallthroughLocked(unsigned vpnNetId, bool add) { 64348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (mDefaultNetId == NETID_UNSET) { 64448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 64548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 64648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 647738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 64848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 64948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return -ESRCH; 65048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 651738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 652738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("inconceivable! default network must be a physical network"); 653738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -EINVAL; 654738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 65548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission = static_cast<PhysicalNetwork*>(network)->getPermission(); 65648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& physicalInterface : network->getInterfaces()) { 65748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = mDelegateImpl->modifyFallthrough(vpnNetId, physicalInterface, permission, 65848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran add)) { 65948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 66048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 66148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 66248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 66348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 664