summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/RouteController.cpp18
-rw-r--r--server/RouteController.h8
-rw-r--r--tests/binder_test.cpp8
3 files changed, 34 insertions, 0 deletions
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index dca6bd98..86b23b6d 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -667,6 +667,19 @@ int RouteController::modifyVpnLocalExclusionRule(bool add, const char* physicalI
INVALID_UID);
}
+int RouteController::addFixedLocalRoutes(const char* interface) {
+ for (size_t i = 0; i < ARRAY_SIZE(V4_FIXED_LOCAL_PREFIXES); ++i) {
+ if (int ret = modifyRoute(RTM_NEWROUTE, NETLINK_ROUTE_CREATE_FLAGS, interface,
+ V4_FIXED_LOCAL_PREFIXES[i], nullptr /* nexthop */,
+ RouteController::INTERFACE, 0 /* mtu */, 0 /* priority */,
+ true /* isLocal */)) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
// A rule to enable split tunnel VPNs.
//
// If a packet with a VPN's netId doesn't find a route in the VPN's routing table, it's allowed to
@@ -1297,6 +1310,11 @@ int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* i
maybeModifyQdiscClsact(interface, ACTION_ADD);
updateTableNamesFile();
+
+ if (int ret = addFixedLocalRoutes(interface)) {
+ return ret;
+ }
+
return 0;
}
diff --git a/server/RouteController.h b/server/RouteController.h
index f57bc242..1b3a093a 100644
--- a/server/RouteController.h
+++ b/server/RouteController.h
@@ -85,6 +85,13 @@ constexpr int32_t RULE_PRIORITY_DEFAULT_NETWORK = 31000;
constexpr int32_t RULE_PRIORITY_UNREACHABLE = 32000;
// clang-format on
+static const char* V4_FIXED_LOCAL_PREFIXES[] = {
+ // The multicast range is 224.0.0.0/4 but only limit it to 224.0.0.0/24 since the IPv4
+ // definitions are not as precise as for IPv6, it is the only range that the standards
+ // (RFC 2365 and RFC 5771) specify is link-local and must not be forwarded.
+ "224.0.0.0/24" // Link-local multicast; non-internet routable
+};
+
class UidRanges;
class RouteController {
@@ -232,6 +239,7 @@ public:
bool add);
static bool isLocalRoute(TableType tableType, const char* destination, const char* nexthop);
static bool isWithinIpv4LocalPrefix(const char* addrstr);
+ static int addFixedLocalRoutes(const char* interface);
};
// Public because they are called by by RouteControllerTest.cpp.
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index d9d7cecc..02a750d2 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -136,6 +136,7 @@ using android::net::TetherStatsParcel;
using android::net::TunInterface;
using android::net::UidRangeParcel;
using android::net::UidRanges;
+using android::net::V4_FIXED_LOCAL_PREFIXES;
using android::net::mdns::aidl::DiscoveryInfo;
using android::net::mdns::aidl::GetAddressInfo;
using android::net::mdns::aidl::IMDns;
@@ -1700,6 +1701,13 @@ TEST_F(NetdBinderTest, NetworkAddRemoveRouteToLocalExcludeTable) {
EXPECT_TRUE(mNetd->networkSetDefault(TEST_NETID1).isOk());
std::string localTableName = std::string(sTun.name() + "_local");
+
+ // Verify the fixed routes exist in the local table.
+ for (size_t i = 0; i < std::size(V4_FIXED_LOCAL_PREFIXES); i++) {
+ expectNetworkRouteExists(IP_RULE_V4, sTun.name(), V4_FIXED_LOCAL_PREFIXES[i], "",
+ localTableName.c_str());
+ }
+
// Set up link-local routes for connectivity to the "gateway"
for (size_t i = 0; i < std::size(kDirectlyConnectedRoutes); i++) {
const auto& td = kDirectlyConnectedRoutes[i];