blob: 3cf82bd13bd8e976fae2e0cd3dd74ff1c06ae9a1 [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
17#include <resolv_netid.h>
18
19#define LOG_TAG "NetworkController"
20#include <cutils/log.h>
21
22#include "NetworkController.h"
23
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070024#include "PermissionsController.h"
25#include "RouteController.h"
26
27namespace {
28
29// Keep these in sync with ConnectivityService.java.
30const unsigned int MIN_NET_ID = 10;
31const unsigned int MAX_NET_ID = 65535;
32
33} // namespace
34
35bool NetworkController::isNetIdValid(unsigned netId) {
36 return MIN_NET_ID <= netId && netId <= MAX_NET_ID;
37}
38
39NetworkController::NetworkController(PermissionsController* permissionsController,
40 RouteController* routeController)
Paul Jensen35c77e32014-04-10 14:57:54 -040041 : mPermissionsController(permissionsController),
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070042 mRouteController(routeController) {
43}
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050044
45void NetworkController::clearNetworkPreference() {
46 android::RWLock::AutoWLock lock(mRWLock);
47 mUidMap.clear();
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050048}
49
50unsigned NetworkController::getDefaultNetwork() const {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070051 android::RWLock::AutoRLock lock(mRWLock);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050052 return mDefaultNetId;
53}
54
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070055bool NetworkController::setDefaultNetwork(unsigned newNetId) {
56 unsigned oldNetId;
57 {
58 android::RWLock::AutoWLock lock(mRWLock);
59 oldNetId = mDefaultNetId;
60 mDefaultNetId = newNetId;
61 }
62
63 if (oldNetId == newNetId) {
64 return true;
65 }
66
67 bool status = true;
68
69 // Add default network rules for the new netId.
70 if (isNetIdValid(newNetId)) {
71 Permission permission = mPermissionsController->getPermissionForNetwork(newNetId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070072 InterfaceRange range = interfacesForNetId(newNetId, &status);
73 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070074 if (!mRouteController->addDefaultNetwork(iter->second.c_str(), permission)) {
75 status = false;
76 }
77 }
78 }
79
80 // Remove the old default network rules.
81 if (isNetIdValid(oldNetId)) {
82 Permission permission = mPermissionsController->getPermissionForNetwork(oldNetId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070083 InterfaceRange range = interfacesForNetId(oldNetId, &status);
84 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070085 if (!mRouteController->removeDefaultNetwork(iter->second.c_str(), permission)) {
86 status = false;
87 }
88 }
89 }
90
91 return status;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050092}
93
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050094bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
95 bool forward_dns) {
96 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070097 if (uid_start > uid_end || !isNetIdValid(netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050098 return false;
99
100 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
Paul Jensen5b49ab92014-04-03 19:06:00 -0400101 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500102 continue;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400103 it->forward_dns = forward_dns;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500104 return true;
105 }
106
Paul Jensen5b49ab92014-04-03 19:06:00 -0400107 mUidMap.push_front(UidEntry(uid_start, uid_end, netId, forward_dns));
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500108 return true;
109}
110
Paul Jensen5b49ab92014-04-03 19:06:00 -0400111bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
112 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700113 if (uid_start > uid_end || !isNetIdValid(netId))
Paul Jensen5b49ab92014-04-03 19:06:00 -0400114 return false;
115
116 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
117 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
118 continue;
119 mUidMap.erase(it);
120 return true;
121 }
122 return false;
123}
124
Paul Jensen35c77e32014-04-10 14:57:54 -0400125unsigned NetworkController::getNetwork(int uid, unsigned requested_netId, bool for_dns) const {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500126 android::RWLock::AutoRLock lock(mRWLock);
127 for (std::list<UidEntry>::const_iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
128 if (uid < it->uid_start || it->uid_end < uid)
129 continue;
130 if (for_dns && !it->forward_dns)
131 break;
132 return it->netId;
133 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700134 if (isNetIdValid(requested_netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500135 return requested_netId;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500136 return mDefaultNetId;
137}
138
139unsigned NetworkController::getNetworkId(const char* interface) {
140 std::map<std::string, unsigned>::const_iterator it = mIfaceNetidMap.find(interface);
141 if (it != mIfaceNetidMap.end())
142 return it->second;
Paul Jensen35c77e32014-04-10 14:57:54 -0400143 return NETID_UNSET;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500144}
145
Paul Jensenae37e8a2014-04-28 10:35:51 -0400146bool NetworkController::createNetwork(unsigned netId, Permission permission) {
147 if (!isNetIdValid(netId)) {
148 ALOGE("invalid netId %u", netId);
149 return false;
150 }
151
152 mPermissionsController->setPermissionForNetwork(permission, netId);
153 return true;
154}
155
156bool NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700157 if (!isNetIdValid(netId) || !interface) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700158 ALOGE("invalid netId %u or interface null", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700159 return false;
160 }
161
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700162 unsigned existingNetId = netIdForInterface(interface);
163 if (existingNetId != NETID_UNSET) {
164 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
165 return false;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700166 }
167
Paul Jensenae37e8a2014-04-28 10:35:51 -0400168 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
169 if (!mRouteController->addInterfaceToNetwork(netId, interface, permission)) {
170 ALOGE("failed to add rules for interface %s to netId %u", interface, netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700171 return false;
172 }
173
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700174 mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
Paul Jensen35c77e32014-04-10 14:57:54 -0400175 mIfaceNetidMap[interface] = netId;
Paul Jensenae37e8a2014-04-28 10:35:51 -0400176
177 if (netId == getDefaultNetwork() &&
178 !mRouteController->addDefaultNetwork(interface, permission)) {
179 ALOGE("failed to add interface %s to default network %u", interface, netId);
180 return false;
181 }
182
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700183 return true;
184}
185
Paul Jensenae37e8a2014-04-28 10:35:51 -0400186bool NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
187 if (!isNetIdValid(netId) || !interface) {
188 ALOGE("invalid netId %u or interface null", netId);
189 return false;
190 }
191
192 bool status = true;
193 bool found = false;
194 InterfaceRange range = interfacesForNetId(netId, &status);
195 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
196 if (iter->second == interface) {
197 mNetIdToInterfaces.erase(iter);
198 found = true;
199 break;
200 }
201 }
202 if (!found) {
203 ALOGE("interface %s not a member of netId %u", interface, netId);
204 status = false;
205 }
206
207 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
208 if (!mRouteController->removeInterfaceFromNetwork(netId, interface, permission)) {
209 ALOGE("failed to remove rules for interface %s from netId %u", interface, netId);
210 status = false;
211 }
212
213 if (netId == getDefaultNetwork() &&
214 !mRouteController->removeDefaultNetwork(interface, permission)) {
215 ALOGE("failed to remove interface %s from default network %u", interface, netId);
216 status = false;
217 }
218
219 mIfaceNetidMap.erase(interface);
220
221 return status;
222}
223
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700224bool NetworkController::destroyNetwork(unsigned netId) {
225 if (!isNetIdValid(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700226 ALOGE("invalid netId %u", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700227 return false;
228 }
229
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700230 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700231
232 bool status = true;
233
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700234 InterfaceRange range = interfacesForNetId(netId, &status);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400235 for (InterfaceIterator iter = range.first; iter != range.second; ) {
236 InterfaceIterator toErase = iter;
237 ++iter;
238 if (!removeInterfaceFromNetwork(netId, toErase->second.c_str())) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700239 status = false;
240 }
241 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700242
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700243 if (netId == getDefaultNetwork()) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700244 // Could the default network have changed from below us, after we evaluated the 'if', making
245 // it wrong to call setDefaultNetwork() now? No, because the default can only change due to
246 // a command from CommandListener; but commands are serialized, I.e., we are processing the
247 // destroyNetwork() command here, so a setDefaultNetwork() command can't happen in parallel.
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700248 setDefaultNetwork(NETID_UNSET);
249 }
250
Sreeram Ramachandrana79f6182014-04-24 15:55:26 -0700251 mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
Sreeram Ramachandrana79f6182014-04-24 15:55:26 -0700252
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700253 _resolv_delete_cache_for_net(netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700254 return status;
255}
256
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700257bool NetworkController::setPermissionForUser(Permission permission,
258 const std::vector<unsigned>& uid) {
259 for (size_t i = 0; i < uid.size(); ++i) {
260 mPermissionsController->setPermissionForUser(permission, uid[i]);
261 }
262 return true;
263}
264
265bool NetworkController::setPermissionForNetwork(Permission newPermission,
266 const std::vector<unsigned>& netId) {
267 bool status = true;
268
269 for (size_t i = 0; i < netId.size(); ++i) {
270 if (!isNetIdValid(netId[i])) {
271 ALOGE("invalid netId %u", netId[i]);
272 status = false;
273 continue;
274 }
275
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700276 InterfaceRange range = interfacesForNetId(netId[i], &status);
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700277
278 Permission oldPermission = mPermissionsController->getPermissionForNetwork(netId[i]);
279 if (oldPermission == newPermission) {
280 continue;
281 }
282
283 // TODO: ioctl(SIOCKILLADDR, ...) to kill sockets on the network that don't have
284 // newPermission.
285
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700286 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700287 if (!mRouteController->modifyNetworkPermission(netId[i], iter->second.c_str(),
288 oldPermission, newPermission)) {
289 status = false;
290 }
291 }
292
293 mPermissionsController->setPermissionForNetwork(newPermission, netId[i]);
294 }
295
296 return status;
297}
298
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700299bool NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
300 const char* nexthop) {
301 return modifyRoute(netId, interface, destination, nexthop, true);
302}
303
304bool NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
305 const char* nexthop) {
306 return modifyRoute(netId, interface, destination, nexthop, false);
307}
308
309unsigned NetworkController::netIdForInterface(const char* interface) {
310 for (InterfaceIterator iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end();
311 ++iter) {
312 if (iter->second == interface) {
313 return iter->first;
314 }
315 }
316 return NETID_UNSET;
317}
318
319NetworkController::InterfaceRange NetworkController::interfacesForNetId(unsigned netId,
320 bool* status) {
321 InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
322 if (range.first == range.second) {
323 ALOGE("unknown netId %u", netId);
324 *status = false;
325 }
326 return range;
327}
328
329bool NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
330 const char* nexthop, bool add) {
331 if (!isNetIdValid(netId)) {
332 ALOGE("invalid netId %u", netId);
333 return false;
334 }
335
336 if (netIdForInterface(interface) != netId) {
337 ALOGE("netId %u has no such interface %s", netId, interface);
338 return false;
339 }
340
341 return add ? mRouteController->addRoute(interface, destination, nexthop) :
342 mRouteController->removeRoute(interface, destination, nexthop);
343}
344
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500345NetworkController::UidEntry::UidEntry(
346 int start, int end, unsigned netId, bool forward_dns)
347 : uid_start(start),
348 uid_end(end),
349 netId(netId),
350 forward_dns(forward_dns) {
351}