blob: 1e44db4596ddbd4f55b02fc0b6e7222c40831cd6 [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
Lorenzo Colitti09353392017-08-24 14:20:32 +0900201std::string kTetherCounterHeaders = Join(std::vector<std::string> {
202 "Chain natctrl_tether_counters (4 references)",
203 " pkts bytes target prot opt in out source destination",
204}, '\n');
205
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900206std::string kIPv4TetherCounters = Join(std::vector<std::string> {
207 "Chain natctrl_tether_counters (4 references)",
208 " pkts bytes target prot opt in out source destination",
209 " 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0",
210 " 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0",
211 " 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0",
212 " 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0",
213}, '\n');
214
215std::string kIPv6TetherCounters = Join(std::vector<std::string> {
216 "Chain natctrl_tether_counters (2 references)",
217 " pkts bytes target prot opt in out source destination",
218 " 10000 10000000 RETURN all wlan0 rmnet0 ::/0 ::/0",
219 " 20000 20000000 RETURN all rmnet0 wlan0 ::/0 ::/0",
220}, '\n');
221
222std::string readSocketClientResponse(int fd) {
223 char buf[32768];
224 ssize_t bytesRead = read(fd, buf, sizeof(buf));
225 if (bytesRead < 0) {
226 return "";
227 }
228 for (int i = 0; i < bytesRead; i++) {
229 if (buf[i] == '\0') buf[i] = '\n';
230 }
231 return std::string(buf, bytesRead);
232}
233
234void expectNoSocketClientResponse(int fd) {
235 char buf[64];
Lorenzo Colitti09353392017-08-24 14:20:32 +0900236 EXPECT_EQ(-1, read(fd, buf, sizeof(buf))) << "Unexpected response: " << buf << "\n";
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900237}
238
239TEST_F(TetherControllerTest, TestGetTetherStats) {
240 int socketPair[2];
241 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, socketPair));
242 ASSERT_EQ(0, fcntl(socketPair[0], F_SETFL, O_NONBLOCK | fcntl(socketPair[0], F_GETFL)));
243 ASSERT_EQ(0, fcntl(socketPair[1], F_SETFL, O_NONBLOCK | fcntl(socketPair[1], F_GETFL)));
244 SocketClient cli(socketPair[0], false);
245
246 std::string err;
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900247
248 // If no filter is specified, both IPv4 and IPv6 counters must have at least one interface pair.
249 addIptablesRestoreOutput(kIPv4TetherCounters);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900250 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900251 expectNoSocketClientResponse(socketPair[1]);
252 clearIptablesRestoreOutput();
253
254 addIptablesRestoreOutput(kIPv6TetherCounters);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900255 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900256 clearIptablesRestoreOutput();
257
258 // IPv4 and IPv6 counters are properly added together.
259 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900260 std::string expected =
261 "114 wlan0 rmnet0 10002373 10026 20002002 20027\n"
262 "114 bt-pan rmnet0 107471 1040 1708806 1450\n"
263 "200 Tethering stats list completed\n";
Lorenzo Colitti09353392017-08-24 14:20:32 +0900264 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900265 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
266 expectNoSocketClientResponse(socketPair[1]);
267 clearIptablesRestoreOutput();
268
Lorenzo Colitti09353392017-08-24 14:20:32 +0900269 // No stats: error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900270 addIptablesRestoreOutput("", kIPv6TetherCounters);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900271 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900272 expectNoSocketClientResponse(socketPair[1]);
273 clearIptablesRestoreOutput();
274
275 addIptablesRestoreOutput(kIPv4TetherCounters, "");
Lorenzo Colitti09353392017-08-24 14:20:32 +0900276 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900277 expectNoSocketClientResponse(socketPair[1]);
278 clearIptablesRestoreOutput();
279
280 // Include only one pair of interfaces and things are fine.
281 std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
282 std::vector<std::string> brokenCounterLines = counterLines;
283 counterLines.resize(4);
284 std::string counters = Join(counterLines, "\n") + "\n";
285 addIptablesRestoreOutput(counters, counters);
286 expected =
287 "114 wlan0 rmnet0 4746 52 4004 54\n"
288 "200 Tethering stats list completed\n";
Lorenzo Colitti09353392017-08-24 14:20:32 +0900289 ASSERT_EQ(0, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900290 ASSERT_EQ(expected, readSocketClientResponse(socketPair[1]));
291 clearIptablesRestoreOutput();
292
293 // But if interfaces aren't paired, it's always an error.
294 err = "";
295 counterLines.resize(3);
296 counters = Join(counterLines, "\n") + "\n";
297 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti09353392017-08-24 14:20:32 +0900298 ASSERT_EQ(-1, mTetherCtrl.getTetherStats(&cli, err));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900299 expectNoSocketClientResponse(socketPair[1]);
300 clearIptablesRestoreOutput();
301
302 // Token unit test of the fact that we return the stats in the error message which the caller
303 // ignores.
304 std::string expectedError = counters;
305 EXPECT_EQ(expectedError, err);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900306}
307
308} // namespace net
309} // namespace android