blob: be28c5b48e3669b0b173ad4b8db10c7730e29777 [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"
37
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070038#define LOG_TAG "Netd"
39#include "log/log.h"
Sreeram Ramachandran72604072014-05-21 13:19:43 -070040#include "resolv_netid.h"
41
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070042namespace {
43
44// Keep these in sync with ConnectivityService.java.
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070045const unsigned MIN_NET_ID = 10;
46const unsigned MAX_NET_ID = 65535;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070047
48} // namespace
49
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070050NetworkController::NetworkController() : mDefaultNetId(NETID_UNSET) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050051}
52
53unsigned NetworkController::getDefaultNetwork() const {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070054 android::RWLock::AutoRLock lock(mRWLock);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050055 return mDefaultNetId;
56}
57
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070058int NetworkController::setDefaultNetwork(unsigned netId) {
59 android::RWLock::AutoWLock lock(mRWLock);
60
61 if (netId == mDefaultNetId) {
62 return 0;
Sreeram Ramachandran72604072014-05-21 13:19:43 -070063 }
64
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070065 if (netId != NETID_UNSET) {
66 auto iter = mPhysicalNetworks.find(netId);
67 if (iter == mPhysicalNetworks.end()) {
68 ALOGE("invalid netId %u", netId);
69 return -EINVAL;
70 }
71 if (int ret = iter->second->addAsDefault()) {
72 return ret;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070073 }
74 }
75
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070076 if (mDefaultNetId != NETID_UNSET) {
77 auto iter = mPhysicalNetworks.find(mDefaultNetId);
78 if (iter == mPhysicalNetworks.end()) {
79 ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
80 return -ESRCH;
81 }
82 if (int ret = iter->second->removeAsDefault()) {
83 return ret;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070084 }
85 }
86
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070087 mDefaultNetId = netId;
88 return 0;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050089}
90
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070091bool NetworkController::setNetworkForUidRange(uid_t uidStart, uid_t uidEnd, unsigned netId,
92 bool forwardDns) {
93 if (uidStart > uidEnd || !isValidNetwork(netId)) {
Lorenzo Colittice8f5832014-05-29 12:20:55 +090094 errno = EINVAL;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050095 return false;
Lorenzo Colittice8f5832014-05-29 12:20:55 +090096 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050097
Sreeram Ramachandran72604072014-05-21 13:19:43 -070098 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -070099 for (UidEntry& entry : mUidMap) {
100 if (entry.uidStart == uidStart && entry.uidEnd == uidEnd && entry.netId == netId) {
101 entry.forwardDns = forwardDns;
102 return true;
103 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500104 }
105
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700106 mUidMap.push_front(UidEntry(uidStart, uidEnd, netId, forwardDns));
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500107 return true;
108}
109
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700110bool NetworkController::clearNetworkForUidRange(uid_t uidStart, uid_t uidEnd, unsigned netId) {
111 if (uidStart > uidEnd || !isValidNetwork(netId)) {
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900112 errno = EINVAL;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400113 return false;
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900114 }
Paul Jensen5b49ab92014-04-03 19:06:00 -0400115
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700116 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700117 for (auto iter = mUidMap.begin(); iter != mUidMap.end(); ++iter) {
118 if (iter->uidStart == uidStart && iter->uidEnd == uidEnd && iter->netId == netId) {
119 mUidMap.erase(iter);
120 return true;
121 }
Paul Jensen5b49ab92014-04-03 19:06:00 -0400122 }
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900123
124 errno = ENOENT;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400125 return false;
126}
127
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700128unsigned NetworkController::getNetwork(uid_t uid, unsigned requestedNetId, bool forDns) const {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500129 android::RWLock::AutoRLock lock(mRWLock);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700130 for (const UidEntry& entry : mUidMap) {
131 if (entry.uidStart <= uid && uid <= entry.uidEnd) {
132 if (forDns && !entry.forwardDns) {
133 break;
134 }
135 return entry.netId;
136 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500137 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700138 return getNetworkLocked(requestedNetId) ? requestedNetId : mDefaultNetId;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500139}
140
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700141unsigned NetworkController::getNetworkId(const char* interface) const {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700142 android::RWLock::AutoRLock lock(mRWLock);
143 for (const auto& entry : mPhysicalNetworks) {
144 if (entry.second->hasInterface(interface)) {
145 return entry.first;
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700146 }
147 }
Paul Jensen35c77e32014-04-10 14:57:54 -0400148 return NETID_UNSET;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500149}
150
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700151bool NetworkController::isValidNetwork(unsigned netId) const {
152 android::RWLock::AutoRLock lock(mRWLock);
153 return getNetworkLocked(netId);
154}
155
156int NetworkController::createNetwork(unsigned netId, Permission permission) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700157 if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
Paul Jensenae37e8a2014-04-28 10:35:51 -0400158 ALOGE("invalid netId %u", netId);
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900159 return -EINVAL;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700160 }
161
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700162 if (isValidNetwork(netId)) {
163 ALOGE("duplicate netId %u", netId);
164 return -EEXIST;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700165 }
166
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700167 PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId);
168 if (int ret = physicalNetwork->setPermission(permission)) {
169 ALOGE("inconceivable! setPermission cannot fail on an empty network");
170 delete physicalNetwork;
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900171 return ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700172 }
173
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700174 android::RWLock::AutoWLock lock(mRWLock);
175 mPhysicalNetworks[netId] = physicalNetwork;
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900176 return 0;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700177}
178
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700179int NetworkController::destroyNetwork(unsigned netId) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700180 if (!isValidNetwork(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700181 ALOGE("invalid netId %u", netId);
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700182 return -EINVAL;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700183 }
184
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700185 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700186
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700187 android::RWLock::AutoWLock lock(mRWLock);
188 Network* network = getNetworkLocked(netId);
189 if (int ret = network->clearInterfaces()) {
190 return ret;
191 }
192 if (mDefaultNetId == netId) {
193 PhysicalNetwork* physicalNetwork = static_cast<PhysicalNetwork*>(network);
194 if (int ret = physicalNetwork->removeAsDefault()) {
195 ALOGE("inconceivable! removeAsDefault cannot fail on an empty network");
196 return ret;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700197 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700198 mDefaultNetId = NETID_UNSET;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700199 }
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700200 mPhysicalNetworks.erase(netId);
201 delete network;
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700202 _resolv_delete_cache_for_net(netId);
Lorenzo Colitti96f261e2014-06-23 15:09:54 +0900203 return 0;
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700204}
205
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700206int NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700207 if (!isValidNetwork(netId)) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700208 ALOGE("invalid netId %u", netId);
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900209 return -EINVAL;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700210 }
211
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700212 unsigned existingNetId = getNetworkId(interface);
213 if (existingNetId != NETID_UNSET && existingNetId != netId) {
214 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
215 return -EBUSY;
216 }
217
218 android::RWLock::AutoWLock lock(mRWLock);
219 return getNetworkLocked(netId)->addInterface(interface);
220}
221
222int NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
223 if (!isValidNetwork(netId)) {
224 ALOGE("invalid netId %u", netId);
225 return -EINVAL;
226 }
227
228 android::RWLock::AutoWLock lock(mRWLock);
229 return getNetworkLocked(netId)->removeInterface(interface);
230}
231
232Permission NetworkController::getPermissionForUser(uid_t uid) const {
233 android::RWLock::AutoRLock lock(mRWLock);
234 auto iter = mUsers.find(uid);
235 return iter != mUsers.end() ? iter->second : PERMISSION_NONE;
236}
237
238void NetworkController::setPermissionForUsers(Permission permission,
239 const std::vector<uid_t>& uids) {
240 android::RWLock::AutoWLock lock(mRWLock);
241 for (uid_t uid : uids) {
242 if (permission == PERMISSION_NONE) {
243 mUsers.erase(uid);
244 } else {
245 mUsers[uid] = permission;
246 }
247 }
248}
249
250bool NetworkController::isUserPermittedOnNetwork(uid_t uid, unsigned netId) const {
251 android::RWLock::AutoRLock lock(mRWLock);
252 auto userIter = mUsers.find(uid);
253 Permission userPermission = (userIter != mUsers.end() ? userIter->second : PERMISSION_NONE);
254 auto networkIter = mPhysicalNetworks.find(netId);
255 if (networkIter == mPhysicalNetworks.end()) {
256 return false;
257 }
258 Permission networkPermission = networkIter->second->getPermission();
259 return (userPermission & networkPermission) == networkPermission;
260}
261
262int NetworkController::setPermissionForNetworks(Permission permission,
263 const std::vector<unsigned>& netIds) {
264 android::RWLock::AutoWLock lock(mRWLock);
265 for (unsigned netId : netIds) {
266 auto iter = mPhysicalNetworks.find(netId);
267 if (iter == mPhysicalNetworks.end()) {
268 ALOGE("invalid netId %u", netId);
269 return -EINVAL;
270 }
271
272 // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission.
273
274 if (int ret = iter->second->setPermission(permission)) {
275 return ret;
276 }
277 }
278 return 0;
279}
280
281int NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
282 const char* nexthop, bool legacy, uid_t uid) {
283 return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
284}
285
286int NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
287 const char* nexthop, bool legacy, uid_t uid) {
288 return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
289}
290
291Network* NetworkController::getNetworkLocked(unsigned netId) const {
292 auto physicalNetworkIter = mPhysicalNetworks.find(netId);
293 if (physicalNetworkIter != mPhysicalNetworks.end()) {
294 return physicalNetworkIter->second;
295 }
296 return NULL;
297}
298
299int NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
300 const char* nexthop, bool add, bool legacy, uid_t uid) {
301 unsigned existingNetId = getNetworkId(interface);
302 if (netId == NETID_UNSET || existingNetId != netId) {
303 ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900304 return -ENOENT;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700305 }
306
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700307 RouteController::TableType tableType;
308 if (legacy) {
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700309 if (getPermissionForUser(uid) & PERMISSION_CONNECTIVITY_INTERNAL) {
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700310 tableType = RouteController::PRIVILEGED_LEGACY;
311 } else {
312 tableType = RouteController::LEGACY;
313 }
314 } else {
315 tableType = RouteController::INTERFACE;
316 }
317
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700318 return add ? RouteController::addRoute(interface, destination, nexthop, tableType, uid) :
319 RouteController::removeRoute(interface, destination, nexthop, tableType, uid);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700320}
321
Sreeram Ramachandranf4f6c8d2014-06-23 09:54:06 -0700322NetworkController::UidEntry::UidEntry(uid_t uidStart, uid_t uidEnd, unsigned netId,
323 bool forwardDns) :
324 uidStart(uidStart), uidEnd(uidEnd), netId(netId), forwardDns(forwardDns) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500325}