NetworkController.cpp revision 738c93ee075354ffafb3a8ceef76e9aa711f057b
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 351011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran#include "Fwmark.h" 366a773534e7f8541f221f27fb8063af079b1a5936Sreeram Ramachandran#include "LocalNetwork.h" 37f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#include "PhysicalNetwork.h" 385c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "RouteController.h" 394043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#include "VirtualNetwork.h" 405c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 41ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran#include "cutils/misc.h" 42f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#define LOG_TAG "Netd" 43f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#include "log/log.h" 4472604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran#include "resolv_netid.h" 4572604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran 465c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandrannamespace { 475c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 485c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran// Keep these in sync with ConnectivityService.java. 49f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranconst unsigned MIN_NET_ID = 10; 50f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranconst unsigned MAX_NET_ID = 65535; 515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} // namespace 535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 5448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran// All calls to methods here are made while holding a write lock on mRWLock. 5548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranclass NetworkController::DelegateImpl : public PhysicalNetwork::Delegate { 5648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranpublic: 5748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran explicit DelegateImpl(NetworkController* networkController); 5848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran virtual ~DelegateImpl(); 5948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 6048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(unsigned vpnNetId, const std::string& physicalInterface, 6148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) WARN_UNUSED_RESULT; 6248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 6348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranprivate: 6448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int addFallthrough(const std::string& physicalInterface, 6548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 6648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int removeFallthrough(const std::string& physicalInterface, 6748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 6848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 6948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(const std::string& physicalInterface, Permission permission, 7048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran bool add) WARN_UNUSED_RESULT; 7148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran NetworkController* const mNetworkController; 7348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}; 7448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7548e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::DelegateImpl(NetworkController* networkController) : 7648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran mNetworkController(networkController) { 7748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 7848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7948e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::~DelegateImpl() { 8048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 8148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(unsigned vpnNetId, 8348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran const std::string& physicalInterface, 8448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 8548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (add) { 8648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::addVirtualNetworkFallthrough(vpnNetId, 8748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 8848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 8948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to add fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 9048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 9148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 9248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 9348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else { 9448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::removeVirtualNetworkFallthrough(vpnNetId, 9548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 9648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 9748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to remove fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 9848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 9948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 10048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 10148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 10248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 10348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 10448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 10548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::addFallthrough(const std::string& physicalInterface, 10648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 10748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, true); 10848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 10948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 11048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::removeFallthrough(const std::string& physicalInterface, 11148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 11248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, false); 11348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 11448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 11548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(const std::string& physicalInterface, 11648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 11748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& entry : mNetworkController->mNetworks) { 11848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 11948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthrough(entry.first, physicalInterface, permission, add)) { 12048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 12148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 12248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 12348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 12448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 12548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 12648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 12748e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::NetworkController() : 12848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran mDelegateImpl(new NetworkController::DelegateImpl(this)), mDefaultNetId(NETID_UNSET) { 12987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran mNetworks[LOCAL_NET_ID] = new LocalNetwork(LOCAL_NET_ID); 130a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 131a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 132a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczakunsigned NetworkController::getDefaultNetwork() const { 1339c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 134a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak return mDefaultNetId; 135a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 136a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 137f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setDefaultNetwork(unsigned netId) { 138f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 1399c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 140f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId == mDefaultNetId) { 141f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 1429c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1439c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 144f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId != NETID_UNSET) { 14536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 146738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 147738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 148738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 149738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 150738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 151738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set default to non-physical network with netId %u", netId); 152f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EINVAL; 153f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 15436ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) { 155f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1569c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1579c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1589c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 159f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId != NETID_UNSET) { 16036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 16136ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (!network || network->getType() != Network::PHYSICAL) { 162f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 163f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -ESRCH; 164f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 16536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 166f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1679c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1689c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1699c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 170f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = netId; 171f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 172a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 173a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 1741011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranuint32_t NetworkController::getNetworkForDns(unsigned* netId, uid_t uid) const { 1751011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 1761011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Fwmark fwmark; 1771011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.protectedFromVpn = true; 1781011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.permission = PERMISSION_SYSTEM; 1791011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (canUserSelectNetworkLocked(uid, *netId)) { 1801011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If a non-zero NetId was explicitly specified, and the user has permission for that 1811011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // network, use that network's DNS servers. Do not fall through to the default network even 1821011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // if the explicitly selected network is a split tunnel VPN or a VPN without DNS servers. 1831011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.explicitlySelected = true; 1841011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 1851011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If the user is subject to a VPN and the VPN provides DNS servers, use those servers 1861011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (possibly falling through to the default network if the VPN doesn't provide a route to 1871011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // them). Otherwise, use the default network's DNS servers. 1881011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 1891011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->getHasDns()) { 1901011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = virtualNetwork->getNetId(); 1911011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 1921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = mDefaultNetId; 1931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 1941011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 1951011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.netId = *netId; 1961011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return fwmark.intValue; 1971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 1981011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 1991011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that a given UID would use if no network is explicitly selected. Specifically, 2001011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the VPN that applies to the UID if any; otherwise, the default network. 2011011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForUser(uid_t uid) const { 2021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 2031011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid)) { 2041011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return virtualNetwork->getNetId(); 2051011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2061011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 2071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2091011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that will be set when a socket connect()s. This is the bypassable VPN that 2101011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// applies to the user if any; otherwise, the default network. 2111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2121011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// In general, we prefer to always set the default network's NetId in connect(), so that if the VPN 2131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// is a split-tunnel and disappears later, the socket continues working (since the default network's 2141011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// NetId is still valid). Secure VPNs will correctly grab the socket's traffic since they have a 2151011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// high-priority routing rule that doesn't care what NetId the socket has. 2161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2171011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// But bypassable VPNs have a very low priority rule, so we need to mark the socket with the 2181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// bypassable VPN's NetId if we expect it to get any traffic at all. If the bypassable VPN is a 2191011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// split-tunnel, that's okay, because we have fallthrough rules that will direct the fallthrough 2201011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// traffic to the default network. But it does mean that if the bypassable VPN goes away (and thus 2211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the fallthrough rules also go away), the socket that used to fallthrough to the default network 2221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// will stop working. 2231011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForConnect(uid_t uid) const { 224a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak android::RWLock::AutoRLock lock(mRWLock); 225e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 2261011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && !virtualNetwork->isSecure()) { 227e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork->getNetId(); 228a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak } 2291011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 230a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 231a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 232e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranunsigned NetworkController::getNetworkForInterface(const char* interface) const { 233f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 23436ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran for (const auto& entry : mNetworks) { 2354043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (entry.second->hasInterface(interface)) { 2364043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return entry.first; 2374043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 2384043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 23935c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen return NETID_UNSET; 240a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 241a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 242070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandranbool NetworkController::isVirtualNetwork(unsigned netId) const { 243070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 244070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran Network* network = getNetworkLocked(netId); 245070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran return network && network->getType() == Network::VIRTUAL; 246070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran} 247070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran 248e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranint NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) { 249f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId < MIN_NET_ID || netId > MAX_NET_ID) { 250f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("invalid netId %u", netId); 25196f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 2525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 2535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 254f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (isValidNetwork(netId)) { 255f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 256f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EEXIST; 2575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 2585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 25948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId, mDelegateImpl); 260f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (int ret = physicalNetwork->setPermission(permission)) { 261f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! setPermission cannot fail on an empty network"); 262f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete physicalNetwork; 26396f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return ret; 264ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 265ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 266f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 26736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks[netId] = physicalNetwork; 26896f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 2695c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 2705c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 27195684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandranint NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) { 2724043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (netId < MIN_NET_ID || netId > MAX_NET_ID) { 2734043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("invalid netId %u", netId); 2744043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EINVAL; 2754043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 2764043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 2774043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (isValidNetwork(netId)) { 2784043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 2794043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EEXIST; 2804043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 2814043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 2824043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 28348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthroughLocked(netId, true)) { 28448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 28548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 28695684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran mNetworks[netId] = new VirtualNetwork(netId, hasDns, secure); 2874043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return 0; 2884043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran} 2894043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 290f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::destroyNetwork(unsigned netId) { 291738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (netId == LOCAL_NET_ID) { 292738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot destroy local network"); 29396f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 294ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 295738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 296738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 297738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 298738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 299ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 300f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network. 30196f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti 302f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 303f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran Network* network = getNetworkLocked(netId); 304f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (int ret = network->clearInterfaces()) { 30596f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return ret; 306ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 307f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId == netId) { 30836ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 309f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! removeAsDefault cannot fail on an empty network"); 310f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 311f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 312f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = NETID_UNSET; 31348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else if (network->getType() == Network::VIRTUAL) { 31448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthroughLocked(netId, false)) { 31548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 31648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 317f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 31836ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks.erase(netId); 319f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete network; 320f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran _resolv_delete_cache_for_net(netId); 321f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 322f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 323ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 324f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) { 325f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (!isValidNetwork(netId)) { 326738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 327738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 328ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 329ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 330e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 331f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (existingNetId != NETID_UNSET && existingNetId != netId) { 332f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s already assigned to netId %u", interface, existingNetId); 333f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EBUSY; 334a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen } 335a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen 336f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 337f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->addInterface(interface); 338ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen} 339ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 340f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) { 34172604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran if (!isValidNetwork(netId)) { 342738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 343738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 3445c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3455c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 346f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 347f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->removeInterface(interface); 348f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 3495c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 350f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranPermission NetworkController::getPermissionForUser(uid_t uid) const { 351f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 352ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return getPermissionForUserLocked(uid); 353f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 3545c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 355f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranvoid NetworkController::setPermissionForUsers(Permission permission, 356f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<uid_t>& uids) { 357f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 358f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (uid_t uid : uids) { 359ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran mUsers[uid] = permission; 3605c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3615c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 3625c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 363e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::canUserSelectNetwork(uid_t uid, unsigned netId) const { 364f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 3651011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return canUserSelectNetworkLocked(uid, netId); 366379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 367379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 368f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setPermissionForNetworks(Permission permission, 369f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<unsigned>& netIds) { 370f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 371f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (unsigned netId : netIds) { 37236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 373738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 374738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 375738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 376738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 377738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 378738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set permissions on non-physical network with netId %u", netId); 37996f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 380379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 381379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 382f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission. 383379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 38436ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) { 385f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 386379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 387379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 38896f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 389379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 390379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 391b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) { 392b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 39336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 394738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 395738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 396738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 397738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 398738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 399738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot add users to non-virtual network with netId %u", netId); 400b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 401b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 40236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) { 403b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 404b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 405b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 406b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 407b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 408b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) { 409b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 41036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 411738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 412738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 413738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 414738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 415738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 416738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot remove users from non-virtual network with netId %u", netId); 417b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 418b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 41936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) { 420b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 421b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 422b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 423b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 424b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 425f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::addRoute(unsigned netId, const char* interface, const char* destination, 426f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 42738b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid); 4287619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 4297619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 430f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination, 431f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 43238b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid); 4337619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 4347619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 435e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::canProtect(uid_t uid) const { 436e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 437e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) || 438e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran mProtectableUsers.find(uid) != mProtectableUsers.end(); 439e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 440e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 44189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::allowProtect(const std::vector<uid_t>& uids) { 44289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 44389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.insert(uids.begin(), uids.end()); 44489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 44589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 44689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::denyProtect(const std::vector<uid_t>& uids) { 44789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 44889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran for (uid_t uid : uids) { 44989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.erase(uid); 45089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran } 45189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 45289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 453e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::isValidNetwork(unsigned netId) const { 454e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 455e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return getNetworkLocked(netId); 456e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 457e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 458f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranNetwork* NetworkController::getNetworkLocked(unsigned netId) const { 45936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran auto iter = mNetworks.find(netId); 46036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran return iter == mNetworks.end() ? NULL : iter->second; 4617619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 4627619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 463e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram RamachandranVirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const { 464e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran for (const auto& entry : mNetworks) { 465e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 466e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second); 467e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (virtualNetwork->appliesToUser(uid)) { 468e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork; 469e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 470e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 471e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 472e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return NULL; 473e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 474e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 475ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission NetworkController::getPermissionForUserLocked(uid_t uid) const { 476ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran auto iter = mUsers.find(uid); 477ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if (iter != mUsers.end()) { 478ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return iter->second; 479ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran } 480ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE; 481ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran} 482ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran 4831011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranbool NetworkController::canUserSelectNetworkLocked(uid_t uid, unsigned netId) const { 4841011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Network* network = getNetworkLocked(netId); 4851011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If uid is INVALID_UID, this likely means that we were unable to retrieve the UID of the peer 4861011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (using SO_PEERCRED). Be safe and deny access to the network, even if it's valid. 4871011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (!network || uid == INVALID_UID) { 4881011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return false; 4891011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 4901011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission userPermission = getPermissionForUserLocked(uid); 4911011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 4921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return true; 4931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 4941011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (network->getType() == Network::VIRTUAL) { 4951011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return static_cast<VirtualNetwork*>(network)->appliesToUser(uid); 4961011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 4971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 4981011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->isSecure() && 4991011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran mProtectableUsers.find(uid) == mProtectableUsers.end()) { 5001011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return false; 5011011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission(); 5031011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return (userPermission & networkPermission) == networkPermission; 5041011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 5051011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 506f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination, 507f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool add, bool legacy, uid_t uid) { 508738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 509738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 510738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 511738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 512e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 513738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId == NETID_UNSET) { 514738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("interface %s not assigned to any netId", interface); 515738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENODEV; 516738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 517738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId != netId) { 518f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId); 519f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colitti return -ENOENT; 5207619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran } 5217619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 52238b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran RouteController::TableType tableType; 52387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran if (netId == LOCAL_NET_ID) { 52487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran tableType = RouteController::LOCAL_NETWORK; 52587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran } else if (legacy) { 526ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 5275009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_SYSTEM; 52838b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 5295009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_NETWORK; 53038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 53138b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 53238b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran tableType = RouteController::INTERFACE; 53338b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 53438b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran 535eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran return add ? RouteController::addRoute(interface, destination, nexthop, tableType) : 536eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran RouteController::removeRoute(interface, destination, nexthop, tableType); 5377619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 53848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 53948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::modifyFallthroughLocked(unsigned vpnNetId, bool add) { 54048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (mDefaultNetId == NETID_UNSET) { 54148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 54248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 54348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 544738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 54548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 54648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return -ESRCH; 54748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 548738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 549738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("inconceivable! default network must be a physical network"); 550738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -EINVAL; 551738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 55248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission = static_cast<PhysicalNetwork*>(network)->getPermission(); 55348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& physicalInterface : network->getInterfaces()) { 55448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = mDelegateImpl->modifyFallthrough(vpnNetId, physicalInterface, permission, 55548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran add)) { 55648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 55748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 55848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 55948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 56048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 561