Add locking to RouteController.

Test: netd_{unit,integration}_test passes
Change-Id: I12899e0304d266b25b0b021ae28f9073c8b42604
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index e2f317d..498ac11 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -136,7 +136,8 @@
     }
 }
 
-uint32_t RouteController::getRouteTableForInterface(const char* interface) {
+// Caller must hold sInterfaceToTableLock.
+uint32_t RouteController::getRouteTableForInterfaceLocked(const char* interface) {
     uint32_t index = if_nametoindex(interface);
     if (index) {
         index += RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX;
@@ -153,6 +154,11 @@
     return iter->second;
 }
 
+uint32_t RouteController::getRouteTableForInterface(const char* interface) {
+    android::RWLock::AutoRLock lock(sInterfaceToTableLock);
+    return getRouteTableForInterfaceLocked(interface);
+}
+
 void addTableName(uint32_t table, const std::string& name, std::string* contents) {
     char tableString[UINT32_STRLEN];
     snprintf(tableString, sizeof(tableString), "%u", table);
@@ -173,6 +179,7 @@
     addTableName(ROUTE_TABLE_LEGACY_NETWORK, ROUTE_TABLE_NAME_LEGACY_NETWORK, &contents);
     addTableName(ROUTE_TABLE_LEGACY_SYSTEM,  ROUTE_TABLE_NAME_LEGACY_SYSTEM,  &contents);
 
+    android::RWLock::AutoRLock lock(sInterfaceToTableLock);
     for (const auto& entry : sInterfaceToTable) {
         addTableName(entry.second, entry.first, &contents);
     }
@@ -905,7 +912,9 @@
 
 // Returns 0 on success or negative errno on failure.
 WARN_UNUSED_RESULT int RouteController::flushRoutes(const char* interface) {
-    uint32_t table = getRouteTableForInterface(interface);
+    android::RWLock::AutoWLock lock(sInterfaceToTableLock);
+
+    uint32_t table = getRouteTableForInterfaceLocked(interface);
     if (table == RT_TABLE_UNSPEC) {
         return -ESRCH;
     }
@@ -1064,7 +1073,9 @@
     return modifyVpnFallthroughRule(RTM_DELRULE, vpnNetId, physicalInterface, permission);
 }
 
-// No locks needed because RouteController is accessed only from one thread (in CommandListener).
+// Protects sInterfaceToTable.
+android::RWLock RouteController::sInterfaceToTableLock;
+
 std::map<std::string, uint32_t> RouteController::sInterfaceToTable;
 
 }  // namespace net