xref: /aosp_15_r20/system/netd/server/RouteControllerTest.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker  * Copyright 2017 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker  *
4*8542734aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker  *
8*8542734aSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker  *
10*8542734aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker  * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker  *
16*8542734aSAndroid Build Coastguard Worker  * RouteControllerTest.cpp - unit tests for RouteController.cpp
17*8542734aSAndroid Build Coastguard Worker  */
18*8542734aSAndroid Build Coastguard Worker 
19*8542734aSAndroid Build Coastguard Worker #include <gtest/gtest.h>
20*8542734aSAndroid Build Coastguard Worker #include <fstream>
21*8542734aSAndroid Build Coastguard Worker 
22*8542734aSAndroid Build Coastguard Worker #include "Fwmark.h"
23*8542734aSAndroid Build Coastguard Worker #include "IptablesBaseTest.h"
24*8542734aSAndroid Build Coastguard Worker #include "NetlinkCommands.h"
25*8542734aSAndroid Build Coastguard Worker #include "RouteController.h"
26*8542734aSAndroid Build Coastguard Worker 
27*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
28*8542734aSAndroid Build Coastguard Worker 
29*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
30*8542734aSAndroid Build Coastguard Worker 
31*8542734aSAndroid Build Coastguard Worker static const char* TEST_IFACE1 = "netdtest1";
32*8542734aSAndroid Build Coastguard Worker static const char* TEST_IFACE2 = "netdtest2";
33*8542734aSAndroid Build Coastguard Worker static const uint32_t TEST_IFACE1_INDEX = 901;
34*8542734aSAndroid Build Coastguard Worker static const uint32_t TEST_IFACE2_INDEX = 902;
35*8542734aSAndroid Build Coastguard Worker // See Linux kernel source in include/net/flow.h
36*8542734aSAndroid Build Coastguard Worker #define LOOPBACK_IFINDEX 1
37*8542734aSAndroid Build Coastguard Worker 
38*8542734aSAndroid Build Coastguard Worker namespace android {
39*8542734aSAndroid Build Coastguard Worker namespace net {
40*8542734aSAndroid Build Coastguard Worker 
41*8542734aSAndroid Build Coastguard Worker class RouteControllerTest : public IptablesBaseTest {
42*8542734aSAndroid Build Coastguard Worker public:
RouteControllerTest()43*8542734aSAndroid Build Coastguard Worker     RouteControllerTest() {
44*8542734aSAndroid Build Coastguard Worker         RouteController::iptablesRestoreCommandFunction = fakeExecIptablesRestoreCommand;
45*8542734aSAndroid Build Coastguard Worker         RouteController::ifNameToIndexFunction = fakeIfaceNameToIndexFunction;
46*8542734aSAndroid Build Coastguard Worker     }
47*8542734aSAndroid Build Coastguard Worker 
flushRoutes(uint32_t a)48*8542734aSAndroid Build Coastguard Worker     int flushRoutes(uint32_t a) {
49*8542734aSAndroid Build Coastguard Worker         return RouteController::flushRoutes(a);
50*8542734aSAndroid Build Coastguard Worker     }
51*8542734aSAndroid Build Coastguard Worker 
fakeIfaceNameToIndexFunction(const char * iface)52*8542734aSAndroid Build Coastguard Worker     uint32_t static fakeIfaceNameToIndexFunction(const char* iface) {
53*8542734aSAndroid Build Coastguard Worker         // "lo" is the same as the real one
54*8542734aSAndroid Build Coastguard Worker         if (!strcmp(iface, "lo")) return LOOPBACK_IFINDEX;
55*8542734aSAndroid Build Coastguard Worker         if (!strcmp(iface, TEST_IFACE1)) return TEST_IFACE1_INDEX;
56*8542734aSAndroid Build Coastguard Worker         if (!strcmp(iface, TEST_IFACE2)) return TEST_IFACE2_INDEX;
57*8542734aSAndroid Build Coastguard Worker         return 0;
58*8542734aSAndroid Build Coastguard Worker     }
59*8542734aSAndroid Build Coastguard Worker };
60*8542734aSAndroid Build Coastguard Worker 
TEST_F(RouteControllerTest,TestGetRulePriority)61*8542734aSAndroid Build Coastguard Worker TEST_F(RouteControllerTest, TestGetRulePriority) {
62*8542734aSAndroid Build Coastguard Worker     // Expect a rule dump for these two families to contain at least the following priorities.
63*8542734aSAndroid Build Coastguard Worker     for (int family : {AF_INET, AF_INET6 }) {
64*8542734aSAndroid Build Coastguard Worker         std::set<uint32_t> expectedPriorities = {
65*8542734aSAndroid Build Coastguard Worker                 0,
66*8542734aSAndroid Build Coastguard Worker                 RULE_PRIORITY_LEGACY_SYSTEM,
67*8542734aSAndroid Build Coastguard Worker                 RULE_PRIORITY_LEGACY_NETWORK,
68*8542734aSAndroid Build Coastguard Worker                 RULE_PRIORITY_UNREACHABLE,
69*8542734aSAndroid Build Coastguard Worker         };
70*8542734aSAndroid Build Coastguard Worker 
71*8542734aSAndroid Build Coastguard Worker         NetlinkDumpCallback callback = [&expectedPriorities] (const nlmsghdr *nlh) {
72*8542734aSAndroid Build Coastguard Worker             expectedPriorities.erase(getRulePriority(nlh));
73*8542734aSAndroid Build Coastguard Worker         };
74*8542734aSAndroid Build Coastguard Worker 
75*8542734aSAndroid Build Coastguard Worker         rtmsg rtm = { .rtm_family = static_cast<uint8_t>(family) };
76*8542734aSAndroid Build Coastguard Worker         iovec iov[] = {
77*8542734aSAndroid Build Coastguard Worker             { nullptr, 0           },
78*8542734aSAndroid Build Coastguard Worker             { &rtm,    sizeof(rtm) },
79*8542734aSAndroid Build Coastguard Worker         };
80*8542734aSAndroid Build Coastguard Worker 
81*8542734aSAndroid Build Coastguard Worker         ASSERT_EQ(0, sendNetlinkRequest(RTM_GETRULE, NETLINK_DUMP_FLAGS,
82*8542734aSAndroid Build Coastguard Worker                                         iov, ARRAY_SIZE(iov), &callback));
83*8542734aSAndroid Build Coastguard Worker 
84*8542734aSAndroid Build Coastguard Worker         EXPECT_TRUE(expectedPriorities.empty()) <<
85*8542734aSAndroid Build Coastguard Worker             "Did not see rule with priority " << *expectedPriorities.begin() <<
86*8542734aSAndroid Build Coastguard Worker             " in dump for address family " << family;
87*8542734aSAndroid Build Coastguard Worker     }
88*8542734aSAndroid Build Coastguard Worker }
89*8542734aSAndroid Build Coastguard Worker 
TEST_F(RouteControllerTest,TestRouteFlush)90*8542734aSAndroid Build Coastguard Worker TEST_F(RouteControllerTest, TestRouteFlush) {
91*8542734aSAndroid Build Coastguard Worker     // Pick a table number that's not used by the system.
92*8542734aSAndroid Build Coastguard Worker     const uint32_t table1 = 500;
93*8542734aSAndroid Build Coastguard Worker     const uint32_t table2 = 600;
94*8542734aSAndroid Build Coastguard Worker     static_assert(table1 < RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX,
95*8542734aSAndroid Build Coastguard Worker                   "Test table1 number too large");
96*8542734aSAndroid Build Coastguard Worker     static_assert(table2 < RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX,
97*8542734aSAndroid Build Coastguard Worker                   "Test table2 number too large");
98*8542734aSAndroid Build Coastguard Worker 
99*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, modifyIpRoute(RTM_NEWROUTE, NETLINK_ROUTE_CREATE_FLAGS, table1, "lo",
100*8542734aSAndroid Build Coastguard Worker                                "192.0.2.2/32", nullptr, 0 /* mtu */, 0 /* priority */));
101*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, modifyIpRoute(RTM_NEWROUTE, NETLINK_ROUTE_CREATE_FLAGS, table1, "lo",
102*8542734aSAndroid Build Coastguard Worker                                "192.0.2.3/32", nullptr, 0 /* mtu */, 0 /* priority */));
103*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, modifyIpRoute(RTM_NEWROUTE, NETLINK_ROUTE_CREATE_FLAGS, table2, "lo",
104*8542734aSAndroid Build Coastguard Worker                                "192.0.2.4/32", nullptr, 0 /* mtu */, 0 /* priority */));
105*8542734aSAndroid Build Coastguard Worker 
106*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, flushRoutes(table1));
107*8542734aSAndroid Build Coastguard Worker 
108*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-ESRCH, modifyIpRoute(RTM_DELROUTE, NETLINK_REQUEST_FLAGS, table1, "lo",
109*8542734aSAndroid Build Coastguard Worker                                     "192.0.2.2/32", nullptr, 0 /* mtu */, 0 /* priority */));
110*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-ESRCH, modifyIpRoute(RTM_DELROUTE, NETLINK_REQUEST_FLAGS, table1, "lo",
111*8542734aSAndroid Build Coastguard Worker                                     "192.0.2.3/32", nullptr, 0 /* mtu */, 0 /* priority */));
112*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, modifyIpRoute(RTM_DELROUTE, NETLINK_REQUEST_FLAGS, table2, "lo",
113*8542734aSAndroid Build Coastguard Worker                                "192.0.2.4/32", nullptr, 0 /* mtu */, 0 /* priority */));
114*8542734aSAndroid Build Coastguard Worker }
115*8542734aSAndroid Build Coastguard Worker 
TEST_F(RouteControllerTest,TestModifyIncomingPacketMark)116*8542734aSAndroid Build Coastguard Worker TEST_F(RouteControllerTest, TestModifyIncomingPacketMark) {
117*8542734aSAndroid Build Coastguard Worker   uint32_t mask = Fwmark::getUidBillingMask() | Fwmark::getIngressCpuWakeupMask();
118*8542734aSAndroid Build Coastguard Worker 
119*8542734aSAndroid Build Coastguard Worker   static constexpr int TEST_NETID = 30;
120*8542734aSAndroid Build Coastguard Worker   EXPECT_EQ(0, modifyIncomingPacketMark(TEST_NETID, "netdtest0",
121*8542734aSAndroid Build Coastguard Worker                                         PERMISSION_NONE, true));
122*8542734aSAndroid Build Coastguard Worker   expectIptablesRestoreCommands({StringPrintf(
123*8542734aSAndroid Build Coastguard Worker       "-t mangle -A routectrl_mangle_INPUT -i netdtest0 -j MARK --set-mark "
124*8542734aSAndroid Build Coastguard Worker       "0x3001e/0x%x",
125*8542734aSAndroid Build Coastguard Worker       ~mask)});
126*8542734aSAndroid Build Coastguard Worker 
127*8542734aSAndroid Build Coastguard Worker   EXPECT_EQ(0, modifyIncomingPacketMark(TEST_NETID, "netdtest0",
128*8542734aSAndroid Build Coastguard Worker                                         PERMISSION_NONE, false));
129*8542734aSAndroid Build Coastguard Worker   expectIptablesRestoreCommands({StringPrintf(
130*8542734aSAndroid Build Coastguard Worker       "-t mangle -D routectrl_mangle_INPUT -i netdtest0 -j MARK --set-mark "
131*8542734aSAndroid Build Coastguard Worker       "0x3001e/0x%x",
132*8542734aSAndroid Build Coastguard Worker       ~mask)});
133*8542734aSAndroid Build Coastguard Worker }
134*8542734aSAndroid Build Coastguard Worker 
hasLocalInterfaceInRouteTable(const char * iface)135*8542734aSAndroid Build Coastguard Worker bool hasLocalInterfaceInRouteTable(const char* iface) {
136*8542734aSAndroid Build Coastguard Worker     // Calculate the table index from interface index
137*8542734aSAndroid Build Coastguard Worker     std::string index = std::to_string(RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX_FOR_LOCAL +
138*8542734aSAndroid Build Coastguard Worker                                        RouteController::ifNameToIndexFunction(iface));
139*8542734aSAndroid Build Coastguard Worker     std::string localIface =
140*8542734aSAndroid Build Coastguard Worker             index + " " + std::string(iface) + std::string(RouteController::INTERFACE_LOCAL_SUFFIX);
141*8542734aSAndroid Build Coastguard Worker     std::string line;
142*8542734aSAndroid Build Coastguard Worker 
143*8542734aSAndroid Build Coastguard Worker     std::ifstream input(RouteController::RT_TABLES_PATH);
144*8542734aSAndroid Build Coastguard Worker     while (std::getline(input, line)) {
145*8542734aSAndroid Build Coastguard Worker         if (line.find(localIface) != std::string::npos) {
146*8542734aSAndroid Build Coastguard Worker             return true;
147*8542734aSAndroid Build Coastguard Worker         }
148*8542734aSAndroid Build Coastguard Worker     }
149*8542734aSAndroid Build Coastguard Worker 
150*8542734aSAndroid Build Coastguard Worker     return false;
151*8542734aSAndroid Build Coastguard Worker }
152*8542734aSAndroid Build Coastguard Worker 
TEST_F(RouteControllerTest,TestCreateVirtualLocalInterfaceTable)153*8542734aSAndroid Build Coastguard Worker TEST_F(RouteControllerTest, TestCreateVirtualLocalInterfaceTable) {
154*8542734aSAndroid Build Coastguard Worker     static constexpr int TEST_NETID = 65500;
155*8542734aSAndroid Build Coastguard Worker     std::map<int32_t, UidRanges> uidRangeMap;
156*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, RouteController::addInterfaceToVirtualNetwork(TEST_NETID, TEST_IFACE1, false,
157*8542734aSAndroid Build Coastguard Worker                                                                uidRangeMap, false));
158*8542734aSAndroid Build Coastguard Worker     // Expect to create <iface>_local in the routing table
159*8542734aSAndroid Build Coastguard Worker     EXPECT_TRUE(hasLocalInterfaceInRouteTable(TEST_IFACE1));
160*8542734aSAndroid Build Coastguard Worker     // Add another interface, <TEST_IFACE2>_local should also be created
161*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, RouteController::addInterfaceToVirtualNetwork(TEST_NETID, TEST_IFACE2, false,
162*8542734aSAndroid Build Coastguard Worker                                                                uidRangeMap, false));
163*8542734aSAndroid Build Coastguard Worker     EXPECT_TRUE(hasLocalInterfaceInRouteTable(TEST_IFACE2));
164*8542734aSAndroid Build Coastguard Worker     // Remove TEST_IFACE1
165*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, RouteController::removeInterfaceFromVirtualNetwork(TEST_NETID, TEST_IFACE1, false,
166*8542734aSAndroid Build Coastguard Worker                                                                     uidRangeMap, false));
167*8542734aSAndroid Build Coastguard Worker     // Interface remove should also remove the virtual local interface for routing table
168*8542734aSAndroid Build Coastguard Worker     EXPECT_FALSE(hasLocalInterfaceInRouteTable(TEST_IFACE1));
169*8542734aSAndroid Build Coastguard Worker     // <TEST_IFACE2> should still in the routing table
170*8542734aSAndroid Build Coastguard Worker     EXPECT_TRUE(hasLocalInterfaceInRouteTable(TEST_IFACE2));
171*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, RouteController::removeInterfaceFromVirtualNetwork(TEST_NETID, TEST_IFACE2, false,
172*8542734aSAndroid Build Coastguard Worker                                                                     uidRangeMap, false));
173*8542734aSAndroid Build Coastguard Worker     EXPECT_FALSE(hasLocalInterfaceInRouteTable(TEST_IFACE2));
174*8542734aSAndroid Build Coastguard Worker }
175*8542734aSAndroid Build Coastguard Worker 
176*8542734aSAndroid Build Coastguard Worker }  // namespace net
177*8542734aSAndroid Build Coastguard Worker }  // namespace android
178