blob: 5638678688580c10cf9d504283d977cdd5badc78 [file] [log] [blame]
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -05001/*
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
Sreeram Ramachandran72604072014-05-21 13:19:43 -070017// 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.
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050032
33#include "NetworkController.h"
34
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070035#include "PhysicalNetwork.h"
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070036#include "RouteController.h"
Sreeram Ramachandran4043f012014-06-23 12:41:37 -070037#include "VirtualNetwork.h"
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070038
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -070039#include "cutils/misc.h"
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070040#define LOG_TAG "Netd"
41#include "log/log.h"
Sreeram Ramachandran72604072014-05-21 13:19:43 -070042#include "resolv_netid.h"
43
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070044namespace {
45
46// Keep these in sync with ConnectivityService.java.
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070047const unsigned MIN_NET_ID = 10;
48const unsigned MAX_NET_ID = 65535;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070049
50} // namespace
51
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070052NetworkController::NetworkController() : mDefaultNetId(NETID_UNSET) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050053}
54
55unsigned NetworkController::getDefaultNetwork() const {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070056 android::RWLock::AutoRLock lock(mRWLock);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050057 return mDefaultNetId;
58}
59
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070060int NetworkController::setDefaultNetwork(unsigned netId) {
61 android::RWLock::AutoWLock lock(mRWLock);
62
63 if (netId == mDefaultNetId) {
64 return 0;
Sreeram Ramachandran72604072014-05-21 13:19:43 -070065 }
66
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070067 if (netId != NETID_UNSET) {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -070068 Network* network = getNetworkLocked(netId);
69 if (!network || network->getType() != Network::PHYSICAL) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070070 ALOGE("invalid netId %u", netId);
71 return -EINVAL;
72 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -070073 if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070074 return ret;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070075 }
76 }
77
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070078 if (mDefaultNetId != NETID_UNSET) {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -070079 Network* network = getNetworkLocked(mDefaultNetId);
80 if (!network || network->getType() != Network::PHYSICAL) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070081 ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
82 return -ESRCH;
83 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -070084 if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070085 return ret;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070086 }
87 }
88
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070089 mDefaultNetId = netId;
90 return 0;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050091}
92
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070093bool NetworkController::setNetworkForUidRange(uid_t uidStart, uid_t uidEnd, unsigned netId,
94 bool forwardDns) {
95 if (uidStart > uidEnd || !isValidNetwork(netId)) {
Lorenzo Colittice8f5832014-05-29 12:20:55 +090096 errno = EINVAL;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050097 return false;
Lorenzo Colittice8f5832014-05-29 12:20:55 +090098 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050099
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700100 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700101 for (UidEntry& entry : mUidMap) {
102 if (entry.uidStart == uidStart && entry.uidEnd == uidEnd && entry.netId == netId) {
103 entry.forwardDns = forwardDns;
104 return true;
105 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500106 }
107
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700108 mUidMap.push_front(UidEntry(uidStart, uidEnd, netId, forwardDns));
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500109 return true;
110}
111
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700112bool NetworkController::clearNetworkForUidRange(uid_t uidStart, uid_t uidEnd, unsigned netId) {
113 if (uidStart > uidEnd || !isValidNetwork(netId)) {
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900114 errno = EINVAL;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400115 return false;
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900116 }
Paul Jensen5b49ab92014-04-03 19:06:00 -0400117
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700118 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700119 for (auto iter = mUidMap.begin(); iter != mUidMap.end(); ++iter) {
120 if (iter->uidStart == uidStart && iter->uidEnd == uidEnd && iter->netId == netId) {
121 mUidMap.erase(iter);
122 return true;
123 }
Paul Jensen5b49ab92014-04-03 19:06:00 -0400124 }
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900125
126 errno = ENOENT;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400127 return false;
128}
129
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700130unsigned NetworkController::getNetwork(uid_t uid, unsigned requestedNetId, bool forDns) const {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500131 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700132 for (const UidEntry& entry : mUidMap) {
133 if (entry.uidStart <= uid && uid <= entry.uidEnd) {
134 if (forDns && !entry.forwardDns) {
135 break;
136 }
137 return entry.netId;
138 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500139 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700140 return getNetworkLocked(requestedNetId) ? requestedNetId : mDefaultNetId;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500141}
142
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700143unsigned NetworkController::getNetworkId(const char* interface) const {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700144 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700145 for (const auto& entry : mNetworks) {
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700146 if (entry.second->hasInterface(interface)) {
147 return entry.first;
148 }
149 }
Paul Jensen35c77e32014-04-10 14:57:54 -0400150 return NETID_UNSET;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500151}
152
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700153bool NetworkController::isValidNetwork(unsigned netId) const {
154 android::RWLock::AutoRLock lock(mRWLock);
155 return getNetworkLocked(netId);
156}
157
158int NetworkController::createNetwork(unsigned netId, Permission permission) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700159 if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
Paul Jensenae37e8a2014-04-28 10:35:51 -0400160 ALOGE("invalid netId %u", netId);
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900161 return -EINVAL;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700162 }
163
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700164 if (isValidNetwork(netId)) {
165 ALOGE("duplicate netId %u", netId);
166 return -EEXIST;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700167 }
168
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700169 PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId);
170 if (int ret = physicalNetwork->setPermission(permission)) {
171 ALOGE("inconceivable! setPermission cannot fail on an empty network");
172 delete physicalNetwork;
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900173 return ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700174 }
175
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700176 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700177 mNetworks[netId] = physicalNetwork;
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900178 return 0;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700179}
180
Sreeram Ramachandran89dad012014-07-02 10:09:49 -0700181int NetworkController::createVpn(unsigned netId) {
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700182 if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
183 ALOGE("invalid netId %u", netId);
184 return -EINVAL;
185 }
186
187 if (isValidNetwork(netId)) {
188 ALOGE("duplicate netId %u", netId);
189 return -EEXIST;
190 }
191
192 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran89dad012014-07-02 10:09:49 -0700193 mNetworks[netId] = new VirtualNetwork(netId);
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700194 return 0;
195}
196
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700197int NetworkController::destroyNetwork(unsigned netId) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700198 if (!isValidNetwork(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700199 ALOGE("invalid netId %u", netId);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700200 return -EINVAL;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700201 }
202
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700203 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700204
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700205 android::RWLock::AutoWLock lock(mRWLock);
206 Network* network = getNetworkLocked(netId);
207 if (int ret = network->clearInterfaces()) {
208 return ret;
209 }
210 if (mDefaultNetId == netId) {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700211 if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700212 ALOGE("inconceivable! removeAsDefault cannot fail on an empty network");
213 return ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700214 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700215 mDefaultNetId = NETID_UNSET;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700216 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700217 mNetworks.erase(netId);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700218 delete network;
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700219 _resolv_delete_cache_for_net(netId);
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900220 return 0;
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700221}
222
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700223int NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700224 if (!isValidNetwork(netId)) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700225 ALOGE("invalid netId %u", netId);
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900226 return -EINVAL;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700227 }
228
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700229 unsigned existingNetId = getNetworkId(interface);
230 if (existingNetId != NETID_UNSET && existingNetId != netId) {
231 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
232 return -EBUSY;
233 }
234
235 android::RWLock::AutoWLock lock(mRWLock);
236 return getNetworkLocked(netId)->addInterface(interface);
237}
238
239int NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
240 if (!isValidNetwork(netId)) {
241 ALOGE("invalid netId %u", netId);
242 return -EINVAL;
243 }
244
245 android::RWLock::AutoWLock lock(mRWLock);
246 return getNetworkLocked(netId)->removeInterface(interface);
247}
248
249Permission NetworkController::getPermissionForUser(uid_t uid) const {
250 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700251 return getPermissionForUserLocked(uid);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700252}
253
254void NetworkController::setPermissionForUsers(Permission permission,
255 const std::vector<uid_t>& uids) {
256 android::RWLock::AutoWLock lock(mRWLock);
257 for (uid_t uid : uids) {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700258 mUsers[uid] = permission;
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700259 }
260}
261
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700262// TODO: Handle VPNs.
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700263bool NetworkController::isUserPermittedOnNetwork(uid_t uid, unsigned netId) const {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700264 if (uid == INVALID_UID || netId == NETID_UNSET) {
265 return false;
266 }
267
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700268 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700269 Network* network = getNetworkLocked(netId);
270 if (!network || network->getType() != Network::PHYSICAL) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700271 return false;
272 }
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700273 Permission userPermission = getPermissionForUserLocked(uid);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700274 Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission();
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700275 return (userPermission & networkPermission) == networkPermission;
276}
277
278int NetworkController::setPermissionForNetworks(Permission permission,
279 const std::vector<unsigned>& netIds) {
280 android::RWLock::AutoWLock lock(mRWLock);
281 for (unsigned netId : netIds) {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700282 Network* network = getNetworkLocked(netId);
283 if (!network || network->getType() != Network::PHYSICAL) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700284 ALOGE("invalid netId %u", netId);
285 return -EINVAL;
286 }
287
288 // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission.
289
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700290 if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700291 return ret;
292 }
293 }
294 return 0;
295}
296
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700297int NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) {
298 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700299 Network* network = getNetworkLocked(netId);
300 if (!network || network->getType() != Network::VIRTUAL) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700301 ALOGE("invalid netId %u", netId);
302 return -EINVAL;
303 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700304 if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700305 return ret;
306 }
307 return 0;
308}
309
310int NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) {
311 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700312 Network* network = getNetworkLocked(netId);
313 if (!network || network->getType() != Network::VIRTUAL) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700314 ALOGE("invalid netId %u", netId);
315 return -EINVAL;
316 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700317 if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700318 return ret;
319 }
320 return 0;
321}
322
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700323int NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
324 const char* nexthop, bool legacy, uid_t uid) {
325 return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
326}
327
328int NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
329 const char* nexthop, bool legacy, uid_t uid) {
330 return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
331}
332
Sreeram Ramachandran89dad012014-07-02 10:09:49 -0700333void NetworkController::allowProtect(const std::vector<uid_t>& uids) {
334 android::RWLock::AutoWLock lock(mRWLock);
335 mProtectableUsers.insert(uids.begin(), uids.end());
336}
337
338void NetworkController::denyProtect(const std::vector<uid_t>& uids) {
339 android::RWLock::AutoWLock lock(mRWLock);
340 for (uid_t uid : uids) {
341 mProtectableUsers.erase(uid);
342 }
343}
344
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700345Network* NetworkController::getNetworkLocked(unsigned netId) const {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700346 auto iter = mNetworks.find(netId);
347 return iter == mNetworks.end() ? NULL : iter->second;
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700348}
349
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700350Permission NetworkController::getPermissionForUserLocked(uid_t uid) const {
351 auto iter = mUsers.find(uid);
352 if (iter != mUsers.end()) {
353 return iter->second;
354 }
355 return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE;
356}
357
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700358int NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
359 const char* nexthop, bool add, bool legacy, uid_t uid) {
360 unsigned existingNetId = getNetworkId(interface);
361 if (netId == NETID_UNSET || existingNetId != netId) {
362 ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900363 return -ENOENT;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700364 }
365
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700366 RouteController::TableType tableType;
367 if (legacy) {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700368 if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700369 tableType = RouteController::PRIVILEGED_LEGACY;
370 } else {
371 tableType = RouteController::LEGACY;
372 }
373 } else {
374 tableType = RouteController::INTERFACE;
375 }
376
Sreeram Ramachandraneb27b7e2014-07-01 14:30:30 -0700377 return add ? RouteController::addRoute(interface, destination, nexthop, tableType) :
378 RouteController::removeRoute(interface, destination, nexthop, tableType);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700379}
380
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700381NetworkController::UidEntry::UidEntry(uid_t uidStart, uid_t uidEnd, unsigned netId,
382 bool forwardDns) :
383 uidStart(uidStart), uidEnd(uidEnd), netId(netId), forwardDns(forwardDns) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500384}