• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 "VtsOffloadConfigV1_0TargetTest"
18 
19 #include <VtsHalHidlTargetTestBase.h>
20 #include <VtsHalHidlTargetTestEnvBase.h>
21 #include <android-base/stringprintf.h>
22 #include <android-base/unique_fd.h>
23 #include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
24 #include <linux/netfilter/nfnetlink.h>
25 #include <linux/netlink.h>
26 #include <linux/rtnetlink.h>
27 #include <log/log.h>
28 #include <sys/socket.h>
29 #include <unistd.h>
30 #include <set>
31 
32 using android::base::StringPrintf;
33 using android::base::unique_fd;
34 using android::hardware::hidl_handle;
35 using android::hardware::hidl_string;
36 using android::hardware::Return;
37 using android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
38 using android::hardware::Void;
39 using android::sp;
40 
41 #define ASSERT_TRUE_CALLBACK \
42     [&](bool success, const hidl_string& errMsg) { ASSERT_TRUE(success) << errMsg.c_str(); }
43 
44 #define ASSERT_FALSE_CALLBACK \
45     [&](bool success, const hidl_string& errMsg) { ASSERT_FALSE(success) << errMsg.c_str(); }
46 
47 const unsigned kFd1Groups = NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY;
48 const unsigned kFd2Groups = NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY;
49 
asSockaddr(const sockaddr_nl * nladdr)50 inline const sockaddr* asSockaddr(const sockaddr_nl* nladdr) {
51     return reinterpret_cast<const sockaddr*>(nladdr);
52 }
53 
netlinkSocket(int protocol,unsigned groups)54 int netlinkSocket(int protocol, unsigned groups) {
55     unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, protocol));
56     if (s.get() < 0) {
57         return -errno;
58     }
59 
60     const struct sockaddr_nl bind_addr = {
61         .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
62     };
63     if (::bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
64         return -errno;
65     }
66 
67     const struct sockaddr_nl kernel_addr = {
68         .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = groups,
69     };
70     if (::connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
71         return -errno;
72     }
73 
74     return s.release();
75 }
76 
netlinkSocket(unsigned groups)77 int netlinkSocket(unsigned groups) {
78     return netlinkSocket(NETLINK_NETFILTER, groups);
79 }
80 
81 // Test environment for OffloadConfig HIDL HAL.
82 class OffloadConfigHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
83    public:
84     // get the test environment singleton
Instance()85     static OffloadConfigHidlEnvironment* Instance() {
86         static OffloadConfigHidlEnvironment* instance = new OffloadConfigHidlEnvironment;
87         return instance;
88     }
89 
registerTestServices()90     virtual void registerTestServices() override { registerTestService<IOffloadConfig>(); }
91    private:
OffloadConfigHidlEnvironment()92     OffloadConfigHidlEnvironment() {}
93 };
94 
95 class OffloadConfigHidlTest : public testing::VtsHalHidlTargetTestBase {
96    public:
SetUp()97     virtual void SetUp() override {
98         config = testing::VtsHalHidlTargetTestBase::getService<IOffloadConfig>(
99             OffloadConfigHidlEnvironment::Instance()->getServiceName<IOffloadConfig>());
100         ASSERT_NE(nullptr, config.get()) << "Could not get HIDL instance";
101     }
102 
TearDown()103     virtual void TearDown() override {}
104 
105     sp<IOffloadConfig> config;
106 };
107 
108 // Ensure handles can be set with correct socket options.
TEST_F(OffloadConfigHidlTest,TestSetHandles)109 TEST_F(OffloadConfigHidlTest, TestSetHandles) {
110     // Try multiple times in a row to see if it provokes file descriptor leaks.
111     for (int i = 0; i < 1024; i++) {
112         unique_fd fd1(netlinkSocket(kFd1Groups));
113         if (fd1.get() < 0) {
114             ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
115             FAIL();
116         }
117         native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
118         nativeHandle1->data[0] = fd1.release();
119         hidl_handle h1;
120         h1.setTo(nativeHandle1, true);
121 
122         unique_fd fd2(netlinkSocket(kFd2Groups));
123         if (fd2.get() < 0) {
124             ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
125             FAIL();
126         }
127         native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
128         nativeHandle2->data[0] = fd2.release();
129         hidl_handle h2;
130         h2.setTo(nativeHandle2, true);
131 
132         const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
133         ASSERT_TRUE(ret.isOk());
134     }
135 }
136 
137 // Passing a handle without an associated file descriptor should return an error
138 // (e.g. "Failed Input Checks"). Check that this occurs when both FDs are empty.
TEST_F(OffloadConfigHidlTest,TestSetHandleNone)139 TEST_F(OffloadConfigHidlTest, TestSetHandleNone) {
140     native_handle_t* const nativeHandle1 = native_handle_create(0, 0);
141     hidl_handle h1;
142     h1.setTo(nativeHandle1, true);
143     native_handle_t* const nativeHandle2 = native_handle_create(0, 0);
144     hidl_handle h2;
145     h2.setTo(nativeHandle2, true);
146 
147     const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
148     ASSERT_TRUE(ret.isOk());
149 }
150 
151 // Passing a handle without an associated file descriptor should return an error
152 // (e.g. "Failed Input Checks"). Check that this occurs when FD2 is empty.
TEST_F(OffloadConfigHidlTest,TestSetHandle1Only)153 TEST_F(OffloadConfigHidlTest, TestSetHandle1Only) {
154     unique_fd fd1(netlinkSocket(kFd1Groups));
155     if (fd1.get() < 0) {
156         ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
157         FAIL();
158     }
159     native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
160     nativeHandle1->data[0] = fd1.release();
161     hidl_handle h1;
162     h1.setTo(nativeHandle1, true);
163 
164     native_handle_t* const nativeHandle2 = native_handle_create(0, 0);
165     hidl_handle h2;
166     h2.setTo(nativeHandle2, true);
167 
168     const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
169     ASSERT_TRUE(ret.isOk());
170 }
171 
172 // Passing a handle without an associated file descriptor should return an error
173 // (e.g. "Failed Input Checks"). Check that this occurs when FD1 is empty.
TEST_F(OffloadConfigHidlTest,TestSetHandle2OnlyNotOk)174 TEST_F(OffloadConfigHidlTest, TestSetHandle2OnlyNotOk) {
175     native_handle_t* const nativeHandle1 = native_handle_create(0, 0);
176     hidl_handle h1;
177     h1.setTo(nativeHandle1, true);
178 
179     unique_fd fd2(netlinkSocket(kFd2Groups));
180     if (fd2.get() < 0) {
181         ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
182         FAIL();
183     }
184     native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
185     nativeHandle2->data[0] = fd2.release();
186     hidl_handle h2;
187     h2.setTo(nativeHandle2, true);
188 
189     const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
190     ASSERT_TRUE(ret.isOk());
191 }
192 
main(int argc,char ** argv)193 int main(int argc, char** argv) {
194     ::testing::AddGlobalTestEnvironment(OffloadConfigHidlEnvironment::Instance());
195     ::testing::InitGoogleTest(&argc, argv);
196     OffloadConfigHidlEnvironment::Instance()->init(&argc, argv);
197     int status = RUN_ALL_TESTS();
198     ALOGE("Test result with status=%d", status);
199     return status;
200 }
201