OSDN Git Service

Separate network and interface addition/removal netd APIs.
authorPaul Jensen <pauljensen@google.com>
Mon, 28 Apr 2014 14:35:51 +0000 (10:35 -0400)
committerLorenzo Colitti <lorenzo@google.com>
Wed, 14 May 2014 09:46:17 +0000 (02:46 -0700)
This should facilitate stacked interfaces (i.e. clatd).

Change-Id: Ib3e7a4d3847ef6ec4449451f6da42e75959baa4f

CommandListener.cpp
NetworkController.cpp
NetworkController.h
RouteController.cpp
RouteController.h

index 112b55e..f7a04f2 100644 (file)
@@ -1586,10 +1586,10 @@ int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc,
         return syntaxError(client, "Missing argument");
     }
 
-    //    0      1       2         3            4
-    // network create <netId> <interface> [<permission> ...]
+    //    0      1       2          3
+    // network create <netId> [<permission> ...]
     if (!strcmp(argv[1], "create")) {
-        if (argc < 4) {
+        if (argc < 3) {
             return syntaxError(client, "Missing argument");
         }
         // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
@@ -1597,13 +1597,12 @@ int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc,
         if (!sNetCtrl->isNetIdValid(netId)) {
             return paramError(client, "Invalid netId");
         }
-        const char* interface = argv[3];
-        int nextArg = 4;
+        int nextArg = 3;
         Permission permission = parseMultiplePermissions(argc, argv, &nextArg);
         if (nextArg != argc) {
             return syntaxError(client, "Unknown trailing argument(s)");
         }
-        if (!sNetCtrl->createNetwork(netId, interface, permission)) {
+        if (!sNetCtrl->createNetwork(netId, permission)) {
             return operationError(client, "createNetwork() failed");
         }
         return success(client);
@@ -1630,6 +1629,30 @@ int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc,
         return success(client);
     }
 
+    //    0      1         2         3
+    // network addiface <netId> <interface>
+    // network removeiface <netId> <interface>
+    if (!strcmp(argv[1], "addiface") || !strcmp(argv[1], "removeiface")) {
+        if (argc != 4) {
+            return syntaxError(client, "Missing argument");
+        }
+        // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
+        unsigned netId = strtoul(argv[2], NULL, 0);
+        if (!sNetCtrl->isNetIdValid(netId)) {
+            return paramError(client, "Invalid netId");
+        }
+        if (!strcmp(argv[1], "addiface")) {
+            if (!sNetCtrl->addInterfaceToNetwork(netId, argv[3])) {
+                return operationError(client, "addInterfaceToNetwork() failed");
+            }
+        } else {
+            if (!sNetCtrl->removeInterfaceFromNetwork(netId, argv[3])) {
+                return operationError(client, "removeInterfaceFromNetwork() failed");
+            }
+        }
+        return success(client);
+    }
+
     //    0        1         2      3         4
     // network permission   user   set  [<permission> ...]  <uid>  ...
     // network permission   user  clear     <uid>     ...
index 93e1c1b..b36dd9d 100644 (file)
@@ -143,8 +143,17 @@ unsigned NetworkController::getNetworkId(const char* interface) {
     return NETID_UNSET;
 }
 
-bool NetworkController::createNetwork(unsigned netId, const char* interface,
-                                      Permission permission) {
+bool NetworkController::createNetwork(unsigned netId, Permission permission) {
+    if (!isNetIdValid(netId)) {
+        ALOGE("invalid netId %u", netId);
+        return false;
+    }
+
+    mPermissionsController->setPermissionForNetwork(permission, netId);
+    return true;
+}
+
+bool NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
     if (!isNetIdValid(netId) || !interface) {
         ALOGE("invalid netId %u or interface null", netId);
         return false;
@@ -156,16 +165,62 @@ bool NetworkController::createNetwork(unsigned netId, const char* interface,
         return false;
     }
 
-    if (!mRouteController->createNetwork(netId, interface, permission)) {
+    Permission permission = mPermissionsController->getPermissionForNetwork(netId);
+    if (!mRouteController->addInterfaceToNetwork(netId, interface, permission)) {
+        ALOGE("failed to add rules for interface %s to netId %u", interface, netId);
         return false;
     }
 
-    mPermissionsController->setPermissionForNetwork(permission, netId);
     mNetIdToInterfaces.insert(std::pair<unsigned, std::string>(netId, interface));
     mIfaceNetidMap[interface] = netId;
+
+    if (netId == getDefaultNetwork() &&
+            !mRouteController->addDefaultNetwork(interface, permission)) {
+        ALOGE("failed to add interface %s to default network %u", interface, netId);
+        return false;
+    }
+
     return true;
 }
 
+bool NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
+    if (!isNetIdValid(netId) || !interface) {
+        ALOGE("invalid netId %u or interface null", netId);
+        return false;
+    }
+
+    bool status = true;
+    bool found = false;
+    InterfaceRange range = interfacesForNetId(netId, &status);
+    for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
+        if (iter->second == interface) {
+            mNetIdToInterfaces.erase(iter);
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        ALOGE("interface %s not a member of netId %u", interface, netId);
+        status = false;
+    }
+
+    Permission permission = mPermissionsController->getPermissionForNetwork(netId);
+    if (!mRouteController->removeInterfaceFromNetwork(netId, interface, permission)) {
+        ALOGE("failed to remove rules for interface %s from netId %u", interface, netId);
+        status = false;
+    }
+
+    if (netId == getDefaultNetwork() &&
+            !mRouteController->removeDefaultNetwork(interface, permission)) {
+        ALOGE("failed to remove interface %s from default network %u", interface, netId);
+        status = false;
+    }
+
+    mIfaceNetidMap.erase(interface);
+
+    return status;
+}
+
 bool NetworkController::destroyNetwork(unsigned netId) {
     if (!isNetIdValid(netId)) {
         ALOGE("invalid netId %u", netId);
@@ -176,10 +231,11 @@ bool NetworkController::destroyNetwork(unsigned netId) {
 
     bool status = true;
 
-    Permission permission = mPermissionsController->getPermissionForNetwork(netId);
     InterfaceRange range = interfacesForNetId(netId, &status);
-    for (InterfaceIterator iter = range.first; iter != range.second; ++iter) {
-        if (!mRouteController->destroyNetwork(netId, iter->second.c_str(), permission)) {
+    for (InterfaceIterator iter = range.first; iter != range.second; ) {
+        InterfaceIterator toErase = iter;
+        ++iter;
+        if (!removeInterfaceFromNetwork(netId, toErase->second.c_str())) {
             status = false;
         }
     }
@@ -193,7 +249,6 @@ bool NetworkController::destroyNetwork(unsigned netId) {
     }
 
     mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
-    mNetIdToInterfaces.erase(netId);
 
 // TODO: Uncomment once this API has been added to bionic.
 #if 0
index f1c8fda..fff3289 100644 (file)
@@ -58,8 +58,10 @@ public:
 
     unsigned getNetworkId(const char* interface);
 
-    bool createNetwork(unsigned netId, const char* interface, Permission permission);
+    bool createNetwork(unsigned netId, Permission permission);
     bool destroyNetwork(unsigned netId);
+    bool addInterfaceToNetwork(unsigned netId, const char* interface);
+    bool removeInterfaceFromNetwork(unsigned netId, const char* interface);
 
     bool setPermissionForUser(Permission permission, const std::vector<unsigned>& uid);
     bool setPermissionForNetwork(Permission permission, const std::vector<unsigned>& netId);
@@ -72,7 +74,7 @@ public:
                      const char* nexthop);
 
 private:
-    typedef std::multimap<unsigned, std::string>::const_iterator InterfaceIterator;
+    typedef std::multimap<unsigned, std::string>::iterator InterfaceIterator;
     typedef std::pair<InterfaceIterator, InterfaceIterator> InterfaceRange;
 
     // Returns the netId that |interface| belongs to, or NETID_UNSET if it doesn't belong to any.
index e771c74..05170b8 100644 (file)
@@ -251,11 +251,13 @@ void RouteController::Init() {
 #endif
 }
 
-bool RouteController::createNetwork(unsigned netId, const char* interface, Permission permission) {
+bool RouteController::addInterfaceToNetwork(unsigned netId, const char* interface,
+                                            Permission permission) {
     return modifyPerNetworkRules(netId, interface, permission, true, true);
 }
 
-bool RouteController::destroyNetwork(unsigned netId, const char* interface, Permission permission) {
+bool RouteController::removeInterfaceFromNetwork(unsigned netId, const char* interface,
+                                                 Permission permission) {
     return modifyPerNetworkRules(netId, interface, permission, false, true) &&
            flushRoutes(interface);
 }
index d9cb10a..77b7eea 100644 (file)
@@ -25,8 +25,9 @@ public:
 
     static void Init();
 
-    static bool createNetwork(unsigned netId, const char* interface, Permission permission);
-    static bool destroyNetwork(unsigned netId, const char* interface, Permission permission);
+    static bool addInterfaceToNetwork(unsigned netId, const char* interface, Permission permission);
+    static bool removeInterfaceFromNetwork(unsigned netId, const char* interface,
+                                           Permission permission);
     static bool modifyNetworkPermission(unsigned netId, const char* interface,
                                         Permission oldPermission, Permission newPermission);