VirtualNetwork.cpp revision fff4bd31ff2bad0acfd8f2439eccf7df70e9695f
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <set>
18#include "VirtualNetwork.h"
19
20#include "SockDiag.h"
21#include "RouteController.h"
22
23#define LOG_TAG "Netd"
24#include "log/log.h"
25
26VirtualNetwork::VirtualNetwork(unsigned netId, bool hasDns, bool secure) :
27        Network(netId), mHasDns(hasDns), mSecure(secure) {
28}
29
30VirtualNetwork::~VirtualNetwork() {
31}
32
33bool VirtualNetwork::getHasDns() const {
34    return mHasDns;
35}
36
37bool VirtualNetwork::isSecure() const {
38    return mSecure;
39}
40
41bool VirtualNetwork::appliesToUser(uid_t uid) const {
42    return mUidRanges.hasUid(uid);
43}
44
45
46int VirtualNetwork::maybeCloseSockets(bool add, const UidRanges& uidRanges,
47                                      const std::set<uid_t>& protectableUsers) {
48    if (!mSecure) {
49        return 0;
50    }
51
52    SockDiag sd;
53    if (!sd.open()) {
54        return -EBADFD;
55    }
56
57    if (int ret = sd.destroySockets(uidRanges, protectableUsers)) {
58        ALOGE("Failed to close sockets while %s %s to network %d: %s",
59              add ? "adding" : "removing", uidRanges.toString().c_str(), mNetId, strerror(-ret));
60        return ret;
61    }
62
63    return 0;
64}
65
66int VirtualNetwork::addUsers(const UidRanges& uidRanges, const std::set<uid_t>& protectableUsers) {
67    maybeCloseSockets(true, uidRanges, protectableUsers);
68
69    for (const std::string& interface : mInterfaces) {
70        if (int ret = RouteController::addUsersToVirtualNetwork(mNetId, interface.c_str(), mSecure,
71                                                                uidRanges)) {
72            ALOGE("failed to add users on interface %s of netId %u", interface.c_str(), mNetId);
73            return ret;
74        }
75    }
76    mUidRanges.add(uidRanges);
77    return 0;
78}
79
80int VirtualNetwork::removeUsers(const UidRanges& uidRanges,
81                                const std::set<uid_t>& protectableUsers) {
82    maybeCloseSockets(false, uidRanges, protectableUsers);
83
84    for (const std::string& interface : mInterfaces) {
85        if (int ret = RouteController::removeUsersFromVirtualNetwork(mNetId, interface.c_str(),
86                                                                     mSecure, uidRanges)) {
87            ALOGE("failed to remove users on interface %s of netId %u", interface.c_str(), mNetId);
88            return ret;
89        }
90    }
91    mUidRanges.remove(uidRanges);
92    return 0;
93}
94
95Network::Type VirtualNetwork::getType() const {
96    return VIRTUAL;
97}
98
99int VirtualNetwork::addInterface(const std::string& interface) {
100    if (hasInterface(interface)) {
101        return 0;
102    }
103    if (int ret = RouteController::addInterfaceToVirtualNetwork(mNetId, interface.c_str(), mSecure,
104                                                                mUidRanges)) {
105        ALOGE("failed to add interface %s to VPN netId %u", interface.c_str(), mNetId);
106        return ret;
107    }
108    mInterfaces.insert(interface);
109    return 0;
110}
111
112int VirtualNetwork::removeInterface(const std::string& interface) {
113    if (!hasInterface(interface)) {
114        return 0;
115    }
116    if (int ret = RouteController::removeInterfaceFromVirtualNetwork(mNetId, interface.c_str(),
117                                                                     mSecure, mUidRanges)) {
118        ALOGE("failed to remove interface %s from VPN netId %u", interface.c_str(), mNetId);
119        return ret;
120    }
121    mInterfaces.erase(interface);
122    return 0;
123}
124