xref: /aosp_15_r20/system/netd/server/ControllersTest.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1 /*
2  * Copyright 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  * ControllersTest.cpp - unit tests for Controllers.cpp
17  */
18 
19 #include <set>
20 #include <string>
21 #include <vector>
22 
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 
26 #include <android-base/strings.h>
27 
28 #include "Controllers.h"
29 #include "IptablesBaseTest.h"
30 
31 using testing::ContainerEq;
32 
33 namespace android {
34 namespace net {
35 
36 class ControllersTest : public IptablesBaseTest {
37   public:
ControllersTest()38     ControllersTest() {
39         Controllers::execIptablesRestore = fakeExecIptablesRestore;
40         Controllers::execIptablesRestoreWithOutput = fakeExecIptablesRestoreWithOutput;
41     }
42 
43   protected:
initChildChains()44     void initChildChains() { Controllers::initChildChains(); };
findExistingChildChains(IptablesTarget a,const char * b,const char * c)45     std::set<std::string> findExistingChildChains(IptablesTarget a, const char* b, const char*c) {
46         return Controllers::findExistingChildChains(a, b, c);
47     }
48 };
49 
TEST_F(ControllersTest,TestFindExistingChildChains)50 TEST_F(ControllersTest, TestFindExistingChildChains) {
51     ExpectedIptablesCommands expectedCmds = {
52         { V6, "*raw\n-S PREROUTING\nCOMMIT\n" },
53     };
54     sIptablesRestoreOutput.push_back(
55         "-P PREROUTING ACCEPT\n"
56         "-A PREROUTING -j bw_raw_PREROUTING\n"
57         "-A PREROUTING -j idletimer_raw_PREROUTING\n"
58         "-A PREROUTING -j tetherctrl_raw_PREROUTING\n"
59     );
60     std::set<std::string> expectedChains = {
61         "bw_raw_PREROUTING",
62         "idletimer_raw_PREROUTING",
63         "tetherctrl_raw_PREROUTING",
64     };
65     std::set<std::string> actual = findExistingChildChains(V6, "raw", "PREROUTING");
66     EXPECT_THAT(expectedChains, ContainerEq(actual));
67     expectIptablesRestoreCommands(expectedCmds);
68 }
69 
TEST_F(ControllersTest,TestInitIptablesRules)70 TEST_F(ControllersTest, TestInitIptablesRules) {
71     // Test what happens when we boot and there are no rules.
72     ExpectedIptablesCommands expected = {
73             {V4V6,
74              "*filter\n"
75              ":INPUT -\n"
76              "-F INPUT\n"
77              ":bw_INPUT -\n"
78              "-A INPUT -j bw_INPUT\n"
79              ":fw_INPUT -\n"
80              "-A INPUT -j fw_INPUT\n"
81              "COMMIT\n"},
82             {V4V6,
83              "*filter\n"
84              ":FORWARD -\n"
85              "-F FORWARD\n"
86              ":oem_fwd -\n"
87              "-A FORWARD -j oem_fwd\n"
88              ":fw_FORWARD -\n"
89              "-A FORWARD -j fw_FORWARD\n"
90              ":bw_FORWARD -\n"
91              "-A FORWARD -j bw_FORWARD\n"
92              ":tetherctrl_FORWARD -\n"
93              "-A FORWARD -j tetherctrl_FORWARD\n"
94              "COMMIT\n"},
95             {V4V6,
96              "*raw\n"
97              ":PREROUTING -\n"
98              "-F PREROUTING\n"
99              ":idletimer_raw_PREROUTING -\n"
100              "-A PREROUTING -j idletimer_raw_PREROUTING\n"
101              ":bw_raw_PREROUTING -\n"
102              "-A PREROUTING -j bw_raw_PREROUTING\n"
103              ":tetherctrl_raw_PREROUTING -\n"
104              "-A PREROUTING -j tetherctrl_raw_PREROUTING\n"
105              "COMMIT\n"},
106             {V4V6,
107              "*mangle\n"
108              ":FORWARD -\n"
109              "-F FORWARD\n"
110              ":tetherctrl_mangle_FORWARD -\n"
111              "-A FORWARD -j tetherctrl_mangle_FORWARD\n"
112              "COMMIT\n"},
113             {V4V6,
114              "*mangle\n"
115              ":INPUT -\n"
116              "-F INPUT\n"
117              ":connmark_mangle_INPUT -\n"
118              "-A INPUT -j connmark_mangle_INPUT\n"
119              ":wakeupctrl_mangle_INPUT -\n"
120              "-A INPUT -j wakeupctrl_mangle_INPUT\n"
121              ":routectrl_mangle_INPUT -\n"
122              "-A INPUT -j routectrl_mangle_INPUT\n"
123              "COMMIT\n"},
124             {V4V6,
125              "*mangle\n"
126              ":OUTPUT -\n"
127              "-F OUTPUT\n"
128              ":connmark_mangle_OUTPUT -\n"
129              "-A OUTPUT -j connmark_mangle_OUTPUT\n"
130              "COMMIT\n"},
131             {V4,
132              "*nat\n"
133              ":PREROUTING -\n"
134              "-F PREROUTING\n"
135              ":oem_nat_pre -\n"
136              "-A PREROUTING -j oem_nat_pre\n"
137              "COMMIT\n"},
138             {V4,
139              "*nat\n"
140              ":POSTROUTING -\n"
141              "-F POSTROUTING\n"
142              ":tetherctrl_nat_POSTROUTING -\n"
143              "-A POSTROUTING -j tetherctrl_nat_POSTROUTING\n"
144              "COMMIT\n"},
145             {V4,
146              "*filter\n"
147              "-S OUTPUT\n"
148              "COMMIT\n"},
149             {V4,
150              "*filter\n"
151              ":oem_out -\n"
152              "-A OUTPUT -j oem_out\n"
153              ":fw_OUTPUT -\n"
154              "-A OUTPUT -j fw_OUTPUT\n"
155              ":st_OUTPUT -\n"
156              "-A OUTPUT -j st_OUTPUT\n"
157              ":bw_OUTPUT -\n"
158              "-A OUTPUT -j bw_OUTPUT\n"
159              "COMMIT\n"},
160             {V6,
161              "*filter\n"
162              "-S OUTPUT\n"
163              "COMMIT\n"},
164             {V6,
165              "*filter\n"
166              ":oem_out -\n"
167              "-A OUTPUT -j oem_out\n"
168              ":fw_OUTPUT -\n"
169              "-A OUTPUT -j fw_OUTPUT\n"
170              ":st_OUTPUT -\n"
171              "-A OUTPUT -j st_OUTPUT\n"
172              ":bw_OUTPUT -\n"
173              "-A OUTPUT -j bw_OUTPUT\n"
174              "COMMIT\n"},
175             {V4,
176              "*mangle\n"
177              "-S POSTROUTING\n"
178              "COMMIT\n"},
179             {V4,
180              "*mangle\n"
181              ":oem_mangle_post -\n"
182              "-A POSTROUTING -j oem_mangle_post\n"
183              ":bw_mangle_POSTROUTING -\n"
184              "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
185              ":idletimer_mangle_POSTROUTING -\n"
186              "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
187              "COMMIT\n"},
188             {V6,
189              "*mangle\n"
190              "-S POSTROUTING\n"
191              "COMMIT\n"},
192             {V6,
193              "*mangle\n"
194              ":oem_mangle_post -\n"
195              "-A POSTROUTING -j oem_mangle_post\n"
196              ":bw_mangle_POSTROUTING -\n"
197              "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
198              ":idletimer_mangle_POSTROUTING -\n"
199              "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
200              "COMMIT\n"},
201     };
202 
203     // Check that we run these commands and these only.
204     initChildChains();
205     expectIptablesRestoreCommands(expected);
206     expectIptablesRestoreCommands(ExpectedIptablesCommands{});
207 
208     // Now test what happens when some rules exist (e.g., if we crash and restart).
209 
210     // First, explicitly tell the iptables test code to return empty output to all the commands we
211     // send. This allows us to tell it to return non-empty output to particular commands in the
212     // following code.
213     for (size_t i = 0; i < expected.size(); i++) {
214         sIptablesRestoreOutput.push_back("");
215     }
216 
217     // Define a macro to remove a substring from a string. We use a macro instead of a function so
218     // we can assert in it. In the following code, we use ASSERT_* to check for programming errors
219     // in the test code, and EXPECT_* to check for errors in the actual code.
220 #define DELETE_SUBSTRING(substr, str) {                      \
221         const size_t start = (str).find((substr));           \
222         ASSERT_NE(std::string::npos, start);                 \
223         (str).erase(start, strlen((substr)));                \
224         ASSERT_EQ(std::string::npos, (str).find((substr)));  \
225     }
226 
227     // Now set test expectations.
228 
229     // 1. Test that if we find rules that we don't create ourselves, we ignore them.
230     // First check that command #8 is where we list the OUTPUT chain in the (IPv4) filter table:
231     ASSERT_NE(std::string::npos, expected[8].second.find("*filter\n-S OUTPUT\n"));
232     // ... and pretend that when we run that command, we find the following rules. Because we don't
233     // create any of these rules ourselves, our behaviour is unchanged.
234     sIptablesRestoreOutput[8] =
235         "-P OUTPUT ACCEPT\n"
236         "-A OUTPUT -o r_rmnet_data8 -p udp -m udp --dport 1900 -j DROP\n";
237 
238     // 2. Test that rules that we create ourselves are not added if they already exist.
239     // Pretend that when we list the OUTPUT chain in the (IPv6) filter table, we find the oem_out
240     // and st_OUTPUT chains:
241     ASSERT_NE(std::string::npos, expected[10].second.find("*filter\n-S OUTPUT\n"));
242     sIptablesRestoreOutput[10] =
243         "-A OUTPUT -j oem_out\n"
244         "-A OUTPUT -j st_OUTPUT\n";
245     // ... and expect that when we populate the OUTPUT chain, we do not re-add them.
246     DELETE_SUBSTRING("-A OUTPUT -j oem_out\n", expected[11].second);
247     DELETE_SUBSTRING("-A OUTPUT -j st_OUTPUT\n", expected[11].second);
248 
249     // 3. Now test that when we list the POSTROUTING chain in the mangle table, we find a mixture of
250     // netd-created rules and vendor rules:
251     ASSERT_NE(std::string::npos, expected[14].second.find("*mangle\n-S POSTROUTING\n"));
252     sIptablesRestoreOutput[14] =
253         "-P POSTROUTING ACCEPT\n"
254         "-A POSTROUTING -j oem_mangle_post\n"
255         "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
256         "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
257         "-A POSTROUTING -j qcom_qos_reset_POSTROUTING\n"
258         "-A POSTROUTING -j qcom_qos_filter_POSTROUTING\n";
259     // and expect that we don't re-add the netd-created rules that already exist.
260     DELETE_SUBSTRING("-A POSTROUTING -j oem_mangle_post\n", expected[15].second);
261     DELETE_SUBSTRING("-A POSTROUTING -j bw_mangle_POSTROUTING\n", expected[15].second);
262     DELETE_SUBSTRING("-A POSTROUTING -j idletimer_mangle_POSTROUTING\n", expected[15].second);
263 
264     // In this last case, also check that our expectations are reasonable.
265     std::string expectedCmd14 =
266         "*mangle\n"
267         ":oem_mangle_post -\n"
268         ":bw_mangle_POSTROUTING -\n"
269         ":idletimer_mangle_POSTROUTING -\n"
270         "COMMIT\n";
271     ASSERT_EQ(expectedCmd14, expected[15].second);
272 
273     // Finally, actually test that initChildChains runs the expected commands, and nothing more.
274     initChildChains();
275     expectIptablesRestoreCommands(expected);
276     expectIptablesRestoreCommands(ExpectedIptablesCommands{});
277 }
278 
279 }  // namespace net
280 }  // namespace android
281