blob: 1487b7286a98a499f92fe7e44ee7ac83395e165c [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 Ramachandrane09b20a2014-07-05 17:15:14 -070093unsigned NetworkController::getNetworkForUser(uid_t uid, unsigned requestedNetId,
94 bool forDns) const {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050095 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -070096 VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
97 if (virtualNetwork && (!forDns || virtualNetwork->getHasDns())) {
98 return virtualNetwork->getNetId();
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050099 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700100 return getNetworkLocked(requestedNetId) ? requestedNetId : mDefaultNetId;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500101}
102
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700103unsigned NetworkController::getNetworkForInterface(const char* interface) const {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700104 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700105 for (const auto& entry : mNetworks) {
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700106 if (entry.second->hasInterface(interface)) {
107 return entry.first;
108 }
109 }
Paul Jensen35c77e32014-04-10 14:57:54 -0400110 return NETID_UNSET;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500111}
112
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700113int NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700114 if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
Paul Jensenae37e8a2014-04-28 10:35:51 -0400115 ALOGE("invalid netId %u", netId);
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900116 return -EINVAL;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700117 }
118
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700119 if (isValidNetwork(netId)) {
120 ALOGE("duplicate netId %u", netId);
121 return -EEXIST;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700122 }
123
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700124 PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId);
125 if (int ret = physicalNetwork->setPermission(permission)) {
126 ALOGE("inconceivable! setPermission cannot fail on an empty network");
127 delete physicalNetwork;
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900128 return ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700129 }
130
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700131 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700132 mNetworks[netId] = physicalNetwork;
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900133 return 0;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700134}
135
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700136int NetworkController::createVirtualNetwork(unsigned netId, bool hasDns) {
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700137 if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
138 ALOGE("invalid netId %u", netId);
139 return -EINVAL;
140 }
141
142 if (isValidNetwork(netId)) {
143 ALOGE("duplicate netId %u", netId);
144 return -EEXIST;
145 }
146
147 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700148 mNetworks[netId] = new VirtualNetwork(netId, hasDns);
Sreeram Ramachandran4043f012014-06-23 12:41:37 -0700149 return 0;
150}
151
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700152int NetworkController::destroyNetwork(unsigned netId) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700153 if (!isValidNetwork(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700154 ALOGE("invalid netId %u", netId);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700155 return -EINVAL;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700156 }
157
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700158 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700159
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700160 android::RWLock::AutoWLock lock(mRWLock);
161 Network* network = getNetworkLocked(netId);
162 if (int ret = network->clearInterfaces()) {
163 return ret;
164 }
165 if (mDefaultNetId == netId) {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700166 if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700167 ALOGE("inconceivable! removeAsDefault cannot fail on an empty network");
168 return ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700169 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700170 mDefaultNetId = NETID_UNSET;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700171 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700172 mNetworks.erase(netId);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700173 delete network;
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700174 _resolv_delete_cache_for_net(netId);
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900175 return 0;
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700176}
177
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700178int NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700179 if (!isValidNetwork(netId)) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700180 ALOGE("invalid netId %u", netId);
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900181 return -EINVAL;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700182 }
183
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700184 unsigned existingNetId = getNetworkForInterface(interface);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700185 if (existingNetId != NETID_UNSET && existingNetId != netId) {
186 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
187 return -EBUSY;
188 }
189
190 android::RWLock::AutoWLock lock(mRWLock);
191 return getNetworkLocked(netId)->addInterface(interface);
192}
193
194int NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
195 if (!isValidNetwork(netId)) {
196 ALOGE("invalid netId %u", netId);
197 return -EINVAL;
198 }
199
200 android::RWLock::AutoWLock lock(mRWLock);
201 return getNetworkLocked(netId)->removeInterface(interface);
202}
203
204Permission NetworkController::getPermissionForUser(uid_t uid) const {
205 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700206 return getPermissionForUserLocked(uid);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700207}
208
209void NetworkController::setPermissionForUsers(Permission permission,
210 const std::vector<uid_t>& uids) {
211 android::RWLock::AutoWLock lock(mRWLock);
212 for (uid_t uid : uids) {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700213 mUsers[uid] = permission;
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700214 }
215}
216
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700217bool NetworkController::canUserSelectNetwork(uid_t uid, unsigned netId) const {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700218 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700219 Network* network = getNetworkLocked(netId);
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700220 if (!network || uid == INVALID_UID) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700221 return false;
222 }
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700223 Permission userPermission = getPermissionForUserLocked(uid);
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700224 if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
225 return true;
226 }
227 if (network->getType() == Network::VIRTUAL) {
228 return static_cast<VirtualNetwork*>(network)->appliesToUser(uid);
229 }
230 VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
231 if (virtualNetwork && mProtectableUsers.find(uid) == mProtectableUsers.end()) {
232 return false;
233 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700234 Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission();
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700235 return (userPermission & networkPermission) == networkPermission;
236}
237
238int NetworkController::setPermissionForNetworks(Permission permission,
239 const std::vector<unsigned>& netIds) {
240 android::RWLock::AutoWLock lock(mRWLock);
241 for (unsigned netId : netIds) {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700242 Network* network = getNetworkLocked(netId);
243 if (!network || network->getType() != Network::PHYSICAL) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700244 ALOGE("invalid netId %u", netId);
245 return -EINVAL;
246 }
247
248 // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission.
249
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700250 if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700251 return ret;
252 }
253 }
254 return 0;
255}
256
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700257int NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) {
258 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700259 Network* network = getNetworkLocked(netId);
260 if (!network || network->getType() != Network::VIRTUAL) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700261 ALOGE("invalid netId %u", netId);
262 return -EINVAL;
263 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700264 if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700265 return ret;
266 }
267 return 0;
268}
269
270int NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) {
271 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700272 Network* network = getNetworkLocked(netId);
273 if (!network || network->getType() != Network::VIRTUAL) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700274 ALOGE("invalid netId %u", netId);
275 return -EINVAL;
276 }
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700277 if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) {
Sreeram Ramachandranb1425cc2014-06-23 18:54:27 -0700278 return ret;
279 }
280 return 0;
281}
282
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700283int NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
284 const char* nexthop, bool legacy, uid_t uid) {
285 return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
286}
287
288int NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
289 const char* nexthop, bool legacy, uid_t uid) {
290 return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
291}
292
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700293bool NetworkController::canProtect(uid_t uid) const {
294 android::RWLock::AutoRLock lock(mRWLock);
295 return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) ||
296 mProtectableUsers.find(uid) != mProtectableUsers.end();
297}
298
Sreeram Ramachandran89dad012014-07-02 10:09:49 -0700299void NetworkController::allowProtect(const std::vector<uid_t>& uids) {
300 android::RWLock::AutoWLock lock(mRWLock);
301 mProtectableUsers.insert(uids.begin(), uids.end());
302}
303
304void NetworkController::denyProtect(const std::vector<uid_t>& uids) {
305 android::RWLock::AutoWLock lock(mRWLock);
306 for (uid_t uid : uids) {
307 mProtectableUsers.erase(uid);
308 }
309}
310
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700311bool NetworkController::isValidNetwork(unsigned netId) const {
312 android::RWLock::AutoRLock lock(mRWLock);
313 return getNetworkLocked(netId);
314}
315
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700316Network* NetworkController::getNetworkLocked(unsigned netId) const {
Sreeram Ramachandran36ed53e2014-07-01 19:01:56 -0700317 auto iter = mNetworks.find(netId);
318 return iter == mNetworks.end() ? NULL : iter->second;
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700319}
320
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700321VirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const {
322 for (const auto& entry : mNetworks) {
323 if (entry.second->getType() == Network::VIRTUAL) {
324 VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second);
325 if (virtualNetwork->appliesToUser(uid)) {
326 return virtualNetwork;
327 }
328 }
329 }
330 return NULL;
331}
332
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700333Permission NetworkController::getPermissionForUserLocked(uid_t uid) const {
334 auto iter = mUsers.find(uid);
335 if (iter != mUsers.end()) {
336 return iter->second;
337 }
338 return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE;
339}
340
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700341int NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
342 const char* nexthop, bool add, bool legacy, uid_t uid) {
Sreeram Ramachandrane09b20a2014-07-05 17:15:14 -0700343 unsigned existingNetId = getNetworkForInterface(interface);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700344 if (netId == NETID_UNSET || existingNetId != netId) {
345 ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900346 return -ENOENT;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700347 }
348
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700349 RouteController::TableType tableType;
350 if (legacy) {
Sreeram Ramachandraned4bd1f2014-07-05 12:31:05 -0700351 if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
Sreeram Ramachandran5009d5e2014-07-03 12:20:48 -0700352 tableType = RouteController::LEGACY_SYSTEM;
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700353 } else {
Sreeram Ramachandran5009d5e2014-07-03 12:20:48 -0700354 tableType = RouteController::LEGACY_NETWORK;
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700355 }
356 } else {
357 tableType = RouteController::INTERFACE;
358 }
359
Sreeram Ramachandraneb27b7e2014-07-01 14:30:30 -0700360 return add ? RouteController::addRoute(interface, destination, nexthop, tableType) :
361 RouteController::removeRoute(interface, destination, nexthop, tableType);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700362}