Implement the "network route add/remove" API.
(cherry picked from commit 909c52248a4ad832548c5feb5e9a58323e30ab7b)
Change-Id: Idb09b0c22a3a519dda232995ced406e470ab9768
diff --git a/NetworkController.cpp b/NetworkController.cpp
index 14c63f3..eaaee5a 100644
--- a/NetworkController.cpp
+++ b/NetworkController.cpp
@@ -72,10 +72,8 @@
// Add default network rules for the new netId.
if (isNetIdValid(newNetId)) {
Permission permission = mPermissionsController->getPermissionForNetwork(newNetId);
-
- typedef std::multimap<unsigned, std::string>::const_iterator Iterator;
- std::pair<Iterator, Iterator> range = mNetIdToInterfaces.equal_range(newNetId);
- for (Iterator iter = range.first; iter != range.second; ++iter) {
+ InterfaceRange range = interfacesForNetId(newNetId, &status);
+ for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
if (!mRouteController->addDefaultNetwork(iter->second.c_str(), permission)) {
status = false;
}
@@ -85,10 +83,8 @@
// Remove the old default network rules.
if (isNetIdValid(oldNetId)) {
Permission permission = mPermissionsController->getPermissionForNetwork(oldNetId);
-
- typedef std::multimap<unsigned, std::string>::const_iterator Iterator;
- std::pair<Iterator, Iterator> range = mNetIdToInterfaces.equal_range(oldNetId);
- for (Iterator iter = range.first; iter != range.second; ++iter) {
+ InterfaceRange range = interfacesForNetId(oldNetId, &status);
+ for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
if (!mRouteController->removeDefaultNetwork(iter->second.c_str(), permission)) {
status = false;
}
@@ -175,12 +171,10 @@
return false;
}
- typedef std::multimap<unsigned, std::string>::const_iterator Iterator;
- for (Iterator iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end(); ++iter) {
- if (iter->second == interface) {
- ALOGE("interface %s already assigned to netId %u", interface, iter->first);
- return false;
- }
+ unsigned existingNetId = netIdForInterface(interface);
+ if (existingNetId != NETID_UNSET) {
+ ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
+ return false;
}
if (!mRouteController->createNetwork(netId, interface, permission)) {
@@ -203,23 +197,20 @@
bool status = true;
Permission permission = mPermissionsController->getPermissionForNetwork(netId);
-
- typedef std::multimap<unsigned, std::string>::const_iterator Iterator;
- std::pair<Iterator, Iterator> range = mNetIdToInterfaces.equal_range(netId);
- for (Iterator iter = range.first; iter != range.second; ++iter) {
+ InterfaceRange range = interfacesForNetId(netId, &status);
+ for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
if (!mRouteController->destroyNetwork(netId, iter->second.c_str(), permission)) {
status = false;
}
}
-
mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
mNetIdToInterfaces.erase(netId);
if (netId == getDefaultNetwork()) {
- // Could the default network have changed from below us, after we evaluated the 'if', thus
- // making it wrong to call setDefaultNetwork() now? No, because the default can only change
- // due to another command from CommandListener, and those are serialized (i.e., they can't
- // happen in parallel with the destroyNetwork() that we are currently processing).
+ // Could the default network have changed from below us, after we evaluated the 'if', making
+ // it wrong to call setDefaultNetwork() now? No, because the default can only change due to
+ // a command from CommandListener; but commands are serialized, I.e., we are processing the
+ // destroyNetwork() command here, so a setDefaultNetwork() command can't happen in parallel.
setDefaultNetwork(NETID_UNSET);
}
@@ -245,13 +236,7 @@
continue;
}
- typedef std::multimap<unsigned, std::string>::const_iterator Iterator;
- std::pair<Iterator, Iterator> range = mNetIdToInterfaces.equal_range(netId[i]);
- if (range.first == range.second) {
- ALOGE("unknown netId %u", netId[i]);
- status = false;
- continue;
- }
+ InterfaceRange range = interfacesForNetId(netId[i], &status);
Permission oldPermission = mPermissionsController->getPermissionForNetwork(netId[i]);
if (oldPermission == newPermission) {
@@ -261,7 +246,7 @@
// TODO: ioctl(SIOCKILLADDR, ...) to kill sockets on the network that don't have
// newPermission.
- for (Iterator iter = range.first; iter != range.second; ++iter) {
+ for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
if (!mRouteController->modifyNetworkPermission(netId[i], iter->second.c_str(),
oldPermission, newPermission)) {
status = false;
@@ -274,6 +259,52 @@
return status;
}
+bool NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
+ const char* nexthop) {
+ return modifyRoute(netId, interface, destination, nexthop, true);
+}
+
+bool NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
+ const char* nexthop) {
+ return modifyRoute(netId, interface, destination, nexthop, false);
+}
+
+unsigned NetworkController::netIdForInterface(const char* interface) {
+ for (InterfaceIterator iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end();
+ ++iter) {
+ if (iter->second == interface) {
+ return iter->first;
+ }
+ }
+ return NETID_UNSET;
+}
+
+NetworkController::InterfaceRange NetworkController::interfacesForNetId(unsigned netId,
+ bool* status) {
+ InterfaceRange range = mNetIdToInterfaces.equal_range(netId);
+ if (range.first == range.second) {
+ ALOGE("unknown netId %u", netId);
+ *status = false;
+ }
+ return range;
+}
+
+bool NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
+ const char* nexthop, bool add) {
+ if (!isNetIdValid(netId)) {
+ ALOGE("invalid netId %u", netId);
+ return false;
+ }
+
+ if (netIdForInterface(interface) != netId) {
+ ALOGE("netId %u has no such interface %s", netId, interface);
+ return false;
+ }
+
+ return add ? mRouteController->addRoute(interface, destination, nexthop) :
+ mRouteController->removeRoute(interface, destination, nexthop);
+}
+
NetworkController::UidEntry::UidEntry(
int start, int end, unsigned netId, bool forward_dns)
: uid_start(start),