• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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