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