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#include "SockDiag.h"
21
22#define LOG_TAG "Netd"
23#include "log/log.h"
24
25namespace android {
26namespace net {
27
28namespace {
29
30WARN_UNUSED_RESULT int addToDefault(unsigned netId, const std::string& interface,
31                                    Permission permission, PhysicalNetwork::Delegate* delegate) {
32    if (int ret = RouteController::addInterfaceToDefaultNetwork(interface.c_str(), permission)) {
33        ALOGE("failed to add interface %s to default netId %u", interface.c_str(), netId);
34        return ret;
35    }
36    if (int ret = delegate->addFallthrough(interface, permission)) {
37        return ret;
38    }
39    return 0;
40}
41
42WARN_UNUSED_RESULT int removeFromDefault(unsigned netId, const std::string& interface,
43                                         Permission permission,
44                                         PhysicalNetwork::Delegate* delegate) {
45    if (int ret = RouteController::removeInterfaceFromDefaultNetwork(interface.c_str(),
46                                                                     permission)) {
47        ALOGE("failed to remove interface %s from default netId %u", interface.c_str(), netId);
48        return ret;
49    }
50    if (int ret = delegate->removeFallthrough(interface, permission)) {
51        return ret;
52    }
53    return 0;
54}
55
56}  // namespace
57
58PhysicalNetwork::Delegate::~Delegate() {
59}
60
61PhysicalNetwork::PhysicalNetwork(unsigned netId, PhysicalNetwork::Delegate* delegate) :
62        Network(netId), mDelegate(delegate), mPermission(PERMISSION_NONE), mIsDefault(false) {
63}
64
65PhysicalNetwork::~PhysicalNetwork() {
66}
67
68Permission PhysicalNetwork::getPermission() const {
69    return mPermission;
70}
71
72int PhysicalNetwork::destroySocketsLackingPermission(Permission permission) {
73    if (permission == PERMISSION_NONE) return 0;
74
75    SockDiag sd;
76    if (!sd.open()) {
77       ALOGE("Error closing sockets for netId %d permission change", mNetId);
78       return -EBADFD;
79    }
80    if (int ret = sd.destroySocketsLackingPermission(mNetId, permission,
81                                                     true /* excludeLoopback */)) {
82        ALOGE("Failed to close sockets changing netId %d to permission %d: %s",
83              mNetId, permission, strerror(-ret));
84        return ret;
85    }
86    return 0;
87}
88
89void PhysicalNetwork::invalidateRouteCache(const std::string& interface) {
90    for (const auto& dst : { "0.0.0.0/0", "::/0" }) {
91        // If any of these operations fail, there's no point in logging because RouteController will
92        // have already logged a message. There's also no point returning an error since there's
93        // nothing we can do.
94        (void) RouteController::addRoute(interface.c_str(), dst, "throw",
95                                         RouteController::INTERFACE);
96        (void) RouteController::removeRoute(interface.c_str(), dst, "throw",
97                                         RouteController::INTERFACE);
98    }
99}
100
101int PhysicalNetwork::setPermission(Permission permission) {
102    if (permission == mPermission) {
103        return 0;
104    }
105    if (mInterfaces.empty()) {
106        mPermission = permission;
107        return 0;
108    }
109
110    destroySocketsLackingPermission(permission);
111    for (const std::string& interface : mInterfaces) {
112        if (int ret = RouteController::modifyPhysicalNetworkPermission(mNetId, interface.c_str(),
113                                                                       mPermission, permission)) {
114            ALOGE("failed to change permission on interface %s of netId %u from %x to %x",
115                  interface.c_str(), mNetId, mPermission, permission);
116            return ret;
117        }
118        invalidateRouteCache(interface);
119    }
120    if (mIsDefault) {
121        for (const std::string& interface : mInterfaces) {
122            if (int ret = addToDefault(mNetId, interface, permission, mDelegate)) {
123                return ret;
124            }
125            if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
126                return ret;
127            }
128        }
129    }
130    // Destroy sockets again in case any were opened after we called destroySocketsLackingPermission
131    // above and before we changed the permissions. These sockets won't be able to send any RST
132    // packets because they are now no longer routed, but at least the apps will get errors.
133    destroySocketsLackingPermission(permission);
134    mPermission = permission;
135    return 0;
136}
137
138int PhysicalNetwork::addAsDefault() {
139    if (mIsDefault) {
140        return 0;
141    }
142    for (const std::string& interface : mInterfaces) {
143        if (int ret = addToDefault(mNetId, interface, mPermission, mDelegate)) {
144            return ret;
145        }
146    }
147    mIsDefault = true;
148    return 0;
149}
150
151int PhysicalNetwork::removeAsDefault() {
152    if (!mIsDefault) {
153        return 0;
154    }
155    for (const std::string& interface : mInterfaces) {
156        if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
157            return ret;
158        }
159    }
160    mIsDefault = false;
161    return 0;
162}
163
164Network::Type PhysicalNetwork::getType() const {
165    return PHYSICAL;
166}
167
168int PhysicalNetwork::addInterface(const std::string& interface) {
169    if (hasInterface(interface)) {
170        return 0;
171    }
172    if (int ret = RouteController::addInterfaceToPhysicalNetwork(mNetId, interface.c_str(),
173                                                                 mPermission)) {
174        ALOGE("failed to add interface %s to netId %u", interface.c_str(), mNetId);
175        return ret;
176    }
177    if (mIsDefault) {
178        if (int ret = addToDefault(mNetId, interface, mPermission, mDelegate)) {
179            return ret;
180        }
181    }
182    mInterfaces.insert(interface);
183    return 0;
184}
185
186int PhysicalNetwork::removeInterface(const std::string& interface) {
187    if (!hasInterface(interface)) {
188        return 0;
189    }
190    if (mIsDefault) {
191        if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
192            return ret;
193        }
194    }
195    // This step will flush the interface index from the cache in RouteController so it must be
196    // done last as further requests to the RouteController regarding this interface will fail
197    // to find the interface index in the cache in cases where the interface is already gone
198    // (e.g. bt-pan).
199    if (int ret = RouteController::removeInterfaceFromPhysicalNetwork(mNetId, interface.c_str(),
200                                                                      mPermission)) {
201        ALOGE("failed to remove interface %s from netId %u", interface.c_str(), mNetId);
202        return ret;
203    }
204    mInterfaces.erase(interface);
205    return 0;
206}
207
208}  // namespace net
209}  // namespace android
210