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