blob: efa23f17d6dc8590baca1b8d11f2cba3d005813e [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 Jensenbe1e7d82014-04-17 13:35:33 -040041 : mDefaultNetId(NETID_UNSET),
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070042 mNextFreeNetId(MIN_NET_ID),
43 mPermissionsController(permissionsController),
44 mRouteController(routeController) {
45}
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050046
47void NetworkController::clearNetworkPreference() {
48 android::RWLock::AutoWLock lock(mRWLock);
49 mUidMap.clear();
50 mPidMap.clear();
51}
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 Ramachandran9c0d3132014-04-10 20:35:04 -070058bool NetworkController::setDefaultNetwork(unsigned newNetId) {
59 unsigned oldNetId;
60 {
61 android::RWLock::AutoWLock lock(mRWLock);
62 oldNetId = mDefaultNetId;
63 mDefaultNetId = newNetId;
64 }
65
66 if (oldNetId == newNetId) {
67 return true;
68 }
69
70 bool status = true;
71
72 // Add default network rules for the new netId.
73 if (isNetIdValid(newNetId)) {
74 Permission permission = mPermissionsController->getPermissionForNetwork(newNetId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070075 InterfaceRange range = interfacesForNetId(newNetId, &status);
76 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070077 if (!mRouteController->addDefaultNetwork(iter->second.c_str(), permission)) {
78 status = false;
79 }
80 }
81 }
82
83 // Remove the old default network rules.
84 if (isNetIdValid(oldNetId)) {
85 Permission permission = mPermissionsController->getPermissionForNetwork(oldNetId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070086 InterfaceRange range = interfacesForNetId(oldNetId, &status);
87 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -070088 if (!mRouteController->removeDefaultNetwork(iter->second.c_str(), permission)) {
89 status = false;
90 }
91 }
92 }
93
94 return status;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050095}
96
97void NetworkController::setNetworkForPid(int pid, unsigned netId) {
98 android::RWLock::AutoWLock lock(mRWLock);
99 if (netId == 0) {
100 mPidMap.erase(pid);
101 } else {
102 mPidMap[pid] = netId;
103 }
104}
105
106bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
107 bool forward_dns) {
108 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700109 if (uid_start > uid_end || !isNetIdValid(netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500110 return false;
111
112 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
Paul Jensen5b49ab92014-04-03 19:06:00 -0400113 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500114 continue;
Paul Jensen5b49ab92014-04-03 19:06:00 -0400115 it->forward_dns = forward_dns;
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500116 return true;
117 }
118
Paul Jensen5b49ab92014-04-03 19:06:00 -0400119 mUidMap.push_front(UidEntry(uid_start, uid_end, netId, forward_dns));
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500120 return true;
121}
122
Paul Jensen5b49ab92014-04-03 19:06:00 -0400123bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
124 android::RWLock::AutoWLock lock(mRWLock);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700125 if (uid_start > uid_end || !isNetIdValid(netId))
Paul Jensen5b49ab92014-04-03 19:06:00 -0400126 return false;
127
128 for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
129 if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
130 continue;
131 mUidMap.erase(it);
132 return true;
133 }
134 return false;
135}
136
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500137unsigned NetworkController::getNetwork(int uid, unsigned requested_netId, int pid,
138 bool for_dns) const {
139 android::RWLock::AutoRLock lock(mRWLock);
140 for (std::list<UidEntry>::const_iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
141 if (uid < it->uid_start || it->uid_end < uid)
142 continue;
143 if (for_dns && !it->forward_dns)
144 break;
145 return it->netId;
146 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700147 if (isNetIdValid(requested_netId))
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500148 return requested_netId;
149 if (pid != PID_UNSPECIFIED) {
150 std::map<int, unsigned>::const_iterator it = mPidMap.find(pid);
151 if (it != mPidMap.end())
152 return it->second;
153 }
154 return mDefaultNetId;
155}
156
157unsigned NetworkController::getNetworkId(const char* interface) {
158 std::map<std::string, unsigned>::const_iterator it = mIfaceNetidMap.find(interface);
159 if (it != mIfaceNetidMap.end())
160 return it->second;
161
162 unsigned netId = mNextFreeNetId++;
163 mIfaceNetidMap[interface] = netId;
164 return netId;
165}
166
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700167bool NetworkController::createNetwork(unsigned netId, const char* interface,
168 Permission permission) {
169 if (!isNetIdValid(netId) || !interface) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700170 ALOGE("invalid netId %u or interface null", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700171 return false;
172 }
173
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700174 unsigned existingNetId = netIdForInterface(interface);
175 if (existingNetId != NETID_UNSET) {
176 ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
177 return false;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700178 }
179
180 if (!mRouteController->createNetwork(netId, interface, permission)) {
181 return false;
182 }
183
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700184 mPermissionsController->setPermissionForNetwork(permission, netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700185 mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
186 return true;
187}
188
189bool NetworkController::destroyNetwork(unsigned netId) {
190 if (!isNetIdValid(netId)) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700191 ALOGE("invalid netId %u", netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700192 return false;
193 }
194
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700195 // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700196
197 bool status = true;
198
199 Permission permission = mPermissionsController->getPermissionForNetwork(netId);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700200 InterfaceRange range = interfacesForNetId(netId, &status);
201 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700202 if (!mRouteController->destroyNetwork(netId, iter->second.c_str(), permission)) {
203 status = false;
204 }
205 }
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700206 mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700207 mNetIdToInterfaces.erase(netId);
208
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700209 if (netId == getDefaultNetwork()) {
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700210 // Could the default network have changed from below us, after we evaluated the 'if', making
211 // it wrong to call setDefaultNetwork() now? No, because the default can only change due to
212 // a command from CommandListener; but commands are serialized, I.e., we are processing the
213 // destroyNetwork() command here, so a setDefaultNetwork() command can't happen in parallel.
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700214 setDefaultNetwork(NETID_UNSET);
215 }
216
Sreeram Ramachandran3ced0692014-04-18 09:49:13 -0700217// TODO: Uncomment once this API has been added to bionic.
218#if 0
219 _resolv_delete_cache_for_net(netId);
220#endif
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700221 return status;
222}
223
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700224bool NetworkController::setPermissionForUser(Permission permission,
225 const std::vector<unsigned>& uid) {
226 for (size_t i = 0; i < uid.size(); ++i) {
227 mPermissionsController->setPermissionForUser(permission, uid[i]);
228 }
229 return true;
230}
231
232bool NetworkController::setPermissionForNetwork(Permission newPermission,
233 const std::vector<unsigned>& netId) {
234 bool status = true;
235
236 for (size_t i = 0; i < netId.size(); ++i) {
237 if (!isNetIdValid(netId[i])) {
238 ALOGE("invalid netId %u", netId[i]);
239 status = false;
240 continue;
241 }
242
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700243 InterfaceRange range = interfacesForNetId(netId[i], &status);
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700244
245 Permission oldPermission = mPermissionsController->getPermissionForNetwork(netId[i]);
246 if (oldPermission == newPermission) {
247 continue;
248 }
249
250 // TODO: ioctl(SIOCKILLADDR, ...) to kill sockets on the network that don't have
251 // newPermission.
252
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700253 for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700254 if (!mRouteController->modifyNetworkPermission(netId[i], iter->second.c_str(),
255 oldPermission, newPermission)) {
256 status = false;
257 }
258 }
259
260 mPermissionsController->setPermissionForNetwork(newPermission, netId[i]);
261 }
262
263 return status;
264}
265
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700266bool NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
267 const char* nexthop) {
268 return modifyRoute(netId, interface, destination, nexthop, true);
269}
270
271bool NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
272 const char* nexthop) {
273 return modifyRoute(netId, interface, destination, nexthop, false);
274}
275
276unsigned NetworkController::netIdForInterface(const char* interface) {
277 for (InterfaceIterator iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end();
278 ++iter) {
279 if (iter->second == interface) {
280 return iter->first;
281 }
282 }
283 return NETID_UNSET;
284}
285
286NetworkController::InterfaceRange NetworkController::interfacesForNetId(unsigned netId,
287 bool* status) {
288 InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
289 if (range.first == range.second) {
290 ALOGE("unknown netId %u", netId);
291 *status = false;
292 }
293 return range;
294}
295
296bool NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
297 const char* nexthop, bool add) {
298 if (!isNetIdValid(netId)) {
299 ALOGE("invalid netId %u", netId);
300 return false;
301 }
302
303 if (netIdForInterface(interface) != netId) {
304 ALOGE("netId %u has no such interface %s", netId, interface);
305 return false;
306 }
307
308 return add ? mRouteController->addRoute(interface, destination, nexthop) :
309 mRouteController->removeRoute(interface, destination, nexthop);
310}
311
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500312NetworkController::UidEntry::UidEntry(
313 int start, int end, unsigned netId, bool forward_dns)
314 : uid_start(start),
315 uid_end(end),
316 netId(netId),
317 forward_dns(forward_dns) {
318}