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 "PhysicalNetwork.h"
18
19#include "RouteController.h"
20
21#define LOG_TAG "Netd"
22#include "log/log.h"
23
24namespace {
25
26WARN_UNUSED_RESULT int addToDefault(unsigned netId, const std::string& interface,
27                                    Permission permission, PhysicalNetwork::Delegate* delegate) {
28    if (int ret = RouteController::addInterfaceToDefaultNetwork(interface.c_str(), permission)) {
29        ALOGE("failed to add interface %s to default netId %u", interface.c_str(), netId);
30        return ret;
31    }
32    if (int ret = delegate->addFallthrough(interface, permission)) {
33        return ret;
34    }
35    return 0;
36}
37
38WARN_UNUSED_RESULT int removeFromDefault(unsigned netId, const std::string& interface,
39                                         Permission permission,
40                                         PhysicalNetwork::Delegate* delegate) {
41    if (int ret = RouteController::removeInterfaceFromDefaultNetwork(interface.c_str(),
42                                                                     permission)) {
43        ALOGE("failed to remove interface %s from default netId %u", interface.c_str(), netId);
44        return ret;
45    }
46    if (int ret = delegate->removeFallthrough(interface, permission)) {
47        return ret;
48    }
49    return 0;
50}
51
52}  // namespace
53
54PhysicalNetwork::Delegate::~Delegate() {
55}
56
57PhysicalNetwork::PhysicalNetwork(unsigned netId, PhysicalNetwork::Delegate* delegate) :
58        Network(netId), mDelegate(delegate), mPermission(PERMISSION_NONE), mIsDefault(false) {
59}
60
61PhysicalNetwork::~PhysicalNetwork() {
62}
63
64Permission PhysicalNetwork::getPermission() const {
65    return mPermission;
66}
67
68int PhysicalNetwork::setPermission(Permission permission) {
69    if (permission == mPermission) {
70        return 0;
71    }
72    for (const std::string& interface : mInterfaces) {
73        if (int ret = RouteController::modifyPhysicalNetworkPermission(mNetId, interface.c_str(),
74                                                                       mPermission, permission)) {
75            ALOGE("failed to change permission on interface %s of netId %u from %x to %x",
76                  interface.c_str(), mNetId, mPermission, permission);
77            return ret;
78        }
79    }
80    if (mIsDefault) {
81        for (const std::string& interface : mInterfaces) {
82            if (int ret = addToDefault(mNetId, interface, permission, mDelegate)) {
83                return ret;
84            }
85            if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
86                return ret;
87            }
88        }
89    }
90    mPermission = permission;
91    return 0;
92}
93
94int PhysicalNetwork::addAsDefault() {
95    if (mIsDefault) {
96        return 0;
97    }
98    for (const std::string& interface : mInterfaces) {
99        if (int ret = addToDefault(mNetId, interface, mPermission, mDelegate)) {
100            return ret;
101        }
102    }
103    mIsDefault = true;
104    return 0;
105}
106
107int PhysicalNetwork::removeAsDefault() {
108    if (!mIsDefault) {
109        return 0;
110    }
111    for (const std::string& interface : mInterfaces) {
112        if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
113            return ret;
114        }
115    }
116    mIsDefault = false;
117    return 0;
118}
119
120Network::Type PhysicalNetwork::getType() const {
121    return PHYSICAL;
122}
123
124int PhysicalNetwork::addInterface(const std::string& interface) {
125    if (hasInterface(interface)) {
126        return 0;
127    }
128    if (int ret = RouteController::addInterfaceToPhysicalNetwork(mNetId, interface.c_str(),
129                                                                 mPermission)) {
130        ALOGE("failed to add interface %s to netId %u", interface.c_str(), mNetId);
131        return ret;
132    }
133    if (mIsDefault) {
134        if (int ret = addToDefault(mNetId, interface, mPermission, mDelegate)) {
135            return ret;
136        }
137    }
138    mInterfaces.insert(interface);
139    return 0;
140}
141
142int PhysicalNetwork::removeInterface(const std::string& interface) {
143    if (!hasInterface(interface)) {
144        return 0;
145    }
146    if (mIsDefault) {
147        if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
148            return ret;
149        }
150    }
151    // This step will flush the interface index from the cache in RouteController so it must be
152    // done last as further requests to the RouteController regarding this interface will fail
153    // to find the interface index in the cache in cases where the interface is already gone
154    // (e.g. bt-pan).
155    if (int ret = RouteController::removeInterfaceFromPhysicalNetwork(mNetId, interface.c_str(),
156                                                                      mPermission)) {
157        ALOGE("failed to remove interface %s from netId %u", interface.c_str(), mNetId);
158        return ret;
159    }
160    mInterfaces.erase(interface);
161    return 0;
162}
163