Add full support for UIDs in VPNs.

Major:
+ Implement the functions mentioned in http://go/android-multinetwork-routing
  correctly, including handling accept(), connect(), setNetworkForSocket()
  and protect() and supporting functions like canUserSelectNetwork().
+ Eliminate the old code path of getting/setting UID ranges through
  SecondaryTableController (which is currently unused) and mUidMap.

Minor:
+ Rename some methods/variables for clarity and consistency.
+ Moved some methods in .cpp files to match declaration order in the .h files.

Bug: 15409918
Change-Id: Ic6ce3646c58cf645db0d9a53cbeefdd7ffafff93
diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp
index 03c22be..1487b72 100644
--- a/server/NetworkController.cpp
+++ b/server/NetworkController.cpp
@@ -90,57 +90,17 @@
     return 0;
 }
 
-bool NetworkController::setNetworkForUidRange(uid_t uidStart, uid_t uidEnd, unsigned netId,
-                                              bool forwardDns) {
-    if (uidStart > uidEnd || !isValidNetwork(netId)) {
-        errno = EINVAL;
-        return false;
-    }
-
-    android::RWLock::AutoWLock lock(mRWLock);
-    for (UidEntry& entry : mUidMap) {
-        if (entry.uidStart == uidStart && entry.uidEnd == uidEnd && entry.netId == netId) {
-            entry.forwardDns = forwardDns;
-            return true;
-        }
-    }
-
-    mUidMap.push_front(UidEntry(uidStart, uidEnd, netId, forwardDns));
-    return true;
-}
-
-bool NetworkController::clearNetworkForUidRange(uid_t uidStart, uid_t uidEnd, unsigned netId) {
-    if (uidStart > uidEnd || !isValidNetwork(netId)) {
-        errno = EINVAL;
-        return false;
-    }
-
-    android::RWLock::AutoWLock lock(mRWLock);
-    for (auto iter = mUidMap.begin(); iter != mUidMap.end(); ++iter) {
-        if (iter->uidStart == uidStart && iter->uidEnd == uidEnd && iter->netId == netId) {
-            mUidMap.erase(iter);
-            return true;
-        }
-    }
-
-    errno = ENOENT;
-    return false;
-}
-
-unsigned NetworkController::getNetwork(uid_t uid, unsigned requestedNetId, bool forDns) const {
+unsigned NetworkController::getNetworkForUser(uid_t uid, unsigned requestedNetId,
+                                              bool forDns) const {
     android::RWLock::AutoRLock lock(mRWLock);
-    for (const UidEntry& entry : mUidMap) {
-        if (entry.uidStart <= uid && uid <= entry.uidEnd) {
-            if (forDns && !entry.forwardDns) {
-                break;
-            }
-            return entry.netId;
-        }
+    VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
+    if (virtualNetwork && (!forDns || virtualNetwork->getHasDns())) {
+        return virtualNetwork->getNetId();
     }
     return getNetworkLocked(requestedNetId) ? requestedNetId : mDefaultNetId;
 }
 
-unsigned NetworkController::getNetworkId(const char* interface) const {
+unsigned NetworkController::getNetworkForInterface(const char* interface) const {
     android::RWLock::AutoRLock lock(mRWLock);
     for (const auto& entry : mNetworks) {
         if (entry.second->hasInterface(interface)) {
@@ -150,12 +110,7 @@
     return NETID_UNSET;
 }
 
-bool NetworkController::isValidNetwork(unsigned netId) const {
-    android::RWLock::AutoRLock lock(mRWLock);
-    return getNetworkLocked(netId);
-}
-
-int NetworkController::createNetwork(unsigned netId, Permission permission) {
+int NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
     if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
         ALOGE("invalid netId %u", netId);
         return -EINVAL;
@@ -178,7 +133,7 @@
     return 0;
 }
 
-int NetworkController::createVpn(unsigned netId) {
+int NetworkController::createVirtualNetwork(unsigned netId, bool hasDns) {
     if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
         ALOGE("invalid netId %u", netId);
         return -EINVAL;
@@ -190,7 +145,7 @@
     }
 
     android::RWLock::AutoWLock lock(mRWLock);
-    mNetworks[netId] = new VirtualNetwork(netId);
+    mNetworks[netId] = new VirtualNetwork(netId, hasDns);
     return 0;
 }
 
@@ -226,7 +181,7 @@
         return -EINVAL;
     }
 
-    unsigned existingNetId = getNetworkId(interface);
+    unsigned existingNetId = getNetworkForInterface(interface);
     if (existingNetId != NETID_UNSET && existingNetId != netId) {
         ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
         return -EBUSY;
@@ -259,18 +214,23 @@
     }
 }
 
-// TODO: Handle VPNs.
-bool NetworkController::isUserPermittedOnNetwork(uid_t uid, unsigned netId) const {
-    if (uid == INVALID_UID || netId == NETID_UNSET) {
-        return false;
-    }
-
+bool NetworkController::canUserSelectNetwork(uid_t uid, unsigned netId) const {
     android::RWLock::AutoRLock lock(mRWLock);
     Network* network = getNetworkLocked(netId);
-    if (!network || network->getType() != Network::PHYSICAL) {
+    if (!network || uid == INVALID_UID) {
         return false;
     }
     Permission userPermission = getPermissionForUserLocked(uid);
+    if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
+        return true;
+    }
+    if (network->getType() == Network::VIRTUAL) {
+        return static_cast<VirtualNetwork*>(network)->appliesToUser(uid);
+    }
+    VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
+    if (virtualNetwork && mProtectableUsers.find(uid) == mProtectableUsers.end()) {
+        return false;
+    }
     Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission();
     return (userPermission & networkPermission) == networkPermission;
 }
@@ -330,6 +290,12 @@
     return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
 }
 
+bool NetworkController::canProtect(uid_t uid) const {
+    android::RWLock::AutoRLock lock(mRWLock);
+    return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) ||
+           mProtectableUsers.find(uid) != mProtectableUsers.end();
+}
+
 void NetworkController::allowProtect(const std::vector<uid_t>& uids) {
     android::RWLock::AutoWLock lock(mRWLock);
     mProtectableUsers.insert(uids.begin(), uids.end());
@@ -342,11 +308,28 @@
     }
 }
 
+bool NetworkController::isValidNetwork(unsigned netId) const {
+    android::RWLock::AutoRLock lock(mRWLock);
+    return getNetworkLocked(netId);
+}
+
 Network* NetworkController::getNetworkLocked(unsigned netId) const {
     auto iter = mNetworks.find(netId);
     return iter == mNetworks.end() ? NULL : iter->second;
 }
 
+VirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const {
+    for (const auto& entry : mNetworks) {
+        if (entry.second->getType() == Network::VIRTUAL) {
+            VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second);
+            if (virtualNetwork->appliesToUser(uid)) {
+                return virtualNetwork;
+            }
+        }
+    }
+    return NULL;
+}
+
 Permission NetworkController::getPermissionForUserLocked(uid_t uid) const {
     auto iter = mUsers.find(uid);
     if (iter != mUsers.end()) {
@@ -357,7 +340,7 @@
 
 int NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
                                    const char* nexthop, bool add, bool legacy, uid_t uid) {
-    unsigned existingNetId = getNetworkId(interface);
+    unsigned existingNetId = getNetworkForInterface(interface);
     if (netId == NETID_UNSET || existingNetId != netId) {
         ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
         return -ENOENT;
@@ -377,8 +360,3 @@
     return add ? RouteController::addRoute(interface, destination, nexthop, tableType) :
                  RouteController::removeRoute(interface, destination, nexthop, tableType);
 }
-
-NetworkController::UidEntry::UidEntry(uid_t uidStart, uid_t uidEnd, unsigned netId,
-                                      bool forwardDns) :
-        uidStart(uidStart), uidEnd(uidEnd), netId(netId), forwardDns(forwardDns) {
-}