Pass route add/delete errors back to CommandListener.
Change-Id: Id1d6d578963080e141f71bc1303801fc53bce40a
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index 3c16fa3..9716b9e 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -309,7 +309,10 @@
mask.intValue, NULL);
}
-bool modifyRoute(const char* interface, const char* destination, const char* nexthop,
+// Adds or removes an IPv4 or IPv6 route to the specified table and, if it's directly-connected
+// route, to the main table as well.
+// Returns 0 on success or negative errno on failure.
+int modifyRoute(const char* interface, const char* destination, const char* nexthop,
int action, RouteController::TableType tableType, unsigned /* uid */) {
uint32_t table = 0;
switch (tableType) {
@@ -329,26 +332,27 @@
}
}
if (!table) {
- return false;
+ return -ESRCH;
}
- if (modifyIpRoute(action, table, interface, destination, nexthop)) {
- return false;
+ int ret = modifyIpRoute(action, table, interface, destination, nexthop);
+ if (ret != 0) {
+ return ret;
}
// If there's no nexthop, this is a directly connected route. Add it to the main table also, to
- // let the kernel find it when validating nexthops when global routes are added. Don't do this
- // for IPv6, since all directly-connected routes in v6 are link-local and should already be in
- // the main table.
- // TODO: A failure here typically means that the route already exists in the main table, so we
- // ignore it. It's wrong to ignore other kinds of failures, but we have no way to distinguish
- // them based on the return status of the 'ip' command. Fix this situation by ignoring errors
- // only when action == ADD && error == EEXIST.
- if (!nexthop && !strchr(destination, ':')) {
- modifyIpRoute(action, RT_TABLE_MAIN, interface, destination, NULL);
+ // let the kernel find it when validating nexthops when global routes are added.
+ if (!nexthop) {
+ ret = modifyIpRoute(action, RT_TABLE_MAIN, interface, destination, NULL);
+ // A failure with action == ADD && errno == EEXIST means that the route already exists in
+ // the main table, perhaps because the kernel added it automatically as part of adding the
+ // IP address to the interface. Ignore this, but complain about everything else.
+ if (ret != 0 && !(action == RTM_NEWROUTE && ret == -EEXIST)) {
+ return ret;
+ }
}
- return true;
+ return 0;
}
bool flushRoutes(const char* interface) {
@@ -450,12 +454,12 @@
return modifyDefaultNetworkRules(interface, permission, DEL);
}
-bool RouteController::addRoute(const char* interface, const char* destination,
- const char* nexthop, TableType tableType, unsigned uid) {
+int RouteController::addRoute(const char* interface, const char* destination,
+ const char* nexthop, TableType tableType, unsigned uid) {
return modifyRoute(interface, destination, nexthop, RTM_NEWROUTE, tableType, uid);
}
-bool RouteController::removeRoute(const char* interface, const char* destination,
- const char* nexthop, TableType tableType, unsigned uid) {
+int RouteController::removeRoute(const char* interface, const char* destination,
+ const char* nexthop, TableType tableType, unsigned uid) {
return modifyRoute(interface, destination, nexthop, RTM_DELROUTE, tableType, uid);
}