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 // THREAD-SAFETY
18 // -------------
19 // The methods in this file are called from multiple threads (from CommandListener, FwmarkServer
20 // and DnsProxyListener). So, all accesses to shared state are guarded by a lock.
21 //
22 // In some cases, a single non-const method acquires and releases the lock several times, like so:
23 // if (isValidNetwork(...)) { // isValidNetwork() acquires and releases the lock.
24 // setDefaultNetwork(...); // setDefaultNetwork() also acquires and releases the lock.
25 //
26 // It might seem that this allows races where the state changes between the two statements, but in
27 // fact there are no races because:
28 // 1. This pattern only occurs in non-const methods (i.e., those that mutate state).
29 // 2. Only CommandListener calls these non-const methods. The others call only const methods.
30 // 3. CommandListener only processes one command at a time. I.e., it's serialized.
31 // Thus, no other mutation can occur in between the two statements above.
32
33 #include "NetworkController.h"
34
35 #include "Fwmark.h"
36 #include "LocalNetwork.h"
37 #include "PhysicalNetwork.h"
38 #include "RouteController.h"
39 #include "VirtualNetwork.h"
40
41 #include "cutils/misc.h"
42 #define LOG_TAG "Netd"
43 #include "log/log.h"
44 #include "resolv_netid.h"
45
46 namespace {
47
48 // Keep these in sync with ConnectivityService.java.
49 const unsigned MIN_NET_ID = 100;
50 const unsigned MAX_NET_ID = 65535;
51
52 } // namespace
53
54 const unsigned NetworkController::MIN_OEM_ID = 1;
55 const unsigned NetworkController::MAX_OEM_ID = 50;
56 // NetIds 51..98 are reserved for future use.
57 const unsigned NetworkController::LOCAL_NET_ID = 99;
58
59 // All calls to methods here are made while holding a write lock on mRWLock.
60 class NetworkController::DelegateImpl : public PhysicalNetwork::Delegate {
61 public:
62 explicit DelegateImpl(NetworkController* networkController);
63 virtual ~DelegateImpl();
64
65 int modifyFallthrough(unsigned vpnNetId, const std::string& physicalInterface,
66 Permission permission, bool add) WARN_UNUSED_RESULT;
67
68 private:
69 int addFallthrough(const std::string& physicalInterface,
70 Permission permission) override WARN_UNUSED_RESULT;
71 int removeFallthrough(const std::string& physicalInterface,
72 Permission permission) override WARN_UNUSED_RESULT;
73
74 int modifyFallthrough(const std::string& physicalInterface, Permission permission,
75 bool add) WARN_UNUSED_RESULT;
76
77 NetworkController* const mNetworkController;
78 };
79
DelegateImpl(NetworkController * networkController)80 NetworkController::DelegateImpl::DelegateImpl(NetworkController* networkController) :
81 mNetworkController(networkController) {
82 }
83
~DelegateImpl()84 NetworkController::DelegateImpl::~DelegateImpl() {
85 }
86
modifyFallthrough(unsigned vpnNetId,const std::string & physicalInterface,Permission permission,bool add)87 int NetworkController::DelegateImpl::modifyFallthrough(unsigned vpnNetId,
88 const std::string& physicalInterface,
89 Permission permission, bool add) {
90 if (add) {
91 if (int ret = RouteController::addVirtualNetworkFallthrough(vpnNetId,
92 physicalInterface.c_str(),
93 permission)) {
94 ALOGE("failed to add fallthrough to %s for VPN netId %u", physicalInterface.c_str(),
95 vpnNetId);
96 return ret;
97 }
98 } else {
99 if (int ret = RouteController::removeVirtualNetworkFallthrough(vpnNetId,
100 physicalInterface.c_str(),
101 permission)) {
102 ALOGE("failed to remove fallthrough to %s for VPN netId %u", physicalInterface.c_str(),
103 vpnNetId);
104 return ret;
105 }
106 }
107 return 0;
108 }
109
addFallthrough(const std::string & physicalInterface,Permission permission)110 int NetworkController::DelegateImpl::addFallthrough(const std::string& physicalInterface,
111 Permission permission) {
112 return modifyFallthrough(physicalInterface, permission, true);
113 }
114
removeFallthrough(const std::string & physicalInterface,Permission permission)115 int NetworkController::DelegateImpl::removeFallthrough(const std::string& physicalInterface,
116 Permission permission) {
117 return modifyFallthrough(physicalInterface, permission, false);
118 }
119
modifyFallthrough(const std::string & physicalInterface,Permission permission,bool add)120 int NetworkController::DelegateImpl::modifyFallthrough(const std::string& physicalInterface,
121 Permission permission, bool add) {
122 for (const auto& entry : mNetworkController->mNetworks) {
123 if (entry.second->getType() == Network::VIRTUAL) {
124 if (int ret = modifyFallthrough(entry.first, physicalInterface, permission, add)) {
125 return ret;
126 }
127 }
128 }
129 return 0;
130 }
131
NetworkController()132 NetworkController::NetworkController() :
133 mDelegateImpl(new NetworkController::DelegateImpl(this)), mDefaultNetId(NETID_UNSET) {
134 mNetworks[LOCAL_NET_ID] = new LocalNetwork(LOCAL_NET_ID);
135 }
136
getDefaultNetwork() const137 unsigned NetworkController::getDefaultNetwork() const {
138 android::RWLock::AutoRLock lock(mRWLock);
139 return mDefaultNetId;
140 }
141
setDefaultNetwork(unsigned netId)142 int NetworkController::setDefaultNetwork(unsigned netId) {
143 android::RWLock::AutoWLock lock(mRWLock);
144
145 if (netId == mDefaultNetId) {
146 return 0;
147 }
148
149 if (netId != NETID_UNSET) {
150 Network* network = getNetworkLocked(netId);
151 if (!network) {
152 ALOGE("no such netId %u", netId);
153 return -ENONET;
154 }
155 if (network->getType() != Network::PHYSICAL) {
156 ALOGE("cannot set default to non-physical network with netId %u", netId);
157 return -EINVAL;
158 }
159 if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) {
160 return ret;
161 }
162 }
163
164 if (mDefaultNetId != NETID_UNSET) {
165 Network* network = getNetworkLocked(mDefaultNetId);
166 if (!network || network->getType() != Network::PHYSICAL) {
167 ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
168 return -ESRCH;
169 }
170 if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
171 return ret;
172 }
173 }
174
175 mDefaultNetId = netId;
176 return 0;
177 }
178
getNetworkForDns(unsigned * netId,uid_t uid) const179 uint32_t NetworkController::getNetworkForDns(unsigned* netId, uid_t uid) const {
180 android::RWLock::AutoRLock lock(mRWLock);
181 Fwmark fwmark;
182 fwmark.protectedFromVpn = true;
183 fwmark.permission = PERMISSION_SYSTEM;
184 if (checkUserNetworkAccessLocked(uid, *netId) == 0) {
185 // If a non-zero NetId was explicitly specified, and the user has permission for that
186 // network, use that network's DNS servers. Do not fall through to the default network even
187 // if the explicitly selected network is a split tunnel VPN or a VPN without DNS servers.
188 fwmark.explicitlySelected = true;
189 } else {
190 // If the user is subject to a VPN and the VPN provides DNS servers, use those servers
191 // (possibly falling through to the default network if the VPN doesn't provide a route to
192 // them). Otherwise, use the default network's DNS servers.
193 VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
194 if (virtualNetwork && virtualNetwork->getHasDns()) {
195 *netId = virtualNetwork->getNetId();
196 } else {
197 *netId = mDefaultNetId;
198 }
199 }
200 fwmark.netId = *netId;
201 return fwmark.intValue;
202 }
203
204 // Returns the NetId that a given UID would use if no network is explicitly selected. Specifically,
205 // the VPN that applies to the UID if any; otherwise, the default network.
getNetworkForUser(uid_t uid) const206 unsigned NetworkController::getNetworkForUser(uid_t uid) const {
207 android::RWLock::AutoRLock lock(mRWLock);
208 if (VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid)) {
209 return virtualNetwork->getNetId();
210 }
211 return mDefaultNetId;
212 }
213
214 // Returns the NetId that will be set when a socket connect()s. This is the bypassable VPN that
215 // applies to the user if any; otherwise, the default network.
216 //
217 // In general, we prefer to always set the default network's NetId in connect(), so that if the VPN
218 // is a split-tunnel and disappears later, the socket continues working (since the default network's
219 // NetId is still valid). Secure VPNs will correctly grab the socket's traffic since they have a
220 // high-priority routing rule that doesn't care what NetId the socket has.
221 //
222 // But bypassable VPNs have a very low priority rule, so we need to mark the socket with the
223 // bypassable VPN's NetId if we expect it to get any traffic at all. If the bypassable VPN is a
224 // split-tunnel, that's okay, because we have fallthrough rules that will direct the fallthrough
225 // traffic to the default network. But it does mean that if the bypassable VPN goes away (and thus
226 // the fallthrough rules also go away), the socket that used to fallthrough to the default network
227 // will stop working.
getNetworkForConnect(uid_t uid) const228 unsigned NetworkController::getNetworkForConnect(uid_t uid) const {
229 android::RWLock::AutoRLock lock(mRWLock);
230 VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
231 if (virtualNetwork && !virtualNetwork->isSecure()) {
232 return virtualNetwork->getNetId();
233 }
234 return mDefaultNetId;
235 }
236
getNetworkForInterface(const char * interface) const237 unsigned NetworkController::getNetworkForInterface(const char* interface) const {
238 android::RWLock::AutoRLock lock(mRWLock);
239 for (const auto& entry : mNetworks) {
240 if (entry.second->hasInterface(interface)) {
241 return entry.first;
242 }
243 }
244 return NETID_UNSET;
245 }
246
isVirtualNetwork(unsigned netId) const247 bool NetworkController::isVirtualNetwork(unsigned netId) const {
248 android::RWLock::AutoRLock lock(mRWLock);
249 Network* network = getNetworkLocked(netId);
250 return network && network->getType() == Network::VIRTUAL;
251 }
252
createPhysicalNetwork(unsigned netId,Permission permission)253 int NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
254 if (!((MIN_NET_ID <= netId && netId <= MAX_NET_ID) ||
255 (MIN_OEM_ID <= netId && netId <= MAX_OEM_ID))) {
256 ALOGE("invalid netId %u", netId);
257 return -EINVAL;
258 }
259
260 if (isValidNetwork(netId)) {
261 ALOGE("duplicate netId %u", netId);
262 return -EEXIST;
263 }
264
265 PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId, mDelegateImpl);
266 if (int ret = physicalNetwork->setPermission(permission)) {
267 ALOGE("inconceivable! setPermission cannot fail on an empty network");
268 delete physicalNetwork;
269 return ret;
270 }
271
272 android::RWLock::AutoWLock lock(mRWLock);
273 mNetworks[netId] = physicalNetwork;
274 return 0;
275 }
276
createVirtualNetwork(unsigned netId,bool hasDns,bool secure)277 int NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) {
278 if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) {
279 ALOGE("invalid netId %u", netId);
280 return -EINVAL;
281 }
282
283 if (isValidNetwork(netId)) {
284 ALOGE("duplicate netId %u", netId);
285 return -EEXIST;
286 }
287
288 android::RWLock::AutoWLock lock(mRWLock);
289 if (int ret = modifyFallthroughLocked(netId, true)) {
290 return ret;
291 }
292 mNetworks[netId] = new VirtualNetwork(netId, hasDns, secure);
293 return 0;
294 }
295
destroyNetwork(unsigned netId)296 int NetworkController::destroyNetwork(unsigned netId) {
297 if (netId == LOCAL_NET_ID) {
298 ALOGE("cannot destroy local network");
299 return -EINVAL;
300 }
301 if (!isValidNetwork(netId)) {
302 ALOGE("no such netId %u", netId);
303 return -ENONET;
304 }
305
306 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
307
308 android::RWLock::AutoWLock lock(mRWLock);
309 Network* network = getNetworkLocked(netId);
310
311 // If we fail to destroy a network, things will get stuck badly. Therefore, unlike most of the
312 // other network code, ignore failures and attempt to clear out as much state as possible, even
313 // if we hit an error on the way. Return the first error that we see.
314 int ret = network->clearInterfaces();
315
316 if (mDefaultNetId == netId) {
317 if (int err = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
318 ALOGE("inconceivable! removeAsDefault cannot fail on an empty network");
319 if (!ret) {
320 ret = err;
321 }
322 }
323 mDefaultNetId = NETID_UNSET;
324 } else if (network->getType() == Network::VIRTUAL) {
325 if (int err = modifyFallthroughLocked(netId, false)) {
326 if (!ret) {
327 ret = err;
328 }
329 }
330 }
331 mNetworks.erase(netId);
332 delete network;
333 _resolv_delete_cache_for_net(netId);
334 return ret;
335 }
336
addInterfaceToNetwork(unsigned netId,const char * interface)337 int NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
338 if (!isValidNetwork(netId)) {
339 ALOGE("no such netId %u", netId);
340 return -ENONET;
341 }
342
343 unsigned existingNetId = getNetworkForInterface(interface);
344 if (existingNetId != NETID_UNSET && existingNetId != netId) {
345 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
346 return -EBUSY;
347 }
348
349 android::RWLock::AutoWLock lock(mRWLock);
350 return getNetworkLocked(netId)->addInterface(interface);
351 }
352
removeInterfaceFromNetwork(unsigned netId,const char * interface)353 int NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
354 if (!isValidNetwork(netId)) {
355 ALOGE("no such netId %u", netId);
356 return -ENONET;
357 }
358
359 android::RWLock::AutoWLock lock(mRWLock);
360 return getNetworkLocked(netId)->removeInterface(interface);
361 }
362
getPermissionForUser(uid_t uid) const363 Permission NetworkController::getPermissionForUser(uid_t uid) const {
364 android::RWLock::AutoRLock lock(mRWLock);
365 return getPermissionForUserLocked(uid);
366 }
367
setPermissionForUsers(Permission permission,const std::vector<uid_t> & uids)368 void NetworkController::setPermissionForUsers(Permission permission,
369 const std::vector<uid_t>& uids) {
370 android::RWLock::AutoWLock lock(mRWLock);
371 for (uid_t uid : uids) {
372 mUsers[uid] = permission;
373 }
374 }
375
checkUserNetworkAccess(uid_t uid,unsigned netId) const376 int NetworkController::checkUserNetworkAccess(uid_t uid, unsigned netId) const {
377 android::RWLock::AutoRLock lock(mRWLock);
378 return checkUserNetworkAccessLocked(uid, netId);
379 }
380
setPermissionForNetworks(Permission permission,const std::vector<unsigned> & netIds)381 int NetworkController::setPermissionForNetworks(Permission permission,
382 const std::vector<unsigned>& netIds) {
383 android::RWLock::AutoWLock lock(mRWLock);
384 for (unsigned netId : netIds) {
385 Network* network = getNetworkLocked(netId);
386 if (!network) {
387 ALOGE("no such netId %u", netId);
388 return -ENONET;
389 }
390 if (network->getType() != Network::PHYSICAL) {
391 ALOGE("cannot set permissions on non-physical network with netId %u", netId);
392 return -EINVAL;
393 }
394
395 // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission.
396
397 if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) {
398 return ret;
399 }
400 }
401 return 0;
402 }
403
addUsersToNetwork(unsigned netId,const UidRanges & uidRanges)404 int NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) {
405 android::RWLock::AutoWLock lock(mRWLock);
406 Network* network = getNetworkLocked(netId);
407 if (!network) {
408 ALOGE("no such netId %u", netId);
409 return -ENONET;
410 }
411 if (network->getType() != Network::VIRTUAL) {
412 ALOGE("cannot add users to non-virtual network with netId %u", netId);
413 return -EINVAL;
414 }
415 if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) {
416 return ret;
417 }
418 return 0;
419 }
420
removeUsersFromNetwork(unsigned netId,const UidRanges & uidRanges)421 int NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) {
422 android::RWLock::AutoWLock lock(mRWLock);
423 Network* network = getNetworkLocked(netId);
424 if (!network) {
425 ALOGE("no such netId %u", netId);
426 return -ENONET;
427 }
428 if (network->getType() != Network::VIRTUAL) {
429 ALOGE("cannot remove users from non-virtual network with netId %u", netId);
430 return -EINVAL;
431 }
432 if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) {
433 return ret;
434 }
435 return 0;
436 }
437
addRoute(unsigned netId,const char * interface,const char * destination,const char * nexthop,bool legacy,uid_t uid)438 int NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
439 const char* nexthop, bool legacy, uid_t uid) {
440 return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
441 }
442
removeRoute(unsigned netId,const char * interface,const char * destination,const char * nexthop,bool legacy,uid_t uid)443 int NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
444 const char* nexthop, bool legacy, uid_t uid) {
445 return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
446 }
447
canProtect(uid_t uid) const448 bool NetworkController::canProtect(uid_t uid) const {
449 android::RWLock::AutoRLock lock(mRWLock);
450 return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) ||
451 mProtectableUsers.find(uid) != mProtectableUsers.end();
452 }
453
allowProtect(const std::vector<uid_t> & uids)454 void NetworkController::allowProtect(const std::vector<uid_t>& uids) {
455 android::RWLock::AutoWLock lock(mRWLock);
456 mProtectableUsers.insert(uids.begin(), uids.end());
457 }
458
denyProtect(const std::vector<uid_t> & uids)459 void NetworkController::denyProtect(const std::vector<uid_t>& uids) {
460 android::RWLock::AutoWLock lock(mRWLock);
461 for (uid_t uid : uids) {
462 mProtectableUsers.erase(uid);
463 }
464 }
465
isValidNetwork(unsigned netId) const466 bool NetworkController::isValidNetwork(unsigned netId) const {
467 android::RWLock::AutoRLock lock(mRWLock);
468 return getNetworkLocked(netId);
469 }
470
getNetworkLocked(unsigned netId) const471 Network* NetworkController::getNetworkLocked(unsigned netId) const {
472 auto iter = mNetworks.find(netId);
473 return iter == mNetworks.end() ? NULL : iter->second;
474 }
475
getVirtualNetworkForUserLocked(uid_t uid) const476 VirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const {
477 for (const auto& entry : mNetworks) {
478 if (entry.second->getType() == Network::VIRTUAL) {
479 VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second);
480 if (virtualNetwork->appliesToUser(uid)) {
481 return virtualNetwork;
482 }
483 }
484 }
485 return NULL;
486 }
487
getPermissionForUserLocked(uid_t uid) const488 Permission NetworkController::getPermissionForUserLocked(uid_t uid) const {
489 auto iter = mUsers.find(uid);
490 if (iter != mUsers.end()) {
491 return iter->second;
492 }
493 return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE;
494 }
495
checkUserNetworkAccessLocked(uid_t uid,unsigned netId) const496 int NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) const {
497 Network* network = getNetworkLocked(netId);
498 if (!network) {
499 return -ENONET;
500 }
501
502 // If uid is INVALID_UID, this likely means that we were unable to retrieve the UID of the peer
503 // (using SO_PEERCRED). Be safe and deny access to the network, even if it's valid.
504 if (uid == INVALID_UID) {
505 return -EREMOTEIO;
506 }
507 Permission userPermission = getPermissionForUserLocked(uid);
508 if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
509 return 0;
510 }
511 if (network->getType() == Network::VIRTUAL) {
512 return static_cast<VirtualNetwork*>(network)->appliesToUser(uid) ? 0 : -EPERM;
513 }
514 VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
515 if (virtualNetwork && virtualNetwork->isSecure() &&
516 mProtectableUsers.find(uid) == mProtectableUsers.end()) {
517 return -EPERM;
518 }
519 Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission();
520 return ((userPermission & networkPermission) == networkPermission) ? 0 : -EACCES;
521 }
522
modifyRoute(unsigned netId,const char * interface,const char * destination,const char * nexthop,bool add,bool legacy,uid_t uid)523 int NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
524 const char* nexthop, bool add, bool legacy, uid_t uid) {
525 if (!isValidNetwork(netId)) {
526 ALOGE("no such netId %u", netId);
527 return -ENONET;
528 }
529 unsigned existingNetId = getNetworkForInterface(interface);
530 if (existingNetId == NETID_UNSET) {
531 ALOGE("interface %s not assigned to any netId", interface);
532 return -ENODEV;
533 }
534 if (existingNetId != netId) {
535 ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
536 return -ENOENT;
537 }
538
539 RouteController::TableType tableType;
540 if (netId == LOCAL_NET_ID) {
541 tableType = RouteController::LOCAL_NETWORK;
542 } else if (legacy) {
543 if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
544 tableType = RouteController::LEGACY_SYSTEM;
545 } else {
546 tableType = RouteController::LEGACY_NETWORK;
547 }
548 } else {
549 tableType = RouteController::INTERFACE;
550 }
551
552 return add ? RouteController::addRoute(interface, destination, nexthop, tableType) :
553 RouteController::removeRoute(interface, destination, nexthop, tableType);
554 }
555
modifyFallthroughLocked(unsigned vpnNetId,bool add)556 int NetworkController::modifyFallthroughLocked(unsigned vpnNetId, bool add) {
557 if (mDefaultNetId == NETID_UNSET) {
558 return 0;
559 }
560 Network* network = getNetworkLocked(mDefaultNetId);
561 if (!network) {
562 ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
563 return -ESRCH;
564 }
565 if (network->getType() != Network::PHYSICAL) {
566 ALOGE("inconceivable! default network must be a physical network");
567 return -EINVAL;
568 }
569 Permission permission = static_cast<PhysicalNetwork*>(network)->getPermission();
570 for (const auto& physicalInterface : network->getInterfaces()) {
571 if (int ret = mDelegateImpl->modifyFallthrough(vpnNetId, physicalInterface, permission,
572 add)) {
573 return ret;
574 }
575 }
576 return 0;
577 }
578