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.
49bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned MIN_NET_ID = 100;
50f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranconst unsigned MAX_NET_ID = 65535;
515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}  // namespace
535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
54bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MIN_OEM_ID   =  1;
55bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MAX_OEM_ID   = 50;
56bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran// NetIds 51..98 are reserved for future use.
57bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::LOCAL_NET_ID = 99;
58bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran
5948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran// All calls to methods here are made while holding a write lock on mRWLock.
6048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranclass NetworkController::DelegateImpl : public PhysicalNetwork::Delegate {
6148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranpublic:
6248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    explicit DelegateImpl(NetworkController* networkController);
6348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    virtual ~DelegateImpl();
6448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
6548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    int modifyFallthrough(unsigned vpnNetId, const std::string& physicalInterface,
6648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                          Permission permission, bool add) WARN_UNUSED_RESULT;
6748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
6848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranprivate:
6948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    int addFallthrough(const std::string& physicalInterface,
7048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                       Permission permission) override WARN_UNUSED_RESULT;
7148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    int removeFallthrough(const std::string& physicalInterface,
7248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                          Permission permission) override WARN_UNUSED_RESULT;
7348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
7448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    int modifyFallthrough(const std::string& physicalInterface, Permission permission,
7548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                          bool add) WARN_UNUSED_RESULT;
7648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
7748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    NetworkController* const mNetworkController;
7848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran};
7948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
8048e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::DelegateImpl(NetworkController* networkController) :
8148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        mNetworkController(networkController) {
8248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
8348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
8448e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::~DelegateImpl() {
8548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
8648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
8748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(unsigned vpnNetId,
8848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                       const std::string& physicalInterface,
8948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                       Permission permission, bool add) {
9048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    if (add) {
9148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        if (int ret = RouteController::addVirtualNetworkFallthrough(vpnNetId,
9248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                                    physicalInterface.c_str(),
9348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                                    permission)) {
9448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            ALOGE("failed to add fallthrough to %s for VPN netId %u", physicalInterface.c_str(),
9548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                  vpnNetId);
9648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            return ret;
9748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        }
9848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    } else {
9948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        if (int ret = RouteController::removeVirtualNetworkFallthrough(vpnNetId,
10048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                                       physicalInterface.c_str(),
10148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                                       permission)) {
10248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            ALOGE("failed to remove fallthrough to %s for VPN netId %u", physicalInterface.c_str(),
10348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                  vpnNetId);
10448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            return ret;
10548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        }
10648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    }
10748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    return 0;
10848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
10948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
11048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::addFallthrough(const std::string& physicalInterface,
11148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                    Permission permission) {
11248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    return modifyFallthrough(physicalInterface, permission, true);
11348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
11448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
11548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::removeFallthrough(const std::string& physicalInterface,
11648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                       Permission permission) {
11748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    return modifyFallthrough(physicalInterface, permission, false);
11848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
11948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
12048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(const std::string& physicalInterface,
12148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                       Permission permission, bool add) {
12248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    for (const auto& entry : mNetworkController->mNetworks) {
12348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        if (entry.second->getType() == Network::VIRTUAL) {
12448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            if (int ret = modifyFallthrough(entry.first, physicalInterface, permission, add)) {
12548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                return ret;
12648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            }
12748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        }
12848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    }
12948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    return 0;
13048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
13148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
13248e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::NetworkController() :
13348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        mDelegateImpl(new NetworkController::DelegateImpl(this)), mDefaultNetId(NETID_UNSET) {
13487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    mNetworks[LOCAL_NET_ID] = new LocalNetwork(LOCAL_NET_ID);
135a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak}
136a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak
137a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczakunsigned NetworkController::getDefaultNetwork() const {
1389c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
139a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    return mDefaultNetId;
140a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak}
141a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak
142f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setDefaultNetwork(unsigned netId) {
143f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
1449c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
145f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (netId == mDefaultNetId) {
146f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return 0;
1479c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    }
1489c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
149f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (netId != NETID_UNSET) {
15036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        Network* network = getNetworkLocked(netId);
151738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        if (!network) {
152738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti            ALOGE("no such netId %u", netId);
153738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti            return -ENONET;
154738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        }
155738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        if (network->getType() != Network::PHYSICAL) {
156738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti            ALOGE("cannot set default to non-physical network with netId %u", netId);
157f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return -EINVAL;
158f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
15936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) {
160f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return ret;
1619c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran        }
1629c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    }
1639c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
164f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (mDefaultNetId != NETID_UNSET) {
16536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        Network* network = getNetworkLocked(mDefaultNetId);
16636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        if (!network || network->getType() != Network::PHYSICAL) {
167f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
168f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return -ESRCH;
169f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
17036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
171f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return ret;
1729c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran        }
1739c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    }
1749c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
175f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    mDefaultNetId = netId;
176f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    return 0;
177a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak}
178a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak
1791011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranuint32_t NetworkController::getNetworkForDns(unsigned* netId, uid_t uid) const {
1801011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
1811011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    Fwmark fwmark;
1821011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    fwmark.protectedFromVpn = true;
1831011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    fwmark.permission = PERMISSION_SYSTEM;
184a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti    if (checkUserNetworkAccessLocked(uid, *netId) == 0) {
1851011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        // If a non-zero NetId was explicitly specified, and the user has permission for that
1861011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        // network, use that network's DNS servers. Do not fall through to the default network even
1871011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        // if the explicitly selected network is a split tunnel VPN or a VPN without DNS servers.
1881011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        fwmark.explicitlySelected = true;
1891011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    } else {
1901011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        // If the user is subject to a VPN and the VPN provides DNS servers, use those servers
1911011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        // (possibly falling through to the default network if the VPN doesn't provide a route to
1921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        // them). Otherwise, use the default network's DNS servers.
1931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
1941011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        if (virtualNetwork && virtualNetwork->getHasDns()) {
1951011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran            *netId = virtualNetwork->getNetId();
1961011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        } else {
1971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran            *netId = mDefaultNetId;
1981011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        }
1991011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    }
2001011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    fwmark.netId = *netId;
2011011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    return fwmark.intValue;
2021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran}
2031011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran
2041011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that a given UID would use if no network is explicitly selected. Specifically,
2051011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the VPN that applies to the UID if any; otherwise, the default network.
2061011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForUser(uid_t uid) const {
2071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
2081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    if (VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid)) {
2091011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran        return virtualNetwork->getNetId();
2101011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    }
2111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    return mDefaultNetId;
2121011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran}
2131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran
2141011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that will be set when a socket connect()s. This is the bypassable VPN that
2151011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// applies to the user if any; otherwise, the default network.
2161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran//
2171011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// In general, we prefer to always set the default network's NetId in connect(), so that if the VPN
2181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// is a split-tunnel and disappears later, the socket continues working (since the default network's
2191011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// NetId is still valid). Secure VPNs will correctly grab the socket's traffic since they have a
2201011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// high-priority routing rule that doesn't care what NetId the socket has.
2211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran//
2221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// But bypassable VPNs have a very low priority rule, so we need to mark the socket with the
2231011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// bypassable VPN's NetId if we expect it to get any traffic at all. If the bypassable VPN is a
2241011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// split-tunnel, that's okay, because we have fallthrough rules that will direct the fallthrough
2251011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// traffic to the default network. But it does mean that if the bypassable VPN goes away (and thus
2261011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the fallthrough rules also go away), the socket that used to fallthrough to the default network
2271011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// will stop working.
2281011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForConnect(uid_t uid) const {
229a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    android::RWLock::AutoRLock lock(mRWLock);
230e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
2311011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    if (virtualNetwork && !virtualNetwork->isSecure()) {
232e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        return virtualNetwork->getNetId();
233a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    }
2341011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    return mDefaultNetId;
235a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak}
236a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak
237e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranunsigned NetworkController::getNetworkForInterface(const char* interface) const {
238f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
23936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    for (const auto& entry : mNetworks) {
2404043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        if (entry.second->hasInterface(interface)) {
2414043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            return entry.first;
2424043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        }
2434043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    }
24435c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen    return NETID_UNSET;
245a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak}
246a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak
247070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandranbool NetworkController::isVirtualNetwork(unsigned netId) const {
248070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
249070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran    Network* network = getNetworkLocked(netId);
250070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran    return network && network->getType() == Network::VIRTUAL;
251070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran}
252070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran
253e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranint NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
254bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    if (!((MIN_NET_ID <= netId && netId <= MAX_NET_ID) ||
255bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran          (MIN_OEM_ID <= netId && netId <= MAX_OEM_ID))) {
256f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("invalid netId %u", netId);
25796f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti        return -EINVAL;
2585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
2595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
260f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (isValidNetwork(netId)) {
261f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("duplicate netId %u", netId);
262f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return -EEXIST;
2635c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
2645c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
26548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId, mDelegateImpl);
266f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (int ret = physicalNetwork->setPermission(permission)) {
267f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("inconceivable! setPermission cannot fail on an empty network");
268f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        delete physicalNetwork;
26996f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti        return ret;
270ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen    }
271ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
272f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
27336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    mNetworks[netId] = physicalNetwork;
27496f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti    return 0;
2755c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
2765c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
27795684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandranint NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) {
278bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) {
2794043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        ALOGE("invalid netId %u", netId);
2804043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        return -EINVAL;
2814043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    }
2824043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
2834043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    if (isValidNetwork(netId)) {
2844043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        ALOGE("duplicate netId %u", netId);
2854043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        return -EEXIST;
2864043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    }
2874043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
2884043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
28948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    if (int ret = modifyFallthroughLocked(netId, true)) {
29048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        return ret;
29148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    }
29295684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    mNetworks[netId] = new VirtualNetwork(netId, hasDns, secure);
2934043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    return 0;
2944043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran}
2954043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
296f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::destroyNetwork(unsigned netId) {
297738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (netId == LOCAL_NET_ID) {
298738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("cannot destroy local network");
29996f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti        return -EINVAL;
300ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen    }
301738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (!isValidNetwork(netId)) {
302738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("no such netId %u", netId);
303738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENONET;
304738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    }
305ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
306f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
30796f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti
308f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
309f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    Network* network = getNetworkLocked(netId);
31099286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti
31199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti    // If we fail to destroy a network, things will get stuck badly. Therefore, unlike most of the
31299286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti    // other network code, ignore failures and attempt to clear out as much state as possible, even
31399286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti    // if we hit an error on the way. Return the first error that we see.
31499286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti    int ret = network->clearInterfaces();
31599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti
316f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (mDefaultNetId == netId) {
31799286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti        if (int err = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
318f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            ALOGE("inconceivable! removeAsDefault cannot fail on an empty network");
31999286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti            if (!ret) {
32099286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti                ret = err;
32199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti            }
322f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
323f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        mDefaultNetId = NETID_UNSET;
32448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    } else if (network->getType() == Network::VIRTUAL) {
32599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti        if (int err = modifyFallthroughLocked(netId, false)) {
32699286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti            if (!ret) {
32799286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti                ret = err;
32899286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti            }
32948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        }
330f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
33136ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    mNetworks.erase(netId);
332f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    delete network;
333f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    _resolv_delete_cache_for_net(netId);
33499286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti    return ret;
335f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran}
336ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
337f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
338f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (!isValidNetwork(netId)) {
339738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("no such netId %u", netId);
340738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENONET;
341ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen    }
342ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
343e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    unsigned existingNetId = getNetworkForInterface(interface);
344f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (existingNetId != NETID_UNSET && existingNetId != netId) {
345f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
346f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return -EBUSY;
347a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen    }
348a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen
349f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
350f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    return getNetworkLocked(netId)->addInterface(interface);
351ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen}
352ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
353f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
35472604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran    if (!isValidNetwork(netId)) {
355738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("no such netId %u", netId);
356738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENONET;
3575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
3585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
359f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
360f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    return getNetworkLocked(netId)->removeInterface(interface);
361f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran}
3625c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
363f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranPermission NetworkController::getPermissionForUser(uid_t uid) const {
364f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
365ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    return getPermissionForUserLocked(uid);
366f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran}
3675c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
368f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranvoid NetworkController::setPermissionForUsers(Permission permission,
369f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                              const std::vector<uid_t>& uids) {
370f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
371f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    for (uid_t uid : uids) {
372ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        mUsers[uid] = permission;
3735c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
3745c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
3755c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
376a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccess(uid_t uid, unsigned netId) const {
377f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
378a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti    return checkUserNetworkAccessLocked(uid, netId);
379379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}
380379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
381f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setPermissionForNetworks(Permission permission,
382f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                                const std::vector<unsigned>& netIds) {
383f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
384f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    for (unsigned netId : netIds) {
38536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        Network* network = getNetworkLocked(netId);
386738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        if (!network) {
387738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti            ALOGE("no such netId %u", netId);
388738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti            return -ENONET;
389738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        }
390738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        if (network->getType() != Network::PHYSICAL) {
391738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti            ALOGE("cannot set permissions on non-physical network with netId %u", netId);
39296f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti            return -EINVAL;
393379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
394379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
395f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission.
396379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
39736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran        if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) {
398f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return ret;
399379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
400379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    }
40196f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti    return 0;
402379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}
403379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
404b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) {
405b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
40636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    Network* network = getNetworkLocked(netId);
407738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (!network) {
408738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("no such netId %u", netId);
409738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENONET;
410738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    }
411738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (network->getType() != Network::VIRTUAL) {
412738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("cannot add users to non-virtual network with netId %u", netId);
413b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        return -EINVAL;
414b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
41536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) {
416b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        return ret;
417b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
418b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    return 0;
419b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
420b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
421b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) {
422b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
42336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    Network* network = getNetworkLocked(netId);
424738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (!network) {
425738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("no such netId %u", netId);
426738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENONET;
427738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    }
428738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (network->getType() != Network::VIRTUAL) {
429738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("cannot remove users from non-virtual network with netId %u", netId);
430b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        return -EINVAL;
431b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
43236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) {
433b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        return ret;
434b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
435b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    return 0;
436b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
437b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
438f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
439f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                const char* nexthop, bool legacy, uid_t uid) {
44038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran    return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
4417619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
4427619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
443f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
444f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                   const char* nexthop, bool legacy, uid_t uid) {
44538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran    return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
4467619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
4477619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
448e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::canProtect(uid_t uid) const {
449e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
450e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) ||
451e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran           mProtectableUsers.find(uid) != mProtectableUsers.end();
452e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
453e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
45489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::allowProtect(const std::vector<uid_t>& uids) {
45589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
45689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    mProtectableUsers.insert(uids.begin(), uids.end());
45789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran}
45889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran
45989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::denyProtect(const std::vector<uid_t>& uids) {
46089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    android::RWLock::AutoWLock lock(mRWLock);
46189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    for (uid_t uid : uids) {
46289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        mProtectableUsers.erase(uid);
46389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    }
46489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran}
46589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran
466e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::isValidNetwork(unsigned netId) const {
467e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    android::RWLock::AutoRLock lock(mRWLock);
468e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return getNetworkLocked(netId);
469e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
470e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
471f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranNetwork* NetworkController::getNetworkLocked(unsigned netId) const {
47236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    auto iter = mNetworks.find(netId);
47336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran    return iter == mNetworks.end() ? NULL : iter->second;
4747619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
4757619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
476e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram RamachandranVirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const {
477e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    for (const auto& entry : mNetworks) {
478e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        if (entry.second->getType() == Network::VIRTUAL) {
479e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran            VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second);
480e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran            if (virtualNetwork->appliesToUser(uid)) {
481e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran                return virtualNetwork;
482e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran            }
483e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        }
484e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    }
485e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return NULL;
486e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
487e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
488ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission NetworkController::getPermissionForUserLocked(uid_t uid) const {
489ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    auto iter = mUsers.find(uid);
490ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    if (iter != mUsers.end()) {
491ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        return iter->second;
492ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    }
493ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE;
494ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran}
495ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran
496a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) const {
4971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    Network* network = getNetworkLocked(netId);
498a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti    if (!network) {
499a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti        return -ENONET;
500a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti    }
501a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti
5021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    // If uid is INVALID_UID, this likely means that we were unable to retrieve the UID of the peer
5031011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    // (using SO_PEERCRED). Be safe and deny access to the network, even if it's valid.
504a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti    if (uid == INVALID_UID) {
505a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti        return -EREMOTEIO;
5061011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    }
5071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    Permission userPermission = getPermissionForUserLocked(uid);
5081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
509a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti        return 0;
5101011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    }
5111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    if (network->getType() == Network::VIRTUAL) {
512a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti        return static_cast<VirtualNetwork*>(network)->appliesToUser(uid) ? 0 : -EPERM;
5131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    }
5141011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
5151011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    if (virtualNetwork && virtualNetwork->isSecure() &&
5161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran            mProtectableUsers.find(uid) == mProtectableUsers.end()) {
517a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti        return -EPERM;
5181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    }
5191011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran    Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission();
520a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti    return ((userPermission & networkPermission) == networkPermission) ? 0 : -EACCES;
5211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran}
5221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran
523f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
524f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                   const char* nexthop, bool add, bool legacy, uid_t uid) {
525738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (!isValidNetwork(netId)) {
526738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("no such netId %u", netId);
527738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENONET;
528738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    }
529e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    unsigned existingNetId = getNetworkForInterface(interface);
530738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (existingNetId == NETID_UNSET) {
531738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("interface %s not assigned to any netId", interface);
532738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -ENODEV;
533738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    }
534738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (existingNetId != netId) {
535f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
536f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colitti        return -ENOENT;
5377619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    }
5387619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
53938b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran    RouteController::TableType tableType;
54087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (netId == LOCAL_NET_ID) {
54187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        tableType = RouteController::LOCAL_NETWORK;
54287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    } else if (legacy) {
543ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
5445009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran            tableType = RouteController::LEGACY_SYSTEM;
54538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran        } else {
5465009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran            tableType = RouteController::LEGACY_NETWORK;
54738b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran        }
54838b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran    } else {
54938b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran        tableType = RouteController::INTERFACE;
55038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran    }
55138b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran
552eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran    return add ? RouteController::addRoute(interface, destination, nexthop, tableType) :
553eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran                 RouteController::removeRoute(interface, destination, nexthop, tableType);
5547619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
55548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran
55648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::modifyFallthroughLocked(unsigned vpnNetId, bool add) {
55748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    if (mDefaultNetId == NETID_UNSET) {
55848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        return 0;
55948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    }
56048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    Network* network = getNetworkLocked(mDefaultNetId);
561738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (!network) {
56248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
56348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        return -ESRCH;
56448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    }
565738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    if (network->getType() != Network::PHYSICAL) {
566738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        ALOGE("inconceivable! default network must be a physical network");
567738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti        return -EINVAL;
568738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti    }
56948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    Permission permission = static_cast<PhysicalNetwork*>(network)->getPermission();
57048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    for (const auto& physicalInterface : network->getInterfaces()) {
57148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        if (int ret = mDelegateImpl->modifyFallthrough(vpnNetId, physicalInterface, permission,
57248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran                                                       add)) {
57348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran            return ret;
57448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran        }
57548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    }
57648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran    return 0;
57748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}
578