blob: 887c64888bee1a5757296d052496184c54143b5c [file] [log] [blame]
Lorenzo Colittia93126d2017-08-24 13:28:19 +09001/*
2 * Copyright 2016 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 * TetherControllerTest.cpp - unit tests for TetherController.cpp
17 */
18
19#include <string>
20#include <vector>
21
22#include <fcntl.h>
23#include <unistd.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26
27#include <gtest/gtest.h>
28
29#include <android-base/stringprintf.h>
30#include <android-base/strings.h>
31
32#include "TetherController.h"
33#include "IptablesBaseTest.h"
34
35using android::base::Join;
36using android::base::StringPrintf;
37
38namespace android {
39namespace net {
40
41class TetherControllerTest : public IptablesBaseTest {
42public:
43 TetherControllerTest() {
44 TetherController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
45 }
46
47protected:
48 TetherController mTetherCtrl;
49
50 int setDefaults() {
51 return mTetherCtrl.setDefaults();
52 }
53
54 const ExpectedIptablesCommands FLUSH_COMMANDS = {
55 { V4, "*filter\n"
56 ":natctrl_FORWARD -\n"
57 "-A natctrl_FORWARD -j DROP\n"
58 "COMMIT\n"
59 "*nat\n"
60 ":natctrl_nat_POSTROUTING -\n"
61 "COMMIT\n" },
62 { V6, "*filter\n"
63 ":natctrl_FORWARD -\n"
64 "COMMIT\n"
65 "*raw\n"
66 ":natctrl_raw_PREROUTING -\n"
67 "COMMIT\n" },
68 };
69
70 const ExpectedIptablesCommands SETUP_COMMANDS = {
71 { V4, "*filter\n"
72 ":natctrl_FORWARD -\n"
73 "-A natctrl_FORWARD -j DROP\n"
74 "COMMIT\n"
75 "*nat\n"
76 ":natctrl_nat_POSTROUTING -\n"
77 "COMMIT\n" },
78 { V6, "*filter\n"
79 ":natctrl_FORWARD -\n"
80 "COMMIT\n"
81 "*raw\n"
82 ":natctrl_raw_PREROUTING -\n"
83 "COMMIT\n" },
84 { V4, "*mangle\n"
85 "-A natctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
86 "-j TCPMSS --clamp-mss-to-pmtu\n"
87 "COMMIT\n" },
88 { V4V6, "*filter\n"
89 ":natctrl_tether_counters -\n"
90 "COMMIT\n" },
91 };
92
93 ExpectedIptablesCommands firstNatCommands(const char *extIf) {
94 std::string v4Cmd = StringPrintf(
95 "*nat\n"
96 "-A natctrl_nat_POSTROUTING -o %s -j MASQUERADE\n"
97 "COMMIT\n", extIf);
98 std::string v6Cmd =
99 "*filter\n"
100 "-A natctrl_FORWARD -g natctrl_tether_counters\n"
101 "COMMIT\n";
102 return {
103 { V4, v4Cmd },
104 { V6, v6Cmd },
105 };
106 }
107
108 ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf) {
109 std::string rpfilterCmd = StringPrintf(
110 "*raw\n"
111 "-A natctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
112 "COMMIT\n", intIf);
113
114 std::vector<std::string> v4Cmds = {
115 "*filter",
116 StringPrintf("-A natctrl_FORWARD -i %s -o %s -m state --state"
117 " ESTABLISHED,RELATED -g natctrl_tether_counters", extIf, intIf),
118 StringPrintf("-A natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
119 intIf, extIf),
120 StringPrintf("-A natctrl_FORWARD -i %s -o %s -g natctrl_tether_counters",
121 intIf, extIf),
122 StringPrintf("-A natctrl_tether_counters -i %s -o %s -j RETURN", intIf, extIf),
123 StringPrintf("-A natctrl_tether_counters -i %s -o %s -j RETURN", extIf, intIf),
124 "-D natctrl_FORWARD -j DROP",
125 "-A natctrl_FORWARD -j DROP",
126 "COMMIT\n",
127 };
128
129 std::vector<std::string> v6Cmds = {
130 "*filter",
131 StringPrintf("-A natctrl_tether_counters -i %s -o %s -j RETURN", intIf, extIf),
132 StringPrintf("-A natctrl_tether_counters -i %s -o %s -j RETURN", extIf, intIf),
133 "COMMIT\n",
134 };
135
136 return {
137 { V6, rpfilterCmd },
138 { V4, Join(v4Cmds, '\n') },
139 { V6, Join(v6Cmds, '\n') },
140 };
141 }
142
143 ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) {
144 std::string rpfilterCmd = StringPrintf(
145 "*raw\n"
146 "-D natctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
147 "COMMIT\n", intIf);
148
149 std::vector<std::string> v4Cmds = {
150 "*filter",
151 StringPrintf("-D natctrl_FORWARD -i %s -o %s -m state --state"
152 " ESTABLISHED,RELATED -g natctrl_tether_counters", extIf, intIf),
153 StringPrintf("-D natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
154 intIf, extIf),
155 StringPrintf("-D natctrl_FORWARD -i %s -o %s -g natctrl_tether_counters",
156 intIf, extIf),
157 "COMMIT\n",
158 };
159
160 return {
161 { V6, rpfilterCmd },
162 { V4, Join(v4Cmds, '\n') },
163 };
164
165 }
166};
167
168TEST_F(TetherControllerTest, TestSetupIptablesHooks) {
169 mTetherCtrl.setupIptablesHooks();
170 expectIptablesRestoreCommands(SETUP_COMMANDS);
171}
172
173TEST_F(TetherControllerTest, TestSetDefaults) {
174 setDefaults();
175 expectIptablesRestoreCommands(FLUSH_COMMANDS);
176}
177
178TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
179 ExpectedIptablesCommands expected;
180 ExpectedIptablesCommands setupFirstNatCommands = firstNatCommands("rmnet0");
181 ExpectedIptablesCommands startFirstNatCommands = startNatCommands("wlan0", "rmnet0");
182 expected.insert(expected.end(), setupFirstNatCommands.begin(), setupFirstNatCommands.end());
183 expected.insert(expected.end(), startFirstNatCommands.begin(), startFirstNatCommands.end());
184 mTetherCtrl.enableNat("wlan0", "rmnet0");
185 expectIptablesRestoreCommands(expected);
186
187 ExpectedIptablesCommands startOtherNat = startNatCommands("usb0", "rmnet0");
188 mTetherCtrl.enableNat("usb0", "rmnet0");
189 expectIptablesRestoreCommands(startOtherNat);
190
191 ExpectedIptablesCommands stopOtherNat = stopNatCommands("wlan0", "rmnet0");
192 mTetherCtrl.disableNat("wlan0", "rmnet0");
193 expectIptablesRestoreCommands(stopOtherNat);
194
195 expected = stopNatCommands("usb0", "rmnet0");
196 expected.insert(expected.end(), FLUSH_COMMANDS.begin(), FLUSH_COMMANDS.end());
197 mTetherCtrl.disableNat("usb0", "rmnet0");
198 expectIptablesRestoreCommands(expected);
199}
200
201std::string kIPv4TetherCounters = Join(std::vector<std::string> {
202 "Chain natctrl_tether_counters (4 references)",
203 " pkts bytes target prot opt in out source destination",
204 " 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0",
205 " 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0",
206 " 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0",
207 " 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0",
208}, '\n');
209
210std::string kIPv6TetherCounters = Join(std::vector<std::string> {
211 "Chain natctrl_tether_counters (2 references)",
212 " pkts bytes target prot opt in out source destination",
213 " 10000 10000000 RETURN all wlan0 rmnet0 ::/0 ::/0",
214 " 20000 20000000 RETURN all rmnet0 wlan0 ::/0 ::/0",
215}, '\n');
216
217std::string readSocketClientResponse(int fd) {
218 char buf[32768];
219 ssize_t bytesRead = read(fd, buf, sizeof(buf));
220 if (bytesRead < 0) {
221 return "";
222 }
223 for (int i = 0; i < bytesRead; i++) {
224 if (buf[i] == '\0') buf[i] = '\n';
225 }
226 return std::string(buf, bytesRead);
227}
228
229void expectNoSocketClientResponse(int fd) {
230 char buf[64];
231 EXPECT_EQ(-1, read(fd, buf, sizeof(buf)));
232}
233
234TEST_F(TetherControllerTest, TestGetTetherStats) {
235 int socketPair[2];
236 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, socketPair));
237 ASSERT_EQ(0, fcntl(socketPair[0], F_SETFL, O_NONBLOCK | fcntl(socketPair[0], F_GETFL)));
238 ASSERT_EQ(0, fcntl(socketPair[1], F_SETFL, O_NONBLOCK | fcntl(socketPair[1], F_GETFL)));
239 SocketClient cli(socketPair[0], false);
240
241 std::string err;
242 TetherController::TetherStats filter;
243
244 // If no filter is specified, both IPv4 and IPv6 counters must have at least one interface pair.
245 addIptablesRestoreOutput(kIPv4TetherCounters);
246 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
247 expectNoSocketClientResponse(socketPair[1]);
248 clearIptablesRestoreOutput();
249
250 addIptablesRestoreOutput(kIPv6TetherCounters);
251 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
252 clearIptablesRestoreOutput();
253
254 // IPv4 and IPv6 counters are properly added together.
255 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
256 filter = TetherController::TetherStats();
257 std::string expected =
258 "114 wlan0 rmnet0 10002373 10026 20002002 20027\n"
259 "114 bt-pan rmnet0 107471 1040 1708806 1450\n"
260 "200 Tethering stats list completed\n";
261 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
262 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
263 expectNoSocketClientResponse(socketPair[1]);
264 clearIptablesRestoreOutput();
265
266 // Test filtering.
267 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
268 filter = TetherController::TetherStats("bt-pan", "rmnet0", -1, -1, -1, -1);
269 expected = "221 bt-pan rmnet0 107471 1040 1708806 1450\n";
270 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
271 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
272 expectNoSocketClientResponse(socketPair[1]);
273 clearIptablesRestoreOutput();
274
275 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
276 filter = TetherController::TetherStats("wlan0", "rmnet0", -1, -1, -1, -1);
277 expected = "221 wlan0 rmnet0 10002373 10026 20002002 20027\n";
278 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
279 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
280 clearIptablesRestoreOutput();
281
282 // Select nonexistent interfaces.
283 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
284 filter = TetherController::TetherStats("rmnet0", "foo0", -1, -1, -1, -1);
285 expected = "200 Tethering stats list completed\n";
286 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
287 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
288 clearIptablesRestoreOutput();
289
290 // No stats with a filter: no error.
291 addIptablesRestoreOutput("", "");
292 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
293 ASSERT_EQ("200 Tethering stats list completed\n", readSocketClientResponse(socketPair[1]));
294 clearIptablesRestoreOutput();
295
296 addIptablesRestoreOutput("foo", "foo");
297 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
298 ASSERT_EQ("200 Tethering stats list completed\n", readSocketClientResponse(socketPair[1]));
299 clearIptablesRestoreOutput();
300
301 // No stats and empty filter: error.
302 filter = TetherController::TetherStats();
303 addIptablesRestoreOutput("", kIPv6TetherCounters);
304 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
305 expectNoSocketClientResponse(socketPair[1]);
306 clearIptablesRestoreOutput();
307
308 addIptablesRestoreOutput(kIPv4TetherCounters, "");
309 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
310 expectNoSocketClientResponse(socketPair[1]);
311 clearIptablesRestoreOutput();
312
313 // Include only one pair of interfaces and things are fine.
314 std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
315 std::vector<std::string> brokenCounterLines = counterLines;
316 counterLines.resize(4);
317 std::string counters = Join(counterLines, "\n") + "\n";
318 addIptablesRestoreOutput(counters, counters);
319 expected =
320 "114 wlan0 rmnet0 4746 52 4004 54\n"
321 "200 Tethering stats list completed\n";
322 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, filter, err));
323 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
324 clearIptablesRestoreOutput();
325
326 // But if interfaces aren't paired, it's always an error.
327 err = "";
328 counterLines.resize(3);
329 counters = Join(counterLines, "\n") + "\n";
330 addIptablesRestoreOutput(counters, counters);
331 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
332 expectNoSocketClientResponse(socketPair[1]);
333 clearIptablesRestoreOutput();
334
335 // Token unit test of the fact that we return the stats in the error message which the caller
336 // ignores.
337 std::string expectedError = counters;
338 EXPECT_EQ(expectedError, err);
339
340 addIptablesRestoreOutput(kIPv4TetherCounters);
341 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
342 expectNoSocketClientResponse(socketPair[1]);
343 clearIptablesRestoreOutput();
344 addIptablesRestoreOutput(kIPv6TetherCounters);
345 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, filter, err));
346 expectNoSocketClientResponse(socketPair[1]);
347 clearIptablesRestoreOutput();
348}
349
350} // namespace net
351} // namespace android