blob: bf6383e0947bdeab0f9924ab19ae3187407353bb [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 Ramachandran5c181bf2014-04-07 14:10:04 -070035#include "PermissionsController.h"
36#include "RouteController.h"
37
Sreeram Ramachandran72604072014-05-21 13:19:43 -070038#define LOG_TAG "NetworkController"
39#include "cutils/log.h"
40#include "resolv_netid.h"
41
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070042namespace {
43
44// Keep these in sync with ConnectivityService.java.
45const unsigned int MIN_NET_ID = 10;
46const unsigned int MAX_NET_ID = 65535;
47
48} // namespace
49
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070050NetworkController::NetworkController(PermissionsController* permissionsController,
51 RouteController* routeController)
Sreeram Ramachandran574e6332014-05-14 08:31:55 -070052 : mDefaultNetId(NETID_UNSET),
53 mPermissionsController(permissionsController),
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070054 mRouteController(routeController) {
55}
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050056
57void NetworkController::clearNetworkPreference() {
58 android::RWLock::AutoWLock lock(mRWLock);
59 mUidMap.clear();
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050060}
61
62unsigned NetworkController::getDefaultNetwork() const {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070063 android::RWLock::AutoRLock lock(mRWLock);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050064 return mDefaultNetId;
65}
66
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070067bool NetworkController::setDefaultNetwork(unsigned newNetId) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -070068 // newNetId must be either NETID_UNSET or a valid network. If it's NETID_UNSET, the caller is
69 // asking for there to be no default network, which is a request we support.
70 if (newNetId != NETID_UNSET && !isValidNetwork(newNetId)) {
71 ALOGE("invalid netId %u", newNetId);
72 return false;
73 }
74
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070075 unsigned oldNetId;
76 {
77 android::RWLock::AutoWLock lock(mRWLock);
78 oldNetId = mDefaultNetId;
79 mDefaultNetId = newNetId;
80 }
81
82 if (oldNetId == newNetId) {
83 return true;
84 }
85
86 bool status = true;
Sreeram Ramachandran72604072014-05-21 13:19:43 -070087 Permission permission;
88 InterfaceRange range;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070089
90 // Add default network rules for the new netId.
Sreeram Ramachandran72604072014-05-21 13:19:43 -070091 permission = mPermissionsController->getPermissionForNetwork(newNetId);
92 range = mNetIdToInterfaces.equal_range(newNetId);
93 for (InterfaceIteratorConst iter = range.first; iter != range.second; ++iter) {
94 if (!mRouteController->addToDefaultNetwork(iter->second.c_str(), permission)) {
95 ALOGE("failed to add interface %s to default netId %u", iter->second.c_str(), newNetId);
96 status = false;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070097 }
98 }
99
100 // Remove the old default network rules.
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700101 permission = mPermissionsController->getPermissionForNetwork(oldNetId);
102 range = mNetIdToInterfaces.equal_range(oldNetId);
103 for (InterfaceIteratorConst iter = range.first; iter != range.second; ++iter) {
104 if (!mRouteController->removeFromDefaultNetwork(iter->second.c_str(), permission)) {
105 ALOGE("failed to remove interface %s from default netId %u", iter->second.c_str(),
106 oldNetId);
107 status = false;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700108 }
109 }
110
111 return status;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500112}
113
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500114bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700115 bool forward_dns) {
116 if (uid_start > uid_end || !isValidNetwork(netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500117 return false;
118
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700119 android::RWLock::AutoWLock lock(mRWLock);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500120 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
Paul Jensen5b49ab92014-04-03 19:06:00 -0400121 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500122 continue;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400123 it->forward_dns = forward_dns;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500124 return true;
125 }
126
Paul Jensen5b49ab92014-04-03 19:06:00 -0400127 mUidMap.push_front(UidEntry(uid_start, uid_end, netId, forward_dns));
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500128 return true;
129}
130
Paul Jensen5b49ab92014-04-03 19:06:00 -0400131bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700132 if (uid_start > uid_end || !isValidNetwork(netId))
Paul Jensen5b49ab92014-04-03 19:06:00 -0400133 return false;
134
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700135 android::RWLock::AutoWLock lock(mRWLock);
Paul Jensen5b49ab92014-04-03 19:06:00 -0400136 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
137 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
138 continue;
139 mUidMap.erase(it);
140 return true;
141 }
142 return false;
143}
144
Paul Jensen35c77e32014-04-10 14:57:54 -0400145unsigned NetworkController::getNetwork(int uid, unsigned requested_netId, bool for_dns) const {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500146 android::RWLock::AutoRLock lock(mRWLock);
147 for (std::list<UidEntry>::const_iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
148 if (uid < it->uid_start || it->uid_end < uid)
149 continue;
150 if (for_dns && !it->forward_dns)
151 break;
152 return it->netId;
153 }
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700154 if (mValidNetworks.find(requested_netId) != mValidNetworks.end())
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500155 return requested_netId;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500156 return mDefaultNetId;
157}
158
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700159unsigned NetworkController::getNetworkId(const char* interface) const {
160 for (InterfaceIteratorConst iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end();
161 ++iter) {
162 if (iter->second == interface) {
163 return iter->first;
164 }
165 }
Paul Jensen35c77e32014-04-10 14:57:54 -0400166 return NETID_UNSET;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500167}
168
Paul Jensenae37e8a2014-04-28 10:35:51 -0400169bool NetworkController::createNetwork(unsigned netId, Permission permission) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700170 if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
Paul Jensenae37e8a2014-04-28 10:35:51 -0400171 ALOGE("invalid netId %u", netId);
172 return false;
173 }
174
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700175 {
176 android::RWLock::AutoWLock lock(mRWLock);
177 if (!mValidNetworks.insert(netId).second) {
178 ALOGE("duplicate netId %u", netId);
179 return false;
180 }
181 }
182
Paul Jensenae37e8a2014-04-28 10:35:51 -0400183 mPermissionsController->setPermissionForNetwork(permission, netId);
184 return true;
185}
186
187bool NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700188 if (!isValidNetwork(netId) || !interface) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700189 ALOGE("invalid netId %u or interface null", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700190 return false;
191 }
192
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700193 unsigned existingNetId = getNetworkId(interface);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700194 if (existingNetId != NETID_UNSET) {
195 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
196 return false;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700197 }
198
Paul Jensenae37e8a2014-04-28 10:35:51 -0400199 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
200 if (!mRouteController->addInterfaceToNetwork(netId, interface, permission)) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700201 ALOGE("failed to add interface %s to netId %u", interface, netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700202 return false;
203 }
204
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700205 mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
Paul Jensenae37e8a2014-04-28 10:35:51 -0400206
207 if (netId == getDefaultNetwork() &&
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700208 !mRouteController->addToDefaultNetwork(interface, permission)) {
209 ALOGE("failed to add interface %s to default netId %u", interface, netId);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400210 return false;
211 }
212
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700213 return true;
214}
215
Paul Jensenae37e8a2014-04-28 10:35:51 -0400216bool NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700217 if (!isValidNetwork(netId) || !interface) {
Paul Jensenae37e8a2014-04-28 10:35:51 -0400218 ALOGE("invalid netId %u or interface null", netId);
219 return false;
220 }
221
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700222 bool status = false;
223 InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400224 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
225 if (iter->second == interface) {
226 mNetIdToInterfaces.erase(iter);
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700227 status = true;
Paul Jensenae37e8a2014-04-28 10:35:51 -0400228 break;
229 }
230 }
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700231 if (!status) {
232 ALOGE("interface %s not assigned to netId %u", interface, netId);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400233 }
234
235 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
236 if (!mRouteController->removeInterfaceFromNetwork(netId, interface, permission)) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700237 ALOGE("failed to remove interface %s from netId %u", interface, netId);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400238 status = false;
239 }
240
241 if (netId == getDefaultNetwork() &&
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700242 !mRouteController->removeFromDefaultNetwork(interface, permission)) {
243 ALOGE("failed to remove interface %s from default netId %u", interface, netId);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400244 status = false;
245 }
246
Paul Jensenae37e8a2014-04-28 10:35:51 -0400247 return status;
248}
249
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700250bool NetworkController::destroyNetwork(unsigned netId) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700251 if (!isValidNetwork(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700252 ALOGE("invalid netId %u", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700253 return false;
254 }
255
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700256 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700257
258 bool status = true;
259
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700260 InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
261 for (InterfaceIteratorConst iter = range.first; iter != range.second; ) {
262 InterfaceIteratorConst toErase = iter;
Paul Jensenae37e8a2014-04-28 10:35:51 -0400263 ++iter;
264 if (!removeInterfaceFromNetwork(netId, toErase->second.c_str())) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700265 status = false;
266 }
267 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700268
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700269 if (netId == getDefaultNetwork()) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700270 setDefaultNetwork(NETID_UNSET);
271 }
272
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700273 {
274 android::RWLock::AutoWLock lock(mRWLock);
275 mValidNetworks.erase(netId);
276 }
277
Sreeram Ramachandrana79f6182014-04-24 15:55:26 -0700278 mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
Sreeram Ramachandrana79f6182014-04-24 15:55:26 -0700279
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700280 _resolv_delete_cache_for_net(netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700281 return status;
282}
283
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700284bool NetworkController::setPermissionForUser(Permission permission,
285 const std::vector<unsigned>& uid) {
286 for (size_t i = 0; i < uid.size(); ++i) {
287 mPermissionsController->setPermissionForUser(permission, uid[i]);
288 }
289 return true;
290}
291
292bool NetworkController::setPermissionForNetwork(Permission newPermission,
293 const std::vector<unsigned>& netId) {
294 bool status = true;
295
296 for (size_t i = 0; i < netId.size(); ++i) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700297 if (!isValidNetwork(netId[i])) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700298 ALOGE("invalid netId %u", netId[i]);
299 status = false;
300 continue;
301 }
302
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700303 Permission oldPermission = mPermissionsController->getPermissionForNetwork(netId[i]);
304 if (oldPermission == newPermission) {
305 continue;
306 }
307
308 // TODO: ioctl(SIOCKILLADDR, ...) to kill sockets on the network that don't have
309 // newPermission.
310
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700311 InterfaceRange range = mNetIdToInterfaces.equal_range(netId[i]);
312 for (InterfaceIteratorConst iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700313 if (!mRouteController->modifyNetworkPermission(netId[i], iter->second.c_str(),
314 oldPermission, newPermission)) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700315 ALOGE("failed to change permission on interface %s of netId %u from %x to %x",
316 iter->second.c_str(), netId[i], oldPermission, newPermission);
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700317 status = false;
318 }
319 }
320
321 mPermissionsController->setPermissionForNetwork(newPermission, netId[i]);
322 }
323
324 return status;
325}
326
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700327bool NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700328 const char* nexthop, bool legacy, unsigned uid) {
329 return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700330}
331
332bool NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700333 const char* nexthop, bool legacy, unsigned uid) {
334 return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700335}
336
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700337bool NetworkController::isValidNetwork(unsigned netId) const {
338 if (netId == NETID_UNSET) {
339 return false;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700340 }
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700341
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700342 android::RWLock::AutoRLock lock(mRWLock);
343 return mValidNetworks.find(netId) != mValidNetworks.end();
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700344}
345
346bool NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700347 const char* nexthop, bool add, bool legacy, unsigned uid) {
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700348 if (!isValidNetwork(netId)) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700349 ALOGE("invalid netId %u", netId);
350 return false;
351 }
352
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700353 if (getNetworkId(interface) != netId) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700354 ALOGE("netId %u has no such interface %s", netId, interface);
355 return false;
356 }
357
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700358 RouteController::TableType tableType;
359 if (legacy) {
360 if (mPermissionsController->getPermissionForUser(uid) & PERMISSION_CONNECTIVITY_INTERNAL) {
361 tableType = RouteController::PRIVILEGED_LEGACY;
362 } else {
363 tableType = RouteController::LEGACY;
364 }
365 } else {
366 tableType = RouteController::INTERFACE;
367 }
368
369 return add ? mRouteController->addRoute(interface, destination, nexthop, tableType, uid) :
370 mRouteController->removeRoute(interface, destination, nexthop, tableType, uid);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700371}
372
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700373NetworkController::UidEntry::UidEntry(int start, int end, unsigned netId, bool forward_dns)
374 : uid_start(start), uid_end(end), netId(netId), forward_dns(forward_dns) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500375}