Implement network create/destroy.
(cherry picked from commit 382fc20107aa38cca062f10b4bc05c47b6c7f191)
Change-Id: Id5f8df447d812c8e8cf03addbb5e70abdcdfceb9
diff --git a/NetworkController.cpp b/NetworkController.cpp
index 937347b..fe78935 100644
--- a/NetworkController.cpp
+++ b/NetworkController.cpp
@@ -21,10 +21,28 @@
#include "NetworkController.h"
-// Mark 1 is reserved for SecondaryTableController::PROTECT_MARK.
-NetworkController::NetworkController()
+#include "PermissionsController.h"
+#include "RouteController.h"
+
+namespace {
+
+// Keep these in sync with ConnectivityService.java.
+const unsigned int MIN_NET_ID = 10;
+const unsigned int MAX_NET_ID = 65535;
+
+} // namespace
+
+bool NetworkController::isNetIdValid(unsigned netId) {
+ return MIN_NET_ID <= netId && netId <= MAX_NET_ID;
+}
+
+NetworkController::NetworkController(PermissionsController* permissionsController,
+ RouteController* routeController)
: mDefaultNetId(NETID_UNSET),
- mNextFreeNetId(10) {}
+ mNextFreeNetId(MIN_NET_ID),
+ mPermissionsController(permissionsController),
+ mRouteController(routeController) {
+}
void NetworkController::clearNetworkPreference() {
android::RWLock::AutoWLock lock(mRWLock);
@@ -53,7 +71,7 @@
bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
bool forward_dns) {
android::RWLock::AutoWLock lock(mRWLock);
- if (uid_start > uid_end || netId == NETID_UNSET)
+ if (uid_start > uid_end || !isNetIdValid(netId))
return false;
for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
@@ -69,7 +87,7 @@
bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
android::RWLock::AutoWLock lock(mRWLock);
- if (uid_start > uid_end || netId == NETID_UNSET)
+ if (uid_start > uid_end || !isNetIdValid(netId))
return false;
for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
@@ -91,7 +109,7 @@
break;
return it->netId;
}
- if (requested_netId != NETID_UNSET)
+ if (isNetIdValid(requested_netId))
return requested_netId;
if (pid != PID_UNSPECIFIED) {
std::map<int, unsigned>::const_iterator it = mPidMap.find(pid);
@@ -111,6 +129,53 @@
return netId;
}
+bool NetworkController::createNetwork(unsigned netId, const char* interface,
+ Permission permission) {
+ if (!isNetIdValid(netId) || !interface) {
+ return false;
+ }
+
+ typedef std::multimap<unsigned, std::string>::const_iterator Iterator;
+ for (Iterator iter = mNetIdToInterfaces.begin(); iter != mNetIdToInterfaces.end(); ++iter) {
+ if (iter->second == interface) {
+ return false;
+ }
+ }
+
+ if (!mRouteController->createNetwork(netId, interface, permission)) {
+ return false;
+ }
+
+ mPermissionsController->setPermissionForNetwork(netId, permission);
+ mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
+ return true;
+}
+
+bool NetworkController::destroyNetwork(unsigned netId) {
+ if (!isNetIdValid(netId)) {
+ return false;
+ }
+
+ // TODO: ioctl(SIOCKILLADDR, ...);
+
+ 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) {
+ if (!mRouteController->destroyNetwork(netId, iter->second.c_str(), permission)) {
+ status = false;
+ }
+ }
+
+ mPermissionsController->clearPermissionForNetwork(netId);
+ mNetIdToInterfaces.erase(netId);
+
+ return status;
+}
+
NetworkController::UidEntry::UidEntry(
int start, int end, unsigned netId, bool forward_dns)
: uid_start(start),