• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 natctrl_raw_PREROUTING\n"
59     );
60     std::set<std::string> expectedChains = {
61         "bw_raw_PREROUTING",
62         "idletimer_raw_PREROUTING",
63         "natctrl_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, "*filter\n"
74                 ":INPUT -\n"
75                 "-F INPUT\n"
76                 ":bw_INPUT -\n"
77                 "-A INPUT -j bw_INPUT\n"
78                 ":fw_INPUT -\n"
79                 "-A INPUT -j fw_INPUT\n"
80                 "COMMIT\n"
81         },
82         { V4V6, "*filter\n"
83                 ":FORWARD -\n"
84                 "-F FORWARD\n"
85                 ":oem_fwd -\n"
86                 "-A FORWARD -j oem_fwd\n"
87                 ":fw_FORWARD -\n"
88                 "-A FORWARD -j fw_FORWARD\n"
89                 ":bw_FORWARD -\n"
90                 "-A FORWARD -j bw_FORWARD\n"
91                 ":natctrl_FORWARD -\n"
92                 "-A FORWARD -j natctrl_FORWARD\n"
93                 "COMMIT\n"
94         },
95         { V4V6, "*raw\n"
96                 ":PREROUTING -\n"
97                 "-F PREROUTING\n"
98                 ":bw_raw_PREROUTING -\n"
99                 "-A PREROUTING -j bw_raw_PREROUTING\n"
100                 ":idletimer_raw_PREROUTING -\n"
101                 "-A PREROUTING -j idletimer_raw_PREROUTING\n"
102                 ":natctrl_raw_PREROUTING -\n"
103                 "-A PREROUTING -j natctrl_raw_PREROUTING\n"
104                 "COMMIT\n"
105         },
106         { V4V6, "*mangle\n"
107                 ":FORWARD -\n"
108                 "-F FORWARD\n"
109                 ":natctrl_mangle_FORWARD -\n"
110                 "-A FORWARD -j natctrl_mangle_FORWARD\n"
111                 "COMMIT\n"
112         },
113         { V4V6, "*mangle\n"
114                 ":INPUT -\n"
115                 "-F INPUT\n"
116                 ":wakeupctrl_mangle_INPUT -\n"
117                 "-A INPUT -j wakeupctrl_mangle_INPUT\n"
118                 ":routectrl_mangle_INPUT -\n"
119                 "-A INPUT -j routectrl_mangle_INPUT\n"
120                 "COMMIT\n"
121         },
122         { V4,   "*nat\n"
123                 ":PREROUTING -\n"
124                 "-F PREROUTING\n"
125                 ":oem_nat_pre -\n"
126                 "-A PREROUTING -j oem_nat_pre\n"
127                 "COMMIT\n"
128         },
129         { V4,   "*nat\n"
130                 ":POSTROUTING -\n"
131                 "-F POSTROUTING\n"
132                 ":natctrl_nat_POSTROUTING -\n"
133                 "-A POSTROUTING -j natctrl_nat_POSTROUTING\n"
134                 "COMMIT\n"
135         },
136         { V4, "*filter\n"
137               "-S OUTPUT\n"
138               "COMMIT\n" },
139         { V4, "*filter\n"
140               ":oem_out -\n"
141               "-A OUTPUT -j oem_out\n"
142               ":fw_OUTPUT -\n"
143               "-A OUTPUT -j fw_OUTPUT\n"
144               ":st_OUTPUT -\n"
145               "-A OUTPUT -j st_OUTPUT\n"
146               ":bw_OUTPUT -\n"
147               "-A OUTPUT -j bw_OUTPUT\n"
148               "COMMIT\n"
149         },
150         { V6, "*filter\n"
151               "-S OUTPUT\n"
152               "COMMIT\n" },
153         { V6, "*filter\n"
154               ":oem_out -\n"
155               "-A OUTPUT -j oem_out\n"
156               ":fw_OUTPUT -\n"
157               "-A OUTPUT -j fw_OUTPUT\n"
158               ":st_OUTPUT -\n"
159               "-A OUTPUT -j st_OUTPUT\n"
160               ":bw_OUTPUT -\n"
161               "-A OUTPUT -j bw_OUTPUT\n"
162               "COMMIT\n"
163         },
164         { V4, "*mangle\n"
165               "-S POSTROUTING\n"
166               "COMMIT\n" },
167         { V4, "*mangle\n"
168               ":oem_mangle_post -\n"
169               "-A POSTROUTING -j oem_mangle_post\n"
170               ":bw_mangle_POSTROUTING -\n"
171               "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
172               ":idletimer_mangle_POSTROUTING -\n"
173               "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
174               "COMMIT\n"
175         },
176         { V6, "*mangle\n"
177               "-S POSTROUTING\n"
178               "COMMIT\n" },
179         { V6, "*mangle\n"
180               ":oem_mangle_post -\n"
181               "-A POSTROUTING -j oem_mangle_post\n"
182               ":bw_mangle_POSTROUTING -\n"
183               "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
184               ":idletimer_mangle_POSTROUTING -\n"
185               "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
186               "COMMIT\n"
187         },
188     };
189 
190     // Check that we run these commands and these only.
191     initChildChains();
192     expectIptablesRestoreCommands(expected);
193     expectIptablesRestoreCommands(ExpectedIptablesCommands{});
194 
195     // Now test what happens when some rules exist (e.g., if we crash and restart).
196 
197     // First, explicitly tell the iptables test code to return empty output to all the commands we
198     // send. This allows us to tell it to return non-empty output to particular commands in the
199     // following code.
200     for (size_t i = 0; i < expected.size(); i++) {
201         sIptablesRestoreOutput.push_back("");
202     }
203 
204     // Define a macro to remove a substring from a string. We use a macro instead of a function so
205     // we can assert in it. In the following code, we use ASSERT_* to check for programming errors
206     // in the test code, and EXPECT_* to check for errors in the actual code.
207 #define DELETE_SUBSTRING(substr, str) {                      \
208         size_t start = (str).find((substr));                 \
209         ASSERT_NE(std::string::npos, start);                 \
210         (str).erase(start, strlen((substr)));                \
211         ASSERT_EQ(std::string::npos, (str).find((substr)));  \
212     }
213 
214     // Now set test expectations.
215 
216     // 1. Test that if we find rules that we don't create ourselves, we ignore them.
217     // First check that command #7 is where we list the OUTPUT chain in the (IPv4) filter table:
218     ASSERT_NE(std::string::npos, expected[7].second.find("*filter\n-S OUTPUT\n"));
219     // ... and pretend that when we run that command, we find the following rules. Because we don't
220     // create any of these rules ourselves, our behaviour is unchanged.
221     sIptablesRestoreOutput[7] =
222         "-P OUTPUT ACCEPT\n"
223         "-A OUTPUT -o r_rmnet_data8 -p udp -m udp --dport 1900 -j DROP\n";
224 
225     // 2. Test that rules that we create ourselves are not added if they already exist.
226     // Pretend that when we list the OUTPUT chain in the (IPv6) filter table, we find the oem_out
227     // and st_OUTPUT chains:
228     ASSERT_NE(std::string::npos, expected[9].second.find("*filter\n-S OUTPUT\n"));
229     sIptablesRestoreOutput[9] =
230         "-A OUTPUT -j oem_out\n"
231         "-A OUTPUT -j st_OUTPUT\n";
232     // ... and expect that when we populate the OUTPUT chain, we do not re-add them.
233     DELETE_SUBSTRING("-A OUTPUT -j oem_out\n", expected[10].second);
234     DELETE_SUBSTRING("-A OUTPUT -j st_OUTPUT\n", expected[10].second);
235 
236     // 3. Now test that when we list the POSTROUTING chain in the mangle table, we find a mixture of
237     // netd-created rules and vendor rules:
238     ASSERT_NE(std::string::npos, expected[13].second.find("*mangle\n-S POSTROUTING\n"));
239     sIptablesRestoreOutput[13] =
240         "-P POSTROUTING ACCEPT\n"
241         "-A POSTROUTING -j oem_mangle_post\n"
242         "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
243         "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
244         "-A POSTROUTING -j qcom_qos_reset_POSTROUTING\n"
245         "-A POSTROUTING -j qcom_qos_filter_POSTROUTING\n";
246     // and expect that we don't re-add the netd-created rules that already exist.
247     DELETE_SUBSTRING("-A POSTROUTING -j oem_mangle_post\n", expected[14].second);
248     DELETE_SUBSTRING("-A POSTROUTING -j bw_mangle_POSTROUTING\n", expected[14].second);
249     DELETE_SUBSTRING("-A POSTROUTING -j idletimer_mangle_POSTROUTING\n", expected[14].second);
250 
251     // In this last case, also check that our expectations are reasonable.
252     std::string expectedCmd14 =
253         "*mangle\n"
254         ":oem_mangle_post -\n"
255         ":bw_mangle_POSTROUTING -\n"
256         ":idletimer_mangle_POSTROUTING -\n"
257         "COMMIT\n";
258     ASSERT_EQ(expectedCmd14, expected[14].second);
259 
260     // Finally, actually test that initChildChains runs the expected commands, and nothing more.
261     initChildChains();
262     expectIptablesRestoreCommands(expected);
263     expectIptablesRestoreCommands(ExpectedIptablesCommands{});
264 }
265 
266 }  // namespace net
267 }  // namespace android
268