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 506d4669fa924315139f3636368c6623209fbfc3eaErik Kline#define DBG 0 516d4669fa924315139f3636368c6623209fbfc3eaErik Kline 527035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colittinamespace android { 537035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colittinamespace net { 547035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti 555c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandrannamespace { 565c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran// Keep these in sync with ConnectivityService.java. 58bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned MIN_NET_ID = 100; 59f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranconst unsigned MAX_NET_ID = 65535; 605c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 615c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} // namespace 625c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 63bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MIN_OEM_ID = 1; 64bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MAX_OEM_ID = 50; 653667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitticonst unsigned NetworkController::DUMMY_NET_ID = 51; 663667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitti// NetIds 52..98 are reserved for future use. 67bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::LOCAL_NET_ID = 99; 68bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran 6948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran// All calls to methods here are made while holding a write lock on mRWLock. 7048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranclass NetworkController::DelegateImpl : public PhysicalNetwork::Delegate { 7148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranpublic: 7248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran explicit DelegateImpl(NetworkController* networkController); 7348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran virtual ~DelegateImpl(); 7448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(unsigned vpnNetId, const std::string& physicalInterface, 7648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) WARN_UNUSED_RESULT; 7748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranprivate: 7948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int addFallthrough(const std::string& physicalInterface, 8048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 8148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int removeFallthrough(const std::string& physicalInterface, 8248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 8348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(const std::string& physicalInterface, Permission permission, 8548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran bool add) WARN_UNUSED_RESULT; 8648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran NetworkController* const mNetworkController; 8848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}; 8948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 9048e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::DelegateImpl(NetworkController* networkController) : 9148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran mNetworkController(networkController) { 9248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 9348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 9448e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::~DelegateImpl() { 9548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 9648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 9748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(unsigned vpnNetId, 9848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran const std::string& physicalInterface, 9948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 10048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (add) { 10148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::addVirtualNetworkFallthrough(vpnNetId, 10248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 10348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 10448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to add fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 10548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 10648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 10748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 10848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else { 10948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::removeVirtualNetworkFallthrough(vpnNetId, 11048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 11148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 11248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to remove fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 11348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 11448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 11548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 11648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 11748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 11848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 11948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 12048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::addFallthrough(const std::string& physicalInterface, 12148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 12248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, true); 12348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 12448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 12548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::removeFallthrough(const std::string& physicalInterface, 12648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 12748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, false); 12848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 12948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 13048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(const std::string& physicalInterface, 13148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 13248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& entry : mNetworkController->mNetworks) { 13348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 13448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthrough(entry.first, physicalInterface, permission, add)) { 13548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 13648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 13748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 13848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 13948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 14048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 14148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 14248e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::NetworkController() : 1436be561952ca91e19bc1ba6195ec47e33b43ae7fdPierre Imai mDelegateImpl(new NetworkController::DelegateImpl(this)), mDefaultNetId(NETID_UNSET), 1446be561952ca91e19bc1ba6195ec47e33b43ae7fdPierre Imai mProtectableUsers({AID_VPN}) { 14587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran mNetworks[LOCAL_NET_ID] = new LocalNetwork(LOCAL_NET_ID); 1463667936aadcabddc708797ac38ce1ffb2f992cb3Lorenzo Colitti mNetworks[DUMMY_NET_ID] = new DummyNetwork(DUMMY_NET_ID); 147a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 148a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 149a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczakunsigned NetworkController::getDefaultNetwork() const { 1509c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 151a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak return mDefaultNetId; 152a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 153a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 154f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setDefaultNetwork(unsigned netId) { 155f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 1569c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 157f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId == mDefaultNetId) { 158f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 1599c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1609c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 161f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId != NETID_UNSET) { 16236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 163738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 164738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 165738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 166738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 167738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 168738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set default to non-physical network with netId %u", netId); 169f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EINVAL; 170f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 17136ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) { 172f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1739c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1749c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1759c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 176f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId != NETID_UNSET) { 17736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 17836ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (!network || network->getType() != Network::PHYSICAL) { 179f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 180f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -ESRCH; 181f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 18236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 183f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1849c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1859c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1869c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 187f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = netId; 188f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 189a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 190a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 1911011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranuint32_t NetworkController::getNetworkForDns(unsigned* netId, uid_t uid) const { 1921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 1931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Fwmark fwmark; 1941011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.protectedFromVpn = true; 1951011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.permission = PERMISSION_SYSTEM; 196a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (checkUserNetworkAccessLocked(uid, *netId) == 0) { 1971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If a non-zero NetId was explicitly specified, and the user has permission for that 1981011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // network, use that network's DNS servers. Do not fall through to the default network even 199c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // if the explicitly selected network is a split tunnel VPN: the explicitlySelected bit 200c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // ensures that the VPN fallthrough rule does not match. 2011011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.explicitlySelected = true; 202c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti 203c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // If the network is a VPN and it doesn't have DNS servers, use the default network's DNS 204c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // servers (through the default network). Otherwise, the query is guaranteed to fail. 205c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // http://b/29498052 206c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti Network *network = getNetworkLocked(*netId); 207c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti if (network && network->getType() == Network::VIRTUAL && 208c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti !static_cast<VirtualNetwork *>(network)->getHasDns()) { 209c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti *netId = mDefaultNetId; 210c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti } 2111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 2121011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If the user is subject to a VPN and the VPN provides DNS servers, use those servers 2131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (possibly falling through to the default network if the VPN doesn't provide a route to 2141011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // them). Otherwise, use the default network's DNS servers. 2151011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 2161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->getHasDns()) { 2171011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = virtualNetwork->getNetId(); 2181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 219c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // TODO: return an error instead of silently doing the DNS lookup on the wrong network. 220c63059c8a7423b13cecc8b65885d54c12aae0d10Lorenzo Colitti // http://b/27560555 2211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = mDefaultNetId; 2221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2231011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2241011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.netId = *netId; 2251011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return fwmark.intValue; 2261011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2271011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2281011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that a given UID would use if no network is explicitly selected. Specifically, 2291011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the VPN that applies to the UID if any; otherwise, the default network. 2301011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForUser(uid_t uid) const { 2311011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 2321011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid)) { 2331011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return virtualNetwork->getNetId(); 2341011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2351011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 2361011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2371011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2381011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that will be set when a socket connect()s. This is the bypassable VPN that 2391011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// applies to the user if any; otherwise, the default network. 2401011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2411011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// In general, we prefer to always set the default network's NetId in connect(), so that if the VPN 2421011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// is a split-tunnel and disappears later, the socket continues working (since the default network's 2431011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// NetId is still valid). Secure VPNs will correctly grab the socket's traffic since they have a 2441011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// high-priority routing rule that doesn't care what NetId the socket has. 2451011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2461011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// But bypassable VPNs have a very low priority rule, so we need to mark the socket with the 2471011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// bypassable VPN's NetId if we expect it to get any traffic at all. If the bypassable VPN is a 2481011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// split-tunnel, that's okay, because we have fallthrough rules that will direct the fallthrough 2491011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// traffic to the default network. But it does mean that if the bypassable VPN goes away (and thus 2501011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the fallthrough rules also go away), the socket that used to fallthrough to the default network 2511011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// will stop working. 2521011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForConnect(uid_t uid) const { 253a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak android::RWLock::AutoRLock lock(mRWLock); 254e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 2551011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && !virtualNetwork->isSecure()) { 256e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork->getNetId(); 257a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak } 2581011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 259a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 260a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 261cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Klinevoid NetworkController::getNetworkContext( 262cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline unsigned netId, uid_t uid, struct android_net_context* netcontext) const { 263cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline struct android_net_context nc = { 264cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .app_netid = netId, 265cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .app_mark = MARK_UNSET, 266cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .dns_netid = netId, 267cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .dns_mark = MARK_UNSET, 268cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline .uid = uid, 269cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline }; 270cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 271492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // |netId| comes directly (via dnsproxyd) from the value returned by netIdForResolv() in the 272492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // client process. This value is nonzero iff.: 273492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 274492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 1. The app specified a netid/nethandle to a DNS resolution method such as: 275492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [Java] android.net.Network#getAllByName() 276492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [C/++] android_getaddrinfofornetwork() 277492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 2. The app specified a netid/nethandle to be used as a process default via: 278492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [Java] android.net.ConnectivityManager#bindProcessToNetwork() 279492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // - [C/++] android_setprocnetwork() 280492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 3. The app called android.net.ConnectivityManager#startUsingNetworkFeature(). 281492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // 282492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // In all these cases (with the possible exception of #3), the right thing to do is to treat 283492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline // such cases as explicitlySelected. 284492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline const bool explicitlySelected = (nc.app_netid != NETID_UNSET); 285492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline if (!explicitlySelected) { 286cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline nc.app_netid = getNetworkForConnect(uid); 287cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline } 288492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline 289cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline Fwmark fwmark; 290cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline fwmark.netId = nc.app_netid; 291492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline fwmark.explicitlySelected = explicitlySelected; 2926d4669fa924315139f3636368c6623209fbfc3eaErik Kline fwmark.protectedFromVpn = explicitlySelected && canProtect(uid); 293492ca5bca129186b53f203386ebe3e28f9143c9eErik Kline fwmark.permission = getPermissionForUser(uid); 294cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline nc.app_mark = fwmark.intValue; 295cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 296cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline nc.dns_mark = getNetworkForDns(&(nc.dns_netid), uid); 297cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 2986d4669fa924315139f3636368c6623209fbfc3eaErik Kline if (DBG) { 2996d4669fa924315139f3636368c6623209fbfc3eaErik Kline ALOGD("app_netid:0x%x app_mark:0x%x dns_netid:0x%x dns_mark:0x%x uid:%d", 3006d4669fa924315139f3636368c6623209fbfc3eaErik Kline nc.app_netid, nc.app_mark, nc.dns_netid, nc.dns_mark, uid); 3016d4669fa924315139f3636368c6623209fbfc3eaErik Kline } 3026d4669fa924315139f3636368c6623209fbfc3eaErik Kline 303cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline if (netcontext) { 304cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline *netcontext = nc; 305cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline } 306cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline} 307cea2d3455eb7c0d9ad1430607cbe98cc09251c1fErik Kline 308e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranunsigned NetworkController::getNetworkForInterface(const char* interface) const { 309f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 31036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran for (const auto& entry : mNetworks) { 3114043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (entry.second->hasInterface(interface)) { 3124043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return entry.first; 3134043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 3144043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 31535c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen return NETID_UNSET; 316a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 317a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 318070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandranbool NetworkController::isVirtualNetwork(unsigned netId) const { 319070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 320070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran Network* network = getNetworkLocked(netId); 321070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran return network && network->getType() == Network::VIRTUAL; 322070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran} 323070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran 3247e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkarint NetworkController::createPhysicalNetworkLocked(unsigned netId, Permission permission) { 325bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran if (!((MIN_NET_ID <= netId && netId <= MAX_NET_ID) || 326bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran (MIN_OEM_ID <= netId && netId <= MAX_OEM_ID))) { 327f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("invalid netId %u", netId); 32896f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 3295c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3305c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 3317e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar if (isValidNetworkLocked(netId)) { 332f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 333f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EEXIST; 3345c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3355c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 33648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId, mDelegateImpl); 337f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (int ret = physicalNetwork->setPermission(permission)) { 338f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! setPermission cannot fail on an empty network"); 339f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete physicalNetwork; 34096f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return ret; 341ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 342ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 34336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks[netId] = physicalNetwork; 34496f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 3455c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 3465c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 3477e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkarint NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) { 3487e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar android::RWLock::AutoWLock lock(mRWLock); 3497e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar return createPhysicalNetworkLocked(netId, permission); 3507e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar} 3517e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 3527e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkarint NetworkController::createPhysicalOemNetwork(Permission permission, unsigned *pNetId) { 3537e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar if (pNetId == NULL) { 3547e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar return -EINVAL; 3557e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar } 3567e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 3577e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar android::RWLock::AutoWLock lock(mRWLock); 3587e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar for (*pNetId = MIN_OEM_ID; *pNetId <= MAX_OEM_ID; (*pNetId)++) { 3597e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar if (!isValidNetworkLocked(*pNetId)) { 3607e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar break; 3617e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar } 3627e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar } 3637e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 3647e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar if (*pNetId > MAX_OEM_ID) { 3657e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar ALOGE("No free network ID"); 3667e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar *pNetId = 0; 3677e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar return -ENONET; 3687e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar } 3697e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 3707e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar int ret = createPhysicalNetworkLocked(*pNetId, permission); 3717e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar if (ret) { 3727e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar *pNetId = 0; 3737e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar } 3747e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 3757e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar return ret; 3767e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar} 3777e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 37895684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandranint NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) { 379bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) { 3804043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("invalid netId %u", netId); 3814043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EINVAL; 3824043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 3834043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 3844043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (isValidNetwork(netId)) { 3854043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 3864043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EEXIST; 3874043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 3884043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 3894043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 39048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthroughLocked(netId, true)) { 39148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 39248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 39395684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran mNetworks[netId] = new VirtualNetwork(netId, hasDns, secure); 3944043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return 0; 3954043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran} 3964043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 397f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::destroyNetwork(unsigned netId) { 398738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (netId == LOCAL_NET_ID) { 399738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot destroy local network"); 40096f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 401ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 402738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 403738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 404738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 405738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 406ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 407f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network. 40896f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti 409f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 410f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran Network* network = getNetworkLocked(netId); 41199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti 41299286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // If we fail to destroy a network, things will get stuck badly. Therefore, unlike most of the 41399286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // other network code, ignore failures and attempt to clear out as much state as possible, even 41499286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // if we hit an error on the way. Return the first error that we see. 41599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti int ret = network->clearInterfaces(); 41699286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti 417f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId == netId) { 41899286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (int err = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 419f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! removeAsDefault cannot fail on an empty network"); 42099286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (!ret) { 42199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti ret = err; 42299286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti } 423f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 424f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = NETID_UNSET; 42548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else if (network->getType() == Network::VIRTUAL) { 42699286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (int err = modifyFallthroughLocked(netId, false)) { 42799286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (!ret) { 42899286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti ret = err; 42999286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti } 43048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 431f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 43236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks.erase(netId); 433f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete network; 434f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran _resolv_delete_cache_for_net(netId); 43599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti return ret; 436f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 437ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 438f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) { 439f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (!isValidNetwork(netId)) { 440738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 441738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 442ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 443ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 444e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 445f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (existingNetId != NETID_UNSET && existingNetId != netId) { 446f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s already assigned to netId %u", interface, existingNetId); 447f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EBUSY; 448a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen } 449a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen 450f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 451f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->addInterface(interface); 452ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen} 453ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 454f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) { 45572604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran if (!isValidNetwork(netId)) { 456738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 457738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 4585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 4595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 460f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 461f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->removeInterface(interface); 462f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 4635c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 464f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranPermission NetworkController::getPermissionForUser(uid_t uid) const { 465f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 466ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return getPermissionForUserLocked(uid); 467f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 4685c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 469f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranvoid NetworkController::setPermissionForUsers(Permission permission, 470f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<uid_t>& uids) { 471f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 472f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (uid_t uid : uids) { 473ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran mUsers[uid] = permission; 4745c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 4755c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 4765c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 477a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccess(uid_t uid, unsigned netId) const { 478f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 479a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return checkUserNetworkAccessLocked(uid, netId); 480379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 481379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 482f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setPermissionForNetworks(Permission permission, 483f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<unsigned>& netIds) { 484f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 485f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (unsigned netId : netIds) { 48636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 487738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 488738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 489738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 490738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 491738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 492738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set permissions on non-physical network with netId %u", netId); 49396f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 494379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 495379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 49636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) { 497f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 498379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 499379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 50096f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 501379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 502379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 503b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) { 504b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 50536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 506738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 507738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 508738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 509738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 510738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 511738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot add users to non-virtual network with netId %u", netId); 512b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 513b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 514fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges, mProtectableUsers)) { 515b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 516b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 517b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 518b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 519b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 520b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) { 521b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 52236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 523738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 524738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 525738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 526738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 527738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 528738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot remove users from non-virtual network with netId %u", netId); 529b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 530b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 531fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges, 532fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti mProtectableUsers)) { 533b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 534b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 535b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 536b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 537b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 538f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::addRoute(unsigned netId, const char* interface, const char* destination, 539f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 54038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid); 5417619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 5427619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 543f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination, 544f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 54538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid); 5467619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 5477619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 548e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::canProtect(uid_t uid) const { 549e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 550e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) || 551e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran mProtectableUsers.find(uid) != mProtectableUsers.end(); 552e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 553e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 55489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::allowProtect(const std::vector<uid_t>& uids) { 55589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 55689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.insert(uids.begin(), uids.end()); 55789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 55889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 55989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::denyProtect(const std::vector<uid_t>& uids) { 56089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 56189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran for (uid_t uid : uids) { 56289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.erase(uid); 56389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran } 56489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 56589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 5662d3a163433c435ff053402ae8965f8602c7ac6daErik Klinevoid NetworkController::dump(DumpWriter& dw) { 5672d3a163433c435ff053402ae8965f8602c7ac6daErik Kline android::RWLock::AutoRLock lock(mRWLock); 5682d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5692d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.incIndent(); 5702d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println("NetworkController"); 5712d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5722d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.incIndent(); 5732d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println("Default network: %u", mDefaultNetId); 5742d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5752d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.blankline(); 5762d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.println("Networks:"); 5772d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.incIndent(); 5782d3a163433c435ff053402ae8965f8602c7ac6daErik Kline for (const auto& i : mNetworks) { 579d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti Network* network = i.second; 580d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti dw.println(network->toString().c_str()); 581d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti if (network->getType() == Network::PHYSICAL) { 582d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti dw.incIndent(); 583d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti Permission permission = reinterpret_cast<PhysicalNetwork*>(network)->getPermission(); 584d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti dw.println("Required permission: %s", permissionToName(permission)); 585d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti dw.decIndent(); 586d102965e157e16c5a7600616cfbabaaa7bc41acdLorenzo Colitti } 5873a272070fc318ef1a7a5a04e500483f1a7c629a8Pierre Imai android::net::gCtls->resolverCtrl.dump(dw, i.first); 5883a272070fc318ef1a7a5a04e500483f1a7c629a8Pierre Imai dw.blankline(); 5892d3a163433c435ff053402ae8965f8602c7ac6daErik Kline } 5902d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.decIndent(); 5912d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5922d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.decIndent(); 5932d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5942d3a163433c435ff053402ae8965f8602c7ac6daErik Kline dw.decIndent(); 5952d3a163433c435ff053402ae8965f8602c7ac6daErik Kline} 5962d3a163433c435ff053402ae8965f8602c7ac6daErik Kline 5977e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkarbool NetworkController::isValidNetworkLocked(unsigned netId) const { 5987e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar return getNetworkLocked(netId); 5997e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar} 6007e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar 601e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::isValidNetwork(unsigned netId) const { 602e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 6037e08f852440c4e9aaada7acc734e45920ec5c398Niranjan Pendharkar return isValidNetworkLocked(netId); 604e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 605e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 606f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranNetwork* NetworkController::getNetworkLocked(unsigned netId) const { 60736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran auto iter = mNetworks.find(netId); 60836ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran return iter == mNetworks.end() ? NULL : iter->second; 6097619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 6107619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 611e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram RamachandranVirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const { 612e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran for (const auto& entry : mNetworks) { 613e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 614e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second); 615e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (virtualNetwork->appliesToUser(uid)) { 616e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork; 617e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 618e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 619e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 620e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return NULL; 621e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 622e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 623ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission NetworkController::getPermissionForUserLocked(uid_t uid) const { 624ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran auto iter = mUsers.find(uid); 625ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if (iter != mUsers.end()) { 626ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return iter->second; 627ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran } 628ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE; 629ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran} 630ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran 631a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) const { 6321011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Network* network = getNetworkLocked(netId); 633a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (!network) { 634a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -ENONET; 635a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti } 636a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti 6371011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If uid is INVALID_UID, this likely means that we were unable to retrieve the UID of the peer 6381011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (using SO_PEERCRED). Be safe and deny access to the network, even if it's valid. 639a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (uid == INVALID_UID) { 640a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -EREMOTEIO; 6411011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 6421011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission userPermission = getPermissionForUserLocked(uid); 6431011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 644a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return 0; 6451011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 6461011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (network->getType() == Network::VIRTUAL) { 647a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return static_cast<VirtualNetwork*>(network)->appliesToUser(uid) ? 0 : -EPERM; 6481011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 6491011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 6501011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->isSecure() && 6511011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran mProtectableUsers.find(uid) == mProtectableUsers.end()) { 652a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -EPERM; 6531011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 6541011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission(); 655a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return ((userPermission & networkPermission) == networkPermission) ? 0 : -EACCES; 6561011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 6571011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 658f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination, 659f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool add, bool legacy, uid_t uid) { 660738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 661738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 662738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 663738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 664e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 665738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId == NETID_UNSET) { 666738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("interface %s not assigned to any netId", interface); 667738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENODEV; 668738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 669738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId != netId) { 670f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId); 671f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colitti return -ENOENT; 6727619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran } 6737619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 67438b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran RouteController::TableType tableType; 67587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran if (netId == LOCAL_NET_ID) { 67687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran tableType = RouteController::LOCAL_NETWORK; 67787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran } else if (legacy) { 678ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 6795009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_SYSTEM; 68038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 6815009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_NETWORK; 68238b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 68338b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 68438b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran tableType = RouteController::INTERFACE; 68538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 68638b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran 687eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran return add ? RouteController::addRoute(interface, destination, nexthop, tableType) : 688eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran RouteController::removeRoute(interface, destination, nexthop, tableType); 6897619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 69048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 69148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::modifyFallthroughLocked(unsigned vpnNetId, bool add) { 69248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (mDefaultNetId == NETID_UNSET) { 69348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 69448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 69548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 696738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 69748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 69848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return -ESRCH; 69948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 700738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 701738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("inconceivable! default network must be a physical network"); 702738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -EINVAL; 703738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 70448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission = static_cast<PhysicalNetwork*>(network)->getPermission(); 70548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& physicalInterface : network->getInterfaces()) { 70648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = mDelegateImpl->modifyFallthrough(vpnNetId, physicalInterface, permission, 70748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran add)) { 70848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 70948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 71048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 71148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 71248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 7137035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti 7147035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti} // namespace net 7157035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti} // namespace android 716