xref: /aosp_15_r20/system/netd/server/PhysicalNetwork.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker  *
4*8542734aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker  *
8*8542734aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker  *
10*8542734aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker  * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker  */
16*8542734aSAndroid Build Coastguard Worker 
17*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "Netd"
18*8542734aSAndroid Build Coastguard Worker 
19*8542734aSAndroid Build Coastguard Worker #include "PhysicalNetwork.h"
20*8542734aSAndroid Build Coastguard Worker 
21*8542734aSAndroid Build Coastguard Worker #include "RouteController.h"
22*8542734aSAndroid Build Coastguard Worker #include "SockDiag.h"
23*8542734aSAndroid Build Coastguard Worker 
24*8542734aSAndroid Build Coastguard Worker #include "log/log.h"
25*8542734aSAndroid Build Coastguard Worker 
26*8542734aSAndroid Build Coastguard Worker namespace android::net {
27*8542734aSAndroid Build Coastguard Worker 
28*8542734aSAndroid Build Coastguard Worker namespace {
29*8542734aSAndroid Build Coastguard Worker 
addToDefault(unsigned netId,const std::string & interface,Permission permission,PhysicalNetwork::Delegate * delegate)30*8542734aSAndroid Build Coastguard Worker [[nodiscard]] int addToDefault(unsigned netId, const std::string& interface, Permission permission,
31*8542734aSAndroid Build Coastguard Worker                                PhysicalNetwork::Delegate* delegate) {
32*8542734aSAndroid Build Coastguard Worker     if (int ret = RouteController::addInterfaceToDefaultNetwork(interface.c_str(), permission)) {
33*8542734aSAndroid Build Coastguard Worker         ALOGE("failed to add interface %s to default netId %u", interface.c_str(), netId);
34*8542734aSAndroid Build Coastguard Worker         return ret;
35*8542734aSAndroid Build Coastguard Worker     }
36*8542734aSAndroid Build Coastguard Worker     if (int ret = delegate->addFallthrough(interface, permission)) {
37*8542734aSAndroid Build Coastguard Worker         return ret;
38*8542734aSAndroid Build Coastguard Worker     }
39*8542734aSAndroid Build Coastguard Worker     return 0;
40*8542734aSAndroid Build Coastguard Worker }
41*8542734aSAndroid Build Coastguard Worker 
removeFromDefault(unsigned netId,const std::string & interface,Permission permission,PhysicalNetwork::Delegate * delegate)42*8542734aSAndroid Build Coastguard Worker [[nodiscard]] int removeFromDefault(unsigned netId, const std::string& interface,
43*8542734aSAndroid Build Coastguard Worker                                     Permission permission, PhysicalNetwork::Delegate* delegate) {
44*8542734aSAndroid Build Coastguard Worker     if (int ret = RouteController::removeInterfaceFromDefaultNetwork(interface.c_str(),
45*8542734aSAndroid Build Coastguard Worker                                                                      permission)) {
46*8542734aSAndroid Build Coastguard Worker         ALOGE("failed to remove interface %s from default netId %u", interface.c_str(), netId);
47*8542734aSAndroid Build Coastguard Worker         return ret;
48*8542734aSAndroid Build Coastguard Worker     }
49*8542734aSAndroid Build Coastguard Worker     if (int ret = delegate->removeFallthrough(interface, permission)) {
50*8542734aSAndroid Build Coastguard Worker         return ret;
51*8542734aSAndroid Build Coastguard Worker     }
52*8542734aSAndroid Build Coastguard Worker     return 0;
53*8542734aSAndroid Build Coastguard Worker }
54*8542734aSAndroid Build Coastguard Worker 
55*8542734aSAndroid Build Coastguard Worker }  // namespace
56*8542734aSAndroid Build Coastguard Worker 
~Delegate()57*8542734aSAndroid Build Coastguard Worker PhysicalNetwork::Delegate::~Delegate() {}
58*8542734aSAndroid Build Coastguard Worker 
PhysicalNetwork(unsigned netId,PhysicalNetwork::Delegate * delegate,bool local)59*8542734aSAndroid Build Coastguard Worker PhysicalNetwork::PhysicalNetwork(unsigned netId, PhysicalNetwork::Delegate* delegate, bool local)
60*8542734aSAndroid Build Coastguard Worker     : Network(netId),
61*8542734aSAndroid Build Coastguard Worker       mDelegate(delegate),
62*8542734aSAndroid Build Coastguard Worker       mPermission(PERMISSION_NONE),
63*8542734aSAndroid Build Coastguard Worker       mIsDefault(false),
64*8542734aSAndroid Build Coastguard Worker       mIsLocalNetwork(local) {}
65*8542734aSAndroid Build Coastguard Worker 
~PhysicalNetwork()66*8542734aSAndroid Build Coastguard Worker PhysicalNetwork::~PhysicalNetwork() {}
67*8542734aSAndroid Build Coastguard Worker 
getPermission() const68*8542734aSAndroid Build Coastguard Worker Permission PhysicalNetwork::getPermission() const {
69*8542734aSAndroid Build Coastguard Worker     return mPermission;
70*8542734aSAndroid Build Coastguard Worker }
71*8542734aSAndroid Build Coastguard Worker 
destroySocketsLackingPermission(Permission permission)72*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::destroySocketsLackingPermission(Permission permission) {
73*8542734aSAndroid Build Coastguard Worker     if (permission == PERMISSION_NONE) return 0;
74*8542734aSAndroid Build Coastguard Worker 
75*8542734aSAndroid Build Coastguard Worker     SockDiag sd;
76*8542734aSAndroid Build Coastguard Worker     if (!sd.open()) {
77*8542734aSAndroid Build Coastguard Worker        ALOGE("Error closing sockets for netId %d permission change", mNetId);
78*8542734aSAndroid Build Coastguard Worker        return -EBADFD;
79*8542734aSAndroid Build Coastguard Worker     }
80*8542734aSAndroid Build Coastguard Worker     if (int ret = sd.destroySocketsLackingPermission(mNetId, permission,
81*8542734aSAndroid Build Coastguard Worker                                                      true /* excludeLoopback */)) {
82*8542734aSAndroid Build Coastguard Worker         ALOGE("Failed to close sockets changing netId %d to permission %d: %s",
83*8542734aSAndroid Build Coastguard Worker               mNetId, permission, strerror(-ret));
84*8542734aSAndroid Build Coastguard Worker         return ret;
85*8542734aSAndroid Build Coastguard Worker     }
86*8542734aSAndroid Build Coastguard Worker     return 0;
87*8542734aSAndroid Build Coastguard Worker }
88*8542734aSAndroid Build Coastguard Worker 
invalidateRouteCache(const std::string & interface)89*8542734aSAndroid Build Coastguard Worker void PhysicalNetwork::invalidateRouteCache(const std::string& interface) {
90*8542734aSAndroid Build Coastguard Worker     // This method invalidates all socket destination cache entries in the kernel by creating and
91*8542734aSAndroid Build Coastguard Worker     // removing a low-priority route.
92*8542734aSAndroid Build Coastguard Worker     // This number is an arbitrary number that need to be higher than any other route created either
93*8542734aSAndroid Build Coastguard Worker     // by netd or by an IPv6 RouterAdvertisement.
94*8542734aSAndroid Build Coastguard Worker     int priority = 100000;
95*8542734aSAndroid Build Coastguard Worker 
96*8542734aSAndroid Build Coastguard Worker     for (const auto& dst : { "0.0.0.0/0", "::/0" }) {
97*8542734aSAndroid Build Coastguard Worker         // If any of these operations fail, there's no point in logging because RouteController will
98*8542734aSAndroid Build Coastguard Worker         // have already logged a message. There's also no point returning an error since there's
99*8542734aSAndroid Build Coastguard Worker         // nothing we can do.
100*8542734aSAndroid Build Coastguard Worker         (void)RouteController::addRoute(interface.c_str(), dst, "throw", RouteController::INTERFACE,
101*8542734aSAndroid Build Coastguard Worker                                         0 /* mtu */, priority);
102*8542734aSAndroid Build Coastguard Worker         (void)RouteController::removeRoute(interface.c_str(), dst, "throw",
103*8542734aSAndroid Build Coastguard Worker                                            RouteController::INTERFACE, priority);
104*8542734aSAndroid Build Coastguard Worker     }
105*8542734aSAndroid Build Coastguard Worker }
106*8542734aSAndroid Build Coastguard Worker 
setPermission(Permission permission)107*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::setPermission(Permission permission) {
108*8542734aSAndroid Build Coastguard Worker     if (permission == mPermission) {
109*8542734aSAndroid Build Coastguard Worker         return 0;
110*8542734aSAndroid Build Coastguard Worker     }
111*8542734aSAndroid Build Coastguard Worker     if (mInterfaces.empty()) {
112*8542734aSAndroid Build Coastguard Worker         mPermission = permission;
113*8542734aSAndroid Build Coastguard Worker         return 0;
114*8542734aSAndroid Build Coastguard Worker     }
115*8542734aSAndroid Build Coastguard Worker 
116*8542734aSAndroid Build Coastguard Worker     destroySocketsLackingPermission(permission);
117*8542734aSAndroid Build Coastguard Worker     for (const std::string& interface : mInterfaces) {
118*8542734aSAndroid Build Coastguard Worker         if (int ret = RouteController::modifyPhysicalNetworkPermission(
119*8542734aSAndroid Build Coastguard Worker                     mNetId, interface.c_str(), mPermission, permission, mIsLocalNetwork)) {
120*8542734aSAndroid Build Coastguard Worker             ALOGE("failed to change permission on interface %s of netId %u from %x to %x",
121*8542734aSAndroid Build Coastguard Worker                   interface.c_str(), mNetId, mPermission, permission);
122*8542734aSAndroid Build Coastguard Worker             return ret;
123*8542734aSAndroid Build Coastguard Worker         }
124*8542734aSAndroid Build Coastguard Worker         invalidateRouteCache(interface);
125*8542734aSAndroid Build Coastguard Worker     }
126*8542734aSAndroid Build Coastguard Worker     if (mIsDefault) {
127*8542734aSAndroid Build Coastguard Worker         for (const std::string& interface : mInterfaces) {
128*8542734aSAndroid Build Coastguard Worker             if (int ret = addToDefault(mNetId, interface, permission, mDelegate)) {
129*8542734aSAndroid Build Coastguard Worker                 return ret;
130*8542734aSAndroid Build Coastguard Worker             }
131*8542734aSAndroid Build Coastguard Worker             if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
132*8542734aSAndroid Build Coastguard Worker                 return ret;
133*8542734aSAndroid Build Coastguard Worker             }
134*8542734aSAndroid Build Coastguard Worker         }
135*8542734aSAndroid Build Coastguard Worker     }
136*8542734aSAndroid Build Coastguard Worker     // Destroy sockets again in case any were opened after we called destroySocketsLackingPermission
137*8542734aSAndroid Build Coastguard Worker     // above and before we changed the permissions. These sockets won't be able to send any RST
138*8542734aSAndroid Build Coastguard Worker     // packets because they are now no longer routed, but at least the apps will get errors.
139*8542734aSAndroid Build Coastguard Worker     destroySocketsLackingPermission(permission);
140*8542734aSAndroid Build Coastguard Worker     mPermission = permission;
141*8542734aSAndroid Build Coastguard Worker     return 0;
142*8542734aSAndroid Build Coastguard Worker }
143*8542734aSAndroid Build Coastguard Worker 
addAsDefault()144*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::addAsDefault() {
145*8542734aSAndroid Build Coastguard Worker     if (mIsDefault) {
146*8542734aSAndroid Build Coastguard Worker         return 0;
147*8542734aSAndroid Build Coastguard Worker     }
148*8542734aSAndroid Build Coastguard Worker     for (const std::string& interface : mInterfaces) {
149*8542734aSAndroid Build Coastguard Worker         if (int ret = addToDefault(mNetId, interface, mPermission, mDelegate)) {
150*8542734aSAndroid Build Coastguard Worker             return ret;
151*8542734aSAndroid Build Coastguard Worker         }
152*8542734aSAndroid Build Coastguard Worker     }
153*8542734aSAndroid Build Coastguard Worker     mIsDefault = true;
154*8542734aSAndroid Build Coastguard Worker     return 0;
155*8542734aSAndroid Build Coastguard Worker }
156*8542734aSAndroid Build Coastguard Worker 
removeAsDefault()157*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::removeAsDefault() {
158*8542734aSAndroid Build Coastguard Worker     if (!mIsDefault) {
159*8542734aSAndroid Build Coastguard Worker         return 0;
160*8542734aSAndroid Build Coastguard Worker     }
161*8542734aSAndroid Build Coastguard Worker     for (const std::string& interface : mInterfaces) {
162*8542734aSAndroid Build Coastguard Worker         if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
163*8542734aSAndroid Build Coastguard Worker             return ret;
164*8542734aSAndroid Build Coastguard Worker         }
165*8542734aSAndroid Build Coastguard Worker     }
166*8542734aSAndroid Build Coastguard Worker     mIsDefault = false;
167*8542734aSAndroid Build Coastguard Worker     return 0;
168*8542734aSAndroid Build Coastguard Worker }
169*8542734aSAndroid Build Coastguard Worker 
addUsers(const UidRanges & uidRanges,int32_t subPriority)170*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::addUsers(const UidRanges& uidRanges, int32_t subPriority) {
171*8542734aSAndroid Build Coastguard Worker     if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges)) {
172*8542734aSAndroid Build Coastguard Worker         return -EINVAL;
173*8542734aSAndroid Build Coastguard Worker     }
174*8542734aSAndroid Build Coastguard Worker 
175*8542734aSAndroid Build Coastguard Worker     for (const std::string& interface : mInterfaces) {
176*8542734aSAndroid Build Coastguard Worker         int ret = RouteController::addUsersToPhysicalNetwork(
177*8542734aSAndroid Build Coastguard Worker                 mNetId, interface.c_str(), {{subPriority, uidRanges}}, mIsLocalNetwork);
178*8542734aSAndroid Build Coastguard Worker         if (ret) {
179*8542734aSAndroid Build Coastguard Worker             ALOGE("failed to add users on interface %s of netId %u", interface.c_str(), mNetId);
180*8542734aSAndroid Build Coastguard Worker             return ret;
181*8542734aSAndroid Build Coastguard Worker         }
182*8542734aSAndroid Build Coastguard Worker     }
183*8542734aSAndroid Build Coastguard Worker     addToUidRangeMap(uidRanges, subPriority);
184*8542734aSAndroid Build Coastguard Worker     return 0;
185*8542734aSAndroid Build Coastguard Worker }
186*8542734aSAndroid Build Coastguard Worker 
removeUsers(const UidRanges & uidRanges,int32_t subPriority)187*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::removeUsers(const UidRanges& uidRanges, int32_t subPriority) {
188*8542734aSAndroid Build Coastguard Worker     if (!isValidSubPriority(subPriority)) return -EINVAL;
189*8542734aSAndroid Build Coastguard Worker 
190*8542734aSAndroid Build Coastguard Worker     for (const std::string& interface : mInterfaces) {
191*8542734aSAndroid Build Coastguard Worker         int ret = RouteController::removeUsersFromPhysicalNetwork(
192*8542734aSAndroid Build Coastguard Worker                 mNetId, interface.c_str(), {{subPriority, uidRanges}}, mIsLocalNetwork);
193*8542734aSAndroid Build Coastguard Worker         if (ret) {
194*8542734aSAndroid Build Coastguard Worker             ALOGE("failed to remove users on interface %s of netId %u", interface.c_str(), mNetId);
195*8542734aSAndroid Build Coastguard Worker             return ret;
196*8542734aSAndroid Build Coastguard Worker         }
197*8542734aSAndroid Build Coastguard Worker     }
198*8542734aSAndroid Build Coastguard Worker     removeFromUidRangeMap(uidRanges, subPriority);
199*8542734aSAndroid Build Coastguard Worker     return 0;
200*8542734aSAndroid Build Coastguard Worker }
201*8542734aSAndroid Build Coastguard Worker 
addInterface(const std::string & interface)202*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::addInterface(const std::string& interface) {
203*8542734aSAndroid Build Coastguard Worker     if (hasInterface(interface)) {
204*8542734aSAndroid Build Coastguard Worker         return 0;
205*8542734aSAndroid Build Coastguard Worker     }
206*8542734aSAndroid Build Coastguard Worker     if (int ret = RouteController::addInterfaceToPhysicalNetwork(
207*8542734aSAndroid Build Coastguard Worker                 mNetId, interface.c_str(), mPermission, mUidRangeMap, mIsLocalNetwork)) {
208*8542734aSAndroid Build Coastguard Worker         ALOGE("failed to add interface %s to netId %u", interface.c_str(), mNetId);
209*8542734aSAndroid Build Coastguard Worker         return ret;
210*8542734aSAndroid Build Coastguard Worker     }
211*8542734aSAndroid Build Coastguard Worker     if (mIsDefault) {
212*8542734aSAndroid Build Coastguard Worker         if (int ret = addToDefault(mNetId, interface, mPermission, mDelegate)) {
213*8542734aSAndroid Build Coastguard Worker             return ret;
214*8542734aSAndroid Build Coastguard Worker         }
215*8542734aSAndroid Build Coastguard Worker     }
216*8542734aSAndroid Build Coastguard Worker     mInterfaces.insert(interface);
217*8542734aSAndroid Build Coastguard Worker     return 0;
218*8542734aSAndroid Build Coastguard Worker }
219*8542734aSAndroid Build Coastguard Worker 
removeInterface(const std::string & interface)220*8542734aSAndroid Build Coastguard Worker int PhysicalNetwork::removeInterface(const std::string& interface) {
221*8542734aSAndroid Build Coastguard Worker     if (!hasInterface(interface)) {
222*8542734aSAndroid Build Coastguard Worker         return 0;
223*8542734aSAndroid Build Coastguard Worker     }
224*8542734aSAndroid Build Coastguard Worker     if (mIsDefault) {
225*8542734aSAndroid Build Coastguard Worker         if (int ret = removeFromDefault(mNetId, interface, mPermission, mDelegate)) {
226*8542734aSAndroid Build Coastguard Worker             return ret;
227*8542734aSAndroid Build Coastguard Worker         }
228*8542734aSAndroid Build Coastguard Worker     }
229*8542734aSAndroid Build Coastguard Worker     // This step will flush the interface index from the cache in RouteController so it must be
230*8542734aSAndroid Build Coastguard Worker     // done last as further requests to the RouteController regarding this interface will fail
231*8542734aSAndroid Build Coastguard Worker     // to find the interface index in the cache in cases where the interface is already gone
232*8542734aSAndroid Build Coastguard Worker     // (e.g. bt-pan).
233*8542734aSAndroid Build Coastguard Worker     if (int ret = RouteController::removeInterfaceFromPhysicalNetwork(
234*8542734aSAndroid Build Coastguard Worker                 mNetId, interface.c_str(), mPermission, mUidRangeMap, mIsLocalNetwork)) {
235*8542734aSAndroid Build Coastguard Worker         ALOGE("failed to remove interface %s from netId %u", interface.c_str(), mNetId);
236*8542734aSAndroid Build Coastguard Worker         return ret;
237*8542734aSAndroid Build Coastguard Worker     }
238*8542734aSAndroid Build Coastguard Worker     mInterfaces.erase(interface);
239*8542734aSAndroid Build Coastguard Worker     return 0;
240*8542734aSAndroid Build Coastguard Worker }
241*8542734aSAndroid Build Coastguard Worker 
isValidSubPriority(int32_t priority)242*8542734aSAndroid Build Coastguard Worker bool PhysicalNetwork::isValidSubPriority(int32_t priority) {
243*8542734aSAndroid Build Coastguard Worker     // SUB_PRIORITY_NO_DEFAULT is a special value, see UidRanges.h.
244*8542734aSAndroid Build Coastguard Worker     return (priority >= UidRanges::SUB_PRIORITY_HIGHEST &&
245*8542734aSAndroid Build Coastguard Worker             priority <= UidRanges::SUB_PRIORITY_LOWEST) ||
246*8542734aSAndroid Build Coastguard Worker            priority == UidRanges::SUB_PRIORITY_NO_DEFAULT;
247*8542734aSAndroid Build Coastguard Worker }
248*8542734aSAndroid Build Coastguard Worker 
249*8542734aSAndroid Build Coastguard Worker }  // namespace android::net
250