This should facilitate stacked interfaces (i.e. clatd).
Change-Id: Ib3e7a4d3847ef6ec4449451f6da42e75959baa4f
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.
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);
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> ...
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;
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);
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;
}
}
}
mPermissionsController->setPermissionForNetwork(PERMISSION_NONE, netId);
- mNetIdToInterfaces.erase(netId);
// TODO: Uncomment once this API has been added to bionic.
#if 0
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);
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.
#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);
}
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);