blob: a11fae8addf7d15054768dc1b6054bebc4decb34 [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)
Sreeram Ramachandran574e6332014-05-14 08:31:55 -070041 : mDefaultNetId(NETID_UNSET),
42 mPermissionsController(permissionsController),
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070043 mRouteController(routeController) {
44}
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050045
46void NetworkController::clearNetworkPreference() {
47 android::RWLock::AutoWLock lock(mRWLock);
48 mUidMap.clear();
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050049}
50
51unsigned NetworkController::getDefaultNetwork() const {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070052 android::RWLock::AutoRLock lock(mRWLock);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050053 return mDefaultNetId;
54}
55
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070056bool NetworkController::setDefaultNetwork(unsigned newNetId) {
57 unsigned oldNetId;
58 {
59 android::RWLock::AutoWLock lock(mRWLock);
60 oldNetId = mDefaultNetId;
61 mDefaultNetId = newNetId;
62 }
63
64 if (oldNetId == newNetId) {
65 return true;
66 }
67
68 bool status = true;
69
70 // Add default network rules for the new netId.
71 if (isNetIdValid(newNetId)) {
72 Permission permission = mPermissionsController->getPermissionForNetwork(newNetId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070073 InterfaceRange range = interfacesForNetId(newNetId, &status);
74 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070075 if (!mRouteController->addDefaultNetwork(iter->second.c_str(), permission)) {
76 status = false;
77 }
78 }
79 }
80
81 // Remove the old default network rules.
82 if (isNetIdValid(oldNetId)) {
83 Permission permission = mPermissionsController->getPermissionForNetwork(oldNetId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070084 InterfaceRange range = interfacesForNetId(oldNetId, &status);
85 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070086 if (!mRouteController->removeDefaultNetwork(iter->second.c_str(), permission)) {
87 status = false;
88 }
89 }
90 }
91
92 return status;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050093}
94
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050095bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
96 bool forward_dns) {
97 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070098 if (uid_start > uid_end || !isNetIdValid(netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050099 return false;
100
101 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
Paul Jensen5b49ab92014-04-03 19:06:00 -0400102 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500103 continue;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400104 it->forward_dns = forward_dns;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500105 return true;
106 }
107
Paul Jensen5b49ab92014-04-03 19:06:00 -0400108 mUidMap.push_front(UidEntry(uid_start, uid_end, netId, forward_dns));
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500109 return true;
110}
111
Paul Jensen5b49ab92014-04-03 19:06:00 -0400112bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
113 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700114 if (uid_start > uid_end || !isNetIdValid(netId))
Paul Jensen5b49ab92014-04-03 19:06:00 -0400115 return false;
116
117 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
118 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
119 continue;
120 mUidMap.erase(it);
121 return true;
122 }
123 return false;
124}
125
Paul Jensen35c77e32014-04-10 14:57:54 -0400126unsigned NetworkController::getNetwork(int uid, unsigned requested_netId, bool for_dns) const {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500127 android::RWLock::AutoRLock lock(mRWLock);
128 for (std::list<UidEntry>::const_iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
129 if (uid < it->uid_start || it->uid_end < uid)
130 continue;
131 if (for_dns && !it->forward_dns)
132 break;
133 return it->netId;
134 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700135 if (isNetIdValid(requested_netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500136 return requested_netId;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500137 return mDefaultNetId;
138}
139
140unsigned NetworkController::getNetworkId(const char* interface) {
141 std::map<std::string, unsigned>::const_iterator it = mIfaceNetidMap.find(interface);
142 if (it != mIfaceNetidMap.end())
143 return it->second;
Paul Jensen35c77e32014-04-10 14:57:54 -0400144 return NETID_UNSET;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500145}
146
Paul Jensenae37e8a2014-04-28 10:35:51 -0400147bool NetworkController::createNetwork(unsigned netId, Permission permission) {
148 if (!isNetIdValid(netId)) {
149 ALOGE("invalid netId %u", netId);
150 return false;
151 }
152
153 mPermissionsController->setPermissionForNetwork(permission, netId);
154 return true;
155}
156
157bool NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700158 if (!isNetIdValid(netId) || !interface) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700159 ALOGE("invalid netId %u or interface null", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700160 return false;
161 }
162
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700163 unsigned existingNetId = netIdForInterface(interface);
164 if (existingNetId != NETID_UNSET) {
165 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
166 return false;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700167 }
168
Paul Jensenae37e8a2014-04-28 10:35:51 -0400169 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
170 if (!mRouteController->addInterfaceToNetwork(netId, interface, permission)) {
171 ALOGE("failed to add rules for interface %s to netId %u", interface, netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700172 return false;
173 }
174
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700175 mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
Paul Jensen35c77e32014-04-10 14:57:54 -0400176 mIfaceNetidMap[interface] = netId;
Paul Jensenae37e8a2014-04-28 10:35:51 -0400177
178 if (netId == getDefaultNetwork() &&
179 !mRouteController->addDefaultNetwork(interface, permission)) {
180 ALOGE("failed to add interface %s to default network %u", interface, netId);
181 return false;
182 }
183
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700184 return true;
185}
186
Paul Jensenae37e8a2014-04-28 10:35:51 -0400187bool NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
188 if (!isNetIdValid(netId) || !interface) {
189 ALOGE("invalid netId %u or interface null", netId);
190 return false;
191 }
192
193 bool status = true;
194 bool found = false;
195 InterfaceRange range = interfacesForNetId(netId, &status);
196 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
197 if (iter->second == interface) {
198 mNetIdToInterfaces.erase(iter);
199 found = true;
200 break;
201 }
202 }
203 if (!found) {
204 ALOGE("interface %s not a member of netId %u", interface, netId);
205 status = false;
206 }
207
208 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
209 if (!mRouteController->removeInterfaceFromNetwork(netId, interface, permission)) {
210 ALOGE("failed to remove rules for interface %s from netId %u", interface, netId);
211 status = false;
212 }
213
214 if (netId == getDefaultNetwork() &&
215 !mRouteController->removeDefaultNetwork(interface, permission)) {
216 ALOGE("failed to remove interface %s from default network %u", interface, netId);
217 status = false;
218 }
219
220 mIfaceNetidMap.erase(interface);
221
222 return status;
223}
224
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700225bool NetworkController::destroyNetwork(unsigned netId) {
226 if (!isNetIdValid(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700227 ALOGE("invalid netId %u", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700228 return false;
229 }
230
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700231 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700232
233 bool status = true;
234
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700235 InterfaceRange range = interfacesForNetId(netId, &status);
Paul Jensenae37e8a2014-04-28 10:35:51 -0400236 for (InterfaceIterator iter = range.first; iter != range.second; ) {
237 InterfaceIterator toErase = iter;
238 ++iter;
239 if (!removeInterfaceFromNetwork(netId, toErase->second.c_str())) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700240 status = false;
241 }
242 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700243
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700244 if (netId == getDefaultNetwork()) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700245 // Could the default network have changed from below us, after we evaluated the 'if', making
246 // it wrong to call setDefaultNetwork() now? No, because the default can only change due to
247 // a command from CommandListener; but commands are serialized, I.e., we are processing the
248 // destroyNetwork() command here, so a setDefaultNetwork() command can't happen in parallel.
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700249 setDefaultNetwork(NETID_UNSET);
250 }
251
Sreeram Ramachandrana79f6182014-04-24 15:55:26 -0700252 mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
Sreeram Ramachandrana79f6182014-04-24 15:55:26 -0700253
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700254 _resolv_delete_cache_for_net(netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700255 return status;
256}
257
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700258bool NetworkController::setPermissionForUser(Permission permission,
259 const std::vector<unsigned>& uid) {
260 for (size_t i = 0; i < uid.size(); ++i) {
261 mPermissionsController->setPermissionForUser(permission, uid[i]);
262 }
263 return true;
264}
265
266bool NetworkController::setPermissionForNetwork(Permission newPermission,
267 const std::vector<unsigned>& netId) {
268 bool status = true;
269
270 for (size_t i = 0; i < netId.size(); ++i) {
271 if (!isNetIdValid(netId[i])) {
272 ALOGE("invalid netId %u", netId[i]);
273 status = false;
274 continue;
275 }
276
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700277 InterfaceRange range = interfacesForNetId(netId[i], &status);
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700278
279 Permission oldPermission = mPermissionsController->getPermissionForNetwork(netId[i]);
280 if (oldPermission == newPermission) {
281 continue;
282 }
283
284 // TODO: ioctl(SIOCKILLADDR, ...) to kill sockets on the network that don't have
285 // newPermission.
286
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700287 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700288 if (!mRouteController->modifyNetworkPermission(netId[i], iter->second.c_str(),
289 oldPermission, newPermission)) {
290 status = false;
291 }
292 }
293
294 mPermissionsController->setPermissionForNetwork(newPermission, netId[i]);
295 }
296
297 return status;
298}
299
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700300bool NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
301 const char* nexthop) {
302 return modifyRoute(netId, interface, destination, nexthop, true);
303}
304
305bool NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
306 const char* nexthop) {
307 return modifyRoute(netId, interface, destination, nexthop, false);
308}
309
310unsigned NetworkController::netIdForInterface(const char* interface) {
311 for (InterfaceIterator iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end();
312 ++iter) {
313 if (iter->second == interface) {
314 return iter->first;
315 }
316 }
317 return NETID_UNSET;
318}
319
320NetworkController::InterfaceRange NetworkController::interfacesForNetId(unsigned netId,
321 bool* status) {
322 InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
323 if (range.first == range.second) {
324 ALOGE("unknown netId %u", netId);
325 *status = false;
326 }
327 return range;
328}
329
330bool NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
331 const char* nexthop, bool add) {
332 if (!isNetIdValid(netId)) {
333 ALOGE("invalid netId %u", netId);
334 return false;
335 }
336
337 if (netIdForInterface(interface) != netId) {
338 ALOGE("netId %u has no such interface %s", netId, interface);
339 return false;
340 }
341
342 return add ? mRouteController->addRoute(interface, destination, nexthop) :
343 mRouteController->removeRoute(interface, destination, nexthop);
344}
345
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500346NetworkController::UidEntry::UidEntry(
347 int start, int end, unsigned netId, bool forward_dns)
348 : uid_start(start),
349 uid_end(end),
350 netId(netId),
351 forward_dns(forward_dns) {
352}