1 /*
2 * Copyright (C) 2021 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 #include <aidl/Gtest.h>
18 #include <aidl/Vintf.h>
19 #include <aidl/android/hardware/net/nlinterceptor/IInterceptor.h>
20 #include <android-base/logging.h>
21 #include <android/binder_manager.h>
22 #include <gtest/gtest.h>
23 #include <libnetdevice/libnetdevice.h>
24 #include <libnl++/MessageFactory.h>
25 #include <libnl++/Socket.h>
26 #include <libnl++/printer.h>
27 #include <linux/netlink.h>
28 #include <linux/rtnetlink.h>
29
30 #include <chrono>
31 #include <thread>
32
33 using aidl::android::hardware::net::nlinterceptor::IInterceptor;
34 using AidlInterceptedSocket =
35 ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
36 using namespace std::chrono_literals;
37 using namespace std::string_literals;
38
39 class InterceptorAidlTest : public ::testing::TestWithParam<std::string> {
40 public:
SetUp()41 virtual void SetUp() override {
42 android::base::SetDefaultTag("InterceptorAidlTest");
43 android::base::SetMinimumLogSeverity(android::base::VERBOSE);
44 const auto instance = IInterceptor::descriptor + "/default"s;
45 mNlInterceptorService = IInterceptor::fromBinder(
46 ndk::SpAIBinder(AServiceManager_getService(instance.c_str())));
47
48 ASSERT_NE(mNlInterceptorService, nullptr);
49 mSocket = std::make_unique<android::nl::Socket>(NETLINK_ROUTE);
50 ASSERT_TRUE(mSocket->getPid().has_value());
51
52 // If the test broke last run, clean up our mess, don't worry about "no
53 // such device".
54 if (android::netdevice::del(mTestIfaceName)) {
55 LOG(WARNING) << "Test interface wasn't cleaned up on previous run!";
56 }
57 }
58
59 void multicastReceiver();
60
61 std::shared_ptr<IInterceptor> mNlInterceptorService;
62 std::unique_ptr<android::nl::Socket> mSocket;
63 bool mRunning;
64 bool mGotMulticast;
65 const std::string mTestIfaceName = "interceptorvts0";
66 };
67
TEST_P(InterceptorAidlTest,createSocketTest)68 TEST_P(InterceptorAidlTest, createSocketTest) {
69 // Ask IInterceptor for a socket.
70 AidlInterceptedSocket interceptedSocket;
71 auto aidlStatus = mNlInterceptorService->createSocket(
72 NETLINK_ROUTE, *(mSocket->getPid()), "createSocketTest",
73 &interceptedSocket);
74 ASSERT_TRUE(aidlStatus.isOk());
75 ASSERT_NE(interceptedSocket.portId, 0);
76 uint32_t interceptorPid = interceptedSocket.portId;
77
78 // Ask the kernel to tell us what interfaces are available.
79 android::nl::MessageFactory<rtgenmsg> req(RTM_GETLINK,
80 NLM_F_REQUEST | NLM_F_DUMP);
81 req->rtgen_family = AF_PACKET;
82 sockaddr_nl sa = {.nl_family = AF_NETLINK,
83 .nl_pad = 0,
84 .nl_pid = interceptorPid,
85 .nl_groups = 0};
86 EXPECT_TRUE(mSocket->send(req, sa));
87
88 // We'll likely get back several messages, as indicated by the MULTI flag.
89 unsigned received = 0;
90 for (const auto msg : *mSocket) {
91 ASSERT_NE(msg->nlmsg_type, NLMSG_ERROR);
92 ++received;
93 break;
94 if (msg->nlmsg_type == NLMSG_DONE) {
95 // TODO(202548749): NLMSG_DONE on NETLINK_ROUTE doesn't work?
96 break;
97 }
98 }
99 ASSERT_GE(received, 1);
100
101 // Close the socket and make sure it's stopped working.
102 aidlStatus = mNlInterceptorService->closeSocket(interceptedSocket);
103 EXPECT_TRUE(aidlStatus.isOk());
104 EXPECT_FALSE(mSocket->send(req, sa));
105 }
106
isSocketReadable(const short revents)107 static bool isSocketReadable(const short revents) {
108 return 0 != (revents & POLLIN);
109 }
110
isSocketBad(const short revents)111 static bool isSocketBad(const short revents) {
112 return 0 != (revents & (POLLERR | POLLHUP | POLLNVAL));
113 }
114
multicastReceiver()115 void InterceptorAidlTest::multicastReceiver() {
116 pollfd fds[] = {
117 mSocket->preparePoll(POLLIN),
118 };
119 while (mRunning) {
120 if (poll(fds, 1, 300) < 0) {
121 PLOG(FATAL) << "poll failed";
122 return;
123 }
124 const auto nlsockEvents = fds[0].revents;
125 ASSERT_FALSE(isSocketBad(nlsockEvents));
126 if (!isSocketReadable(nlsockEvents)) continue;
127
128 const auto [msgMaybe, sa] = mSocket->receiveFrom();
129 ASSERT_TRUE(msgMaybe.has_value());
130 auto msg = *msgMaybe;
131
132 // Multicast messages have 0 for their pid and sequence number.
133 if (msg->nlmsg_pid == 0 && msg->nlmsg_seq == 0) {
134 mGotMulticast = true;
135 }
136 }
137 }
138
TEST_P(InterceptorAidlTest,subscribeGroupTest)139 TEST_P(InterceptorAidlTest, subscribeGroupTest) {
140 // Ask IInterceptor for a socket.
141 AidlInterceptedSocket interceptedSocket;
142 auto aidlStatus = mNlInterceptorService->createSocket(
143 NETLINK_ROUTE, *(mSocket->getPid()), "subscribeGroupTest",
144 &interceptedSocket);
145 ASSERT_TRUE(aidlStatus.isOk());
146 ASSERT_TRUE(interceptedSocket.portId != 0);
147
148 // Listen for interface up/down events.
149 aidlStatus =
150 mNlInterceptorService->subscribeGroup(interceptedSocket, RTNLGRP_LINK);
151 ASSERT_TRUE(aidlStatus.isOk());
152
153 // Start a thread to receive a multicast
154 mRunning = true;
155 mGotMulticast = false;
156 std::thread successfulReceiver(&InterceptorAidlTest::multicastReceiver,
157 this);
158
159 // TODO(201695162): use futures with wait_for instead of a sleep_for().
160 std::this_thread::sleep_for(50ms);
161 // create a network interface and bring it up to trigger a multicast event.
162 ASSERT_TRUE(android::netdevice::add(mTestIfaceName, /*type=*/"dummy"));
163 ASSERT_TRUE(android::netdevice::up(mTestIfaceName));
164 std::this_thread::sleep_for(50ms);
165 EXPECT_TRUE(mGotMulticast);
166 mRunning = false;
167 successfulReceiver.join();
168
169 // Stop listening to interface up/down events.
170 aidlStatus = mNlInterceptorService->unsubscribeGroup(interceptedSocket,
171 RTNLGRP_LINK);
172 ASSERT_TRUE(aidlStatus.isOk());
173
174 // This time, we should hear nothing.
175 mGotMulticast = false;
176 mRunning = true;
177 std::thread unsuccessfulReceiver(&InterceptorAidlTest::multicastReceiver,
178 this);
179 std::this_thread::sleep_for(50ms);
180 ASSERT_TRUE(android::netdevice::down(mTestIfaceName));
181 ASSERT_TRUE(android::netdevice::del(mTestIfaceName));
182 std::this_thread::sleep_for(50ms);
183 EXPECT_FALSE(mGotMulticast);
184 mRunning = false;
185 unsuccessfulReceiver.join();
186
187 aidlStatus = mNlInterceptorService->closeSocket(interceptedSocket);
188 EXPECT_TRUE(aidlStatus.isOk());
189 }
190
191 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InterceptorAidlTest);
192 INSTANTIATE_TEST_SUITE_P(PerInstance, InterceptorAidlTest,
193 testing::ValuesIn(android::getAidlHalInstanceNames(
194 IInterceptor::descriptor)),
195 android::PrintInstanceNameToString);
196