14043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran/*
24043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * Copyright (C) 2014 The Android Open Source Project
34043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran *
44043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * Licensed under the Apache License, Version 2.0 (the "License");
54043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * you may not use this file except in compliance with the License.
64043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * You may obtain a copy of the License at
74043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran *
84043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran *      http://www.apache.org/licenses/LICENSE-2.0
94043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran *
104043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * Unless required by applicable law or agreed to in writing, software
114043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * distributed under the License is distributed on an "AS IS" BASIS,
124043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * See the License for the specific language governing permissions and
144043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran * limitations under the License.
154043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran */
164043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
17fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <set>
184043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#include "VirtualNetwork.h"
194043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
20fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include "SockDiag.h"
214043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#include "RouteController.h"
224043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
234043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#define LOG_TAG "Netd"
244043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#include "log/log.h"
254043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
267035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colittinamespace android {
277035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colittinamespace net {
287035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti
2995684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram RamachandranVirtualNetwork::VirtualNetwork(unsigned netId, bool hasDns, bool secure) :
3095684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran        Network(netId), mHasDns(hasDns), mSecure(secure) {
314043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran}
324043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
334043f01f8e25f24246efadc710ad7440aab75529Sreeram RamachandranVirtualNetwork::~VirtualNetwork() {
344043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran}
354043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran
36e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool VirtualNetwork::getHasDns() const {
37e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return mHasDns;
384043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran}
39b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
4095684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandranbool VirtualNetwork::isSecure() const {
4195684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    return mSecure;
4295684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran}
4395684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran
44e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool VirtualNetwork::appliesToUser(uid_t uid) const {
45e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return mUidRanges.hasUid(uid);
4636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran}
4736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran
48fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
49fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittiint VirtualNetwork::maybeCloseSockets(bool add, const UidRanges& uidRanges,
50fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti                                      const std::set<uid_t>& protectableUsers) {
51fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    if (!mSecure) {
52fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        return 0;
53fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
54fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
55fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    SockDiag sd;
56fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    if (!sd.open()) {
57fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        return -EBADFD;
58fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
59fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
600726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    if (int ret = sd.destroySockets(uidRanges, protectableUsers, true /* excludeLoopback */)) {
61fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        ALOGE("Failed to close sockets while %s %s to network %d: %s",
62fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti              add ? "adding" : "removing", uidRanges.toString().c_str(), mNetId, strerror(-ret));
63fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        return ret;
64fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
65fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
66fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    return 0;
67fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti}
68fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
69fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittiint VirtualNetwork::addUsers(const UidRanges& uidRanges, const std::set<uid_t>& protectableUsers) {
70fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    maybeCloseSockets(true, uidRanges, protectableUsers);
71fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
72b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    for (const std::string& interface : mInterfaces) {
7395684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran        if (int ret = RouteController::addUsersToVirtualNetwork(mNetId, interface.c_str(), mSecure,
745009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran                                                                uidRanges)) {
75b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            ALOGE("failed to add users on interface %s of netId %u", interface.c_str(), mNetId);
76b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return ret;
77b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
78b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
79b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    mUidRanges.add(uidRanges);
80b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    return 0;
81b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
82b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
83fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittiint VirtualNetwork::removeUsers(const UidRanges& uidRanges,
84fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti                                const std::set<uid_t>& protectableUsers) {
85fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    maybeCloseSockets(false, uidRanges, protectableUsers);
86fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
87b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    for (const std::string& interface : mInterfaces) {
885009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran        if (int ret = RouteController::removeUsersFromVirtualNetwork(mNetId, interface.c_str(),
8995684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran                                                                     mSecure, uidRanges)) {
90b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            ALOGE("failed to remove users on interface %s of netId %u", interface.c_str(), mNetId);
91b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return ret;
92b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
93b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
94b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    mUidRanges.remove(uidRanges);
95b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    return 0;
96b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran}
97e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
98e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram RamachandranNetwork::Type VirtualNetwork::getType() const {
99e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return VIRTUAL;
100e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
101e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
102e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranint VirtualNetwork::addInterface(const std::string& interface) {
103e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    if (hasInterface(interface)) {
104e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        return 0;
105e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    }
10695684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    if (int ret = RouteController::addInterfaceToVirtualNetwork(mNetId, interface.c_str(), mSecure,
107e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran                                                                mUidRanges)) {
108e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        ALOGE("failed to add interface %s to VPN netId %u", interface.c_str(), mNetId);
109e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        return ret;
110e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    }
111e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    mInterfaces.insert(interface);
112e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return 0;
113e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
114e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran
115e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranint VirtualNetwork::removeInterface(const std::string& interface) {
116e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    if (!hasInterface(interface)) {
117e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        return 0;
118e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    }
119e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    if (int ret = RouteController::removeInterfaceFromVirtualNetwork(mNetId, interface.c_str(),
12095684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran                                                                     mSecure, mUidRanges)) {
121e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        ALOGE("failed to remove interface %s from VPN netId %u", interface.c_str(), mNetId);
122e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran        return ret;
123e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    }
124e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    mInterfaces.erase(interface);
125e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran    return 0;
126e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran}
1277035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti
1287035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti}  // namespace net
1297035f228d17e925116b1b64a7c917b3196ab8818Lorenzo Colitti}  // namespace android
130