• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "netd_hidl_test"
18 
19 #include <linux/if.h>
20 
21 #include <android-base/stringprintf.h>
22 #include <android/system/net/netd/1.1/INetd.h>
23 #include <gtest/gtest.h>
24 #include <hidl/GtestPrinter.h>
25 #include <hidl/ServiceManagement.h>
26 #include <log/log.h>
27 #include <netutils/ifc.h>
28 
29 #include "VtsHalNetNetdTestUtils.h"
30 #include "tun_interface.h"
31 
32 using android::sp;
33 using android::base::StringPrintf;
34 using android::hardware::Return;
35 using android::net::TunInterface;
36 using android::system::net::netd::V1_1::INetd;
37 
38 namespace {
39 const net_handle_t INVALID_NET_HANDLE = 0x6600FACADE;
40 
41 constexpr const char* IPV4_ROUTER = "192.0.2.1";
42 constexpr const char* IPV4_CONNECTED = "192.0.2.0/25";
43 constexpr const char* IPV4_SUBNET_1 = "192.0.2.192/28";
44 constexpr const char* IPV4_HOST_1 = "192.0.2.195";
45 constexpr const char* IPV4_SUBNET_2 = "192.0.2.240/28";
46 constexpr const char* IPV4_HOST_2 = "192.0.2.245";
47 constexpr const char* IPV4_UNREACHABLE = "192.0.2.239";
48 
49 constexpr const char* IPV6_ROUTER = "2001:db8::cafe";
50 constexpr const char* IPV6_CONNECTED = "2001:db8::/64";
51 constexpr const char* IPV6_SUBNET_1 = "2001:db8:babe::/48";
52 constexpr const char* IPV6_HOST_1 = "2001:db8:babe::1";
53 constexpr const char* IPV6_SUBNET_2 = "2001:db8:d00d::/48";
54 constexpr const char* IPV6_HOST_2 = "2001:db8:d00d::1";
55 constexpr const char* IPV6_UNREACHABLE = "2001:db8:d0a::";
56 
57 std::vector<const char*> REACHABLE = {
58     IPV4_ROUTER, IPV4_HOST_1, IPV4_HOST_2, IPV6_ROUTER, IPV6_HOST_1, IPV6_HOST_2,
59 };
60 
checkAllReachable(net_handle_t handle)61 void checkAllReachable(net_handle_t handle) {
62     int ret;
63     for (const auto& dst : REACHABLE) {
64         ret = checkReachability(handle, dst);
65         EXPECT_EQ(0, ret) << "Expected reachability to " << dst << " but got %s" << strerror(-ret);
66     }
67     for (const auto& dst : {IPV4_UNREACHABLE, IPV6_UNREACHABLE}) {
68         EXPECT_EQ(-ENETUNREACH, checkReachability(handle, dst))
69             << "Expected " << dst << " to be unreachable, but was reachable";
70     }
71 }
72 
checkAllUnreachable(net_handle_t handle)73 void checkAllUnreachable(net_handle_t handle) {
74     for (const auto& dst : REACHABLE) {
75         EXPECT_EQ(-ENETUNREACH, checkReachability(handle, dst));
76     }
77     for (const auto& dst : {IPV4_UNREACHABLE, IPV6_UNREACHABLE}) {
78         EXPECT_EQ(-ENETUNREACH, checkReachability(handle, dst));
79     }
80 }
81 }  // namespace
82 
83 class NetdHidlTest : public ::testing::TestWithParam<std::string> {
84    public:
85     // Netd HAL instance.
86     sp<INetd> netd;
87 
88     // The nethandle of our test network, and its packet mark.
89     net_handle_t mNetHandle;
90     uint32_t mPacketMark;
91 
92     // Two interfaces that we can add and remove from our test network.
93     static TunInterface sTun1;
94     static TunInterface sTun2;
95 
96     // The interface name of sTun1, for convenience.
97     static const char* sIfaceName;
98 
SetUpTestCase()99     static void SetUpTestCase() {
100         ASSERT_EQ(0, sTun1.init());
101         ASSERT_EQ(0, sTun2.init());
102         ASSERT_LE(sTun1.name().size(), static_cast<size_t>(IFNAMSIZ));
103         ASSERT_LE(sTun2.name().size(), static_cast<size_t>(IFNAMSIZ));
104         ifc_init();
105         ASSERT_EQ(0, ifc_up(sTun1.name().c_str()));
106         ASSERT_EQ(0, ifc_up(sTun2.name().c_str()));
107         sIfaceName = sTun1.name().c_str();
108     }
109 
TearDownTestCase()110     static void TearDownTestCase() {
111         sTun1.destroy();
112         sTun2.destroy();
113         ifc_close();
114     }
115 
SetUp()116     virtual void SetUp() override {
117         netd = INetd::getService(GetParam());
118 
119         ASSERT_NE(netd, nullptr) << "Could not get HIDL instance";
120 
121         // Set up an OEM network.
122         INetd::StatusCode status;
123         Return<void> ret =
124             netd->createOemNetwork([&](net_handle_t n, uint32_t p, INetd::StatusCode s) {
125                 status = s;
126                 mNetHandle = n;
127                 mPacketMark = p;
128             });
129         ASSERT_TRUE(ret.isOk());
130         ASSERT_EQ(INetd::StatusCode::OK, status);
131         ASSERT_NE(NETWORK_UNSPECIFIED, mNetHandle);
132         ASSERT_NE((uint32_t)0, mPacketMark);
133     }
134 
TearDown()135     virtual void TearDown() override { netd->destroyOemNetwork(mNetHandle); }
136 
expectAddRoute(INetd::StatusCode expectedStatus,net_handle_t handle,const char * iface,const char * destination,const char * nexthop)137     void expectAddRoute(INetd::StatusCode expectedStatus, net_handle_t handle, const char* iface,
138                         const char* destination, const char* nexthop) {
139         Return<INetd::StatusCode> retStatus =
140             netd->addRouteToOemNetwork(handle, iface, destination, nexthop);
141         EXPECT_STATUS(expectedStatus, retStatus);
142     }
143 
expectAddRouteSuccess(net_handle_t h,const char * i,const char * d,const char * n)144     void expectAddRouteSuccess(net_handle_t h, const char* i, const char* d, const char* n) {
145         expectAddRoute(INetd::StatusCode::OK, h, i, d, n);
146     }
147 
expectRemoveRoute(INetd::StatusCode expectedStatus,net_handle_t handle,const char * iface,const char * destination,const char * nexthop)148     void expectRemoveRoute(INetd::StatusCode expectedStatus, net_handle_t handle, const char* iface,
149                            const char* destination, const char* nexthop) {
150         Return<INetd::StatusCode> retStatus =
151             netd->removeRouteFromOemNetwork(handle, iface, destination, nexthop);
152         EXPECT_STATUS(expectedStatus, retStatus);
153     }
154 
expectRemoveRouteSuccess(net_handle_t h,const char * i,const char * d,const char * n)155     void expectRemoveRouteSuccess(net_handle_t h, const char* i, const char* d, const char* n) {
156         expectRemoveRoute(INetd::StatusCode::OK, h, i, d, n);
157     }
158 };
159 
160 TunInterface NetdHidlTest::sTun1;
161 TunInterface NetdHidlTest::sTun2;
162 const char* NetdHidlTest::sIfaceName;
163 
164 // Tests adding and removing interfaces from the OEM network.
TEST_P(NetdHidlTest,TestAddRemoveInterfaces)165 TEST_P(NetdHidlTest, TestAddRemoveInterfaces) {
166     // HACK: mark out permissions bits.
167     uint32_t packetMark = mPacketMark & 0xffff;
168 
169     EXPECT_EQ(0, checkNetworkExists(mNetHandle));
170     EXPECT_EQ(0, countRulesForFwmark(packetMark));
171 
172     // Adding an interface creates the routing rules.
173     Return<INetd::StatusCode> retStatus = netd->addInterfaceToOemNetwork(mNetHandle, sIfaceName);
174     EXPECT_TRUE(retStatus.isOk());
175     EXPECT_EQ(0, checkNetworkExists(mNetHandle));
176     EXPECT_EQ(2, countRulesForFwmark(packetMark));
177 
178     // Adding an interface again silently succeeds.
179     retStatus = netd->addInterfaceToOemNetwork(mNetHandle, sIfaceName);
180     EXPECT_TRUE(retStatus.isOk());
181     EXPECT_EQ(0, checkNetworkExists(mNetHandle));
182     EXPECT_EQ(2, countRulesForFwmark(packetMark));
183 
184     // More than one network can be created.
185     net_handle_t netHandle2;
186     uint32_t packetMark2;
187 
188     Return<void> ret = netd->createOemNetwork([&](net_handle_t n, uint32_t p, INetd::StatusCode) {
189         netHandle2 = n;
190         packetMark2 = p & 0xffff;
191     });
192     EXPECT_TRUE(ret.isOk());
193     EXPECT_NE(mNetHandle, netHandle2);
194     EXPECT_NE(packetMark, packetMark2);
195     EXPECT_EQ(0, checkNetworkExists(netHandle2));
196     EXPECT_EQ(0, countRulesForFwmark(packetMark2));
197 
198     // An interface can only be in one network.
199     retStatus = netd->addInterfaceToOemNetwork(netHandle2, sIfaceName);
200     EXPECT_STATUS(INetd::StatusCode::UNKNOWN_ERROR, retStatus);
201 
202     // Removing the interface removes the rules.
203     retStatus = netd->removeInterfaceFromOemNetwork(mNetHandle, sIfaceName);
204     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
205     EXPECT_EQ(0, countRulesForFwmark(packetMark));
206 
207     retStatus = netd->addInterfaceToOemNetwork(netHandle2, sIfaceName);
208     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
209     EXPECT_EQ(2, countRulesForFwmark(packetMark2));
210 
211     // When a network is removed the interfaces are deleted.
212     retStatus = netd->destroyOemNetwork(netHandle2);
213     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
214     EXPECT_EQ(-ENONET, checkNetworkExists(netHandle2));
215     EXPECT_EQ(0, countRulesForFwmark(packetMark2));
216 
217     // Adding an interface to a non-existent network fails.
218     retStatus = netd->addInterfaceToOemNetwork(INVALID_NET_HANDLE, sIfaceName);
219     EXPECT_STATUS(INetd::StatusCode::INVALID_ARGUMENTS, retStatus);
220     retStatus = netd->removeInterfaceFromOemNetwork(INVALID_NET_HANDLE, sIfaceName);
221     EXPECT_STATUS(INetd::StatusCode::INVALID_ARGUMENTS, retStatus);
222 }
223 
224 // Tests adding and removing routes from the OEM network.
TEST_P(NetdHidlTest,TestAddRemoveRoutes)225 TEST_P(NetdHidlTest, TestAddRemoveRoutes) {
226     Return<INetd::StatusCode> retStatus = netd->addInterfaceToOemNetwork(mNetHandle, sIfaceName);
227     ASSERT_TRUE(retStatus.isOk());
228 
229     // Network exists, but has no routes and no connectivity.
230     EXPECT_EQ(0, checkNetworkExists(mNetHandle));
231     checkAllUnreachable(mNetHandle);
232 
233     // Add a directly-connected route and two gatewayed routes through it.
234     expectAddRouteSuccess(mNetHandle, sIfaceName, IPV4_CONNECTED, "");
235     expectAddRouteSuccess(mNetHandle, sIfaceName, IPV4_SUBNET_1, IPV4_ROUTER);
236     expectAddRouteSuccess(mNetHandle, sIfaceName, IPV4_SUBNET_2, IPV4_ROUTER);
237     expectAddRouteSuccess(mNetHandle, sIfaceName, IPV6_CONNECTED, "");
238     expectAddRouteSuccess(mNetHandle, sIfaceName, IPV6_SUBNET_1, IPV6_ROUTER);
239     expectAddRouteSuccess(mNetHandle, sIfaceName, IPV6_SUBNET_2, IPV6_ROUTER);
240 
241     // Test some destinations.
242     checkAllReachable(mNetHandle);
243 
244     // Remove the directly-connected routes and everything is unreachable again.
245     expectRemoveRouteSuccess(mNetHandle, sIfaceName, IPV4_CONNECTED, "");
246     expectRemoveRouteSuccess(mNetHandle, sIfaceName, IPV6_CONNECTED, "");
247     expectRemoveRouteSuccess(mNetHandle, sIfaceName, IPV4_SUBNET_1, IPV4_ROUTER);
248     expectRemoveRouteSuccess(mNetHandle, sIfaceName, IPV4_SUBNET_2, IPV4_ROUTER);
249     expectRemoveRouteSuccess(mNetHandle, sIfaceName, IPV6_SUBNET_1, IPV6_ROUTER);
250     expectRemoveRouteSuccess(mNetHandle, sIfaceName, IPV6_SUBNET_2, IPV6_ROUTER);
251 
252     checkAllUnreachable(mNetHandle);
253 
254     // Invalid: route doesn't exist so can't be deleted.
255     expectRemoveRoute(INetd::StatusCode::UNKNOWN_ERROR, mNetHandle, sIfaceName, IPV4_CONNECTED, "");
256 
257     // Invalid: IP address instead of prefix.
258     expectAddRoute(INetd::StatusCode::INVALID_ARGUMENTS, mNetHandle, sIfaceName, IPV4_HOST_1, "");
259     expectAddRoute(INetd::StatusCode::INVALID_ARGUMENTS, mNetHandle, sIfaceName, IPV6_HOST_1, "");
260 
261     // Invalid: both nexthop and interface are empty.
262     expectAddRoute(INetd::StatusCode::UNKNOWN_ERROR, mNetHandle, "", IPV4_SUBNET_1, "");
263     expectAddRoute(INetd::StatusCode::UNKNOWN_ERROR, mNetHandle, "", IPV6_SUBNET_1, "");
264 
265     // The kernel deletes the routes when the interfaces go away.
266 }
267 
268 // Tests enabling and disabling forwarding between interfaces.
TEST_P(NetdHidlTest,TestForwarding)269 TEST_P(NetdHidlTest, TestForwarding) {
270     Return<INetd::StatusCode> retStatus =
271         netd->addInterfaceToOemNetwork(mNetHandle, sTun1.name().c_str());
272     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
273     retStatus = netd->addInterfaceToOemNetwork(mNetHandle, sTun2.name().c_str());
274     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
275 
276     // TODO: move this test to netd and use ROUTE_TABLE_OFFSET_FROM_INDEX directly.
277     uint32_t table1 = 1000 + sTun1.ifindex();
278     uint32_t table2 = 1000 + sTun1.ifindex();
279     const char* regexTemplate = "from all iif %s .*lookup (%s|%d)";
280     std::string regex1 =
281         StringPrintf(regexTemplate, sTun1.name().c_str(), sTun2.name().c_str(), table2);
282     std::string regex2 =
283         StringPrintf(regexTemplate, sTun2.name().c_str(), sTun1.name().c_str(), table1);
284 
285     EXPECT_EQ(0, countMatchingIpRules(regex1));
286     EXPECT_EQ(0, countMatchingIpRules(regex2));
287 
288     retStatus = netd->setForwardingBetweenInterfaces(sTun1.name(), sTun2.name(), true);
289     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
290     EXPECT_EQ(2, countMatchingIpRules(regex1));
291     EXPECT_EQ(0, countMatchingIpRules(regex2));
292 
293     // No attempt at deduplicating rules is made.
294     retStatus = netd->setForwardingBetweenInterfaces(sTun1.name(), sTun2.name(), true);
295     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
296     EXPECT_EQ(4, countMatchingIpRules(regex1));
297 
298     retStatus = netd->setForwardingBetweenInterfaces(sTun1.name(), sTun2.name(), false);
299     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
300     EXPECT_EQ(2, countMatchingIpRules(regex1));
301 
302     retStatus = netd->setForwardingBetweenInterfaces(sTun2.name(), sTun1.name(), true);
303     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
304     EXPECT_EQ(2, countMatchingIpRules(regex1));
305     EXPECT_EQ(2, countMatchingIpRules(regex2));
306 
307     retStatus = netd->setForwardingBetweenInterfaces(sTun1.name(), sTun2.name(), false);
308     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
309     EXPECT_EQ(0, countMatchingIpRules(regex1));
310     EXPECT_EQ(2, countMatchingIpRules(regex2));
311 
312     retStatus = netd->setForwardingBetweenInterfaces(sTun2.name(), sTun1.name(), false);
313     EXPECT_STATUS(INetd::StatusCode::OK, retStatus);
314     EXPECT_EQ(0, countMatchingIpRules(regex1));
315     EXPECT_EQ(0, countMatchingIpRules(regex2));
316 
317     // Deleting rules that don't exist fails.
318     retStatus = netd->setForwardingBetweenInterfaces(sTun1.name(), sTun2.name(), false);
319     EXPECT_STATUS(INetd::StatusCode::UNKNOWN_ERROR, retStatus);
320     EXPECT_EQ(0, countMatchingIpRules(regex1));
321     EXPECT_EQ(0, countMatchingIpRules(regex2));
322 }
323 
324 INSTANTIATE_TEST_SUITE_P(
325     PerInstance, NetdHidlTest,
326     testing::ValuesIn(android::hardware::getAllHalInstanceNames(INetd::descriptor)),
327     android::hardware::PrintInstanceNameToString);
328