blob: b92dc242bbfa3d74d40af81c6f8ff47eb1eae668 [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>
Lorenzo Colitti5192bf72017-09-04 13:30:59 +090031#include <netdutils/StatusOr.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090032
33#include "TetherController.h"
34#include "IptablesBaseTest.h"
35
36using android::base::Join;
37using android::base::StringPrintf;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +090038using android::netdutils::StatusOr;
39using TetherStats = android::net::TetherController::TetherStats;
40using TetherStatsList = android::net::TetherController::TetherStatsList;
Lorenzo Colittia93126d2017-08-24 13:28:19 +090041
42namespace android {
43namespace net {
44
45class TetherControllerTest : public IptablesBaseTest {
46public:
47 TetherControllerTest() {
48 TetherController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
49 }
50
51protected:
52 TetherController mTetherCtrl;
53
54 int setDefaults() {
55 return mTetherCtrl.setDefaults();
56 }
57
58 const ExpectedIptablesCommands FLUSH_COMMANDS = {
59 { V4, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090060 ":tetherctrl_FORWARD -\n"
61 "-A tetherctrl_FORWARD -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090062 "COMMIT\n"
63 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090064 ":tetherctrl_nat_POSTROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090065 "COMMIT\n" },
66 { V6, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090067 ":tetherctrl_FORWARD -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090068 "COMMIT\n"
69 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090070 ":tetherctrl_raw_PREROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090071 "COMMIT\n" },
72 };
73
74 const ExpectedIptablesCommands SETUP_COMMANDS = {
75 { V4, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090076 ":tetherctrl_FORWARD -\n"
77 "-A tetherctrl_FORWARD -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090078 "COMMIT\n"
79 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090080 ":tetherctrl_nat_POSTROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090081 "COMMIT\n" },
82 { V6, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090083 ":tetherctrl_FORWARD -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090084 "COMMIT\n"
85 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090086 ":tetherctrl_raw_PREROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090087 "COMMIT\n" },
88 { V4, "*mangle\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090089 "-A tetherctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
Lorenzo Colittia93126d2017-08-24 13:28:19 +090090 "-j TCPMSS --clamp-mss-to-pmtu\n"
91 "COMMIT\n" },
92 { V4V6, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090093 ":tetherctrl_counters -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090094 "COMMIT\n" },
95 };
96
97 ExpectedIptablesCommands firstNatCommands(const char *extIf) {
98 std::string v4Cmd = StringPrintf(
99 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900100 "-A tetherctrl_nat_POSTROUTING -o %s -j MASQUERADE\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900101 "COMMIT\n", extIf);
102 std::string v6Cmd =
103 "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900104 "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900105 "COMMIT\n";
106 return {
107 { V4, v4Cmd },
108 { V6, v6Cmd },
109 };
110 }
111
112 ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf) {
113 std::string rpfilterCmd = StringPrintf(
114 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900115 "-A tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900116 "COMMIT\n", intIf);
117
118 std::vector<std::string> v4Cmds = {
119 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900120 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state"
121 " ESTABLISHED,RELATED -g tetherctrl_counters", extIf, intIf),
122 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900123 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900124 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900125 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900126 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
127 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
128 "-D tetherctrl_FORWARD -j DROP",
129 "-A tetherctrl_FORWARD -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900130 "COMMIT\n",
131 };
132
133 std::vector<std::string> v6Cmds = {
134 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900135 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
136 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900137 "COMMIT\n",
138 };
139
140 return {
141 { V6, rpfilterCmd },
142 { V4, Join(v4Cmds, '\n') },
143 { V6, Join(v6Cmds, '\n') },
144 };
145 }
146
147 ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) {
148 std::string rpfilterCmd = StringPrintf(
149 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900150 "-D tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900151 "COMMIT\n", intIf);
152
153 std::vector<std::string> v4Cmds = {
154 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900155 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state"
156 " ESTABLISHED,RELATED -g tetherctrl_counters", extIf, intIf),
157 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900158 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900159 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900160 intIf, extIf),
161 "COMMIT\n",
162 };
163
164 return {
165 { V6, rpfilterCmd },
166 { V4, Join(v4Cmds, '\n') },
167 };
168
169 }
170};
171
172TEST_F(TetherControllerTest, TestSetupIptablesHooks) {
173 mTetherCtrl.setupIptablesHooks();
174 expectIptablesRestoreCommands(SETUP_COMMANDS);
175}
176
177TEST_F(TetherControllerTest, TestSetDefaults) {
178 setDefaults();
179 expectIptablesRestoreCommands(FLUSH_COMMANDS);
180}
181
182TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
183 ExpectedIptablesCommands expected;
184 ExpectedIptablesCommands setupFirstNatCommands = firstNatCommands("rmnet0");
185 ExpectedIptablesCommands startFirstNatCommands = startNatCommands("wlan0", "rmnet0");
186 expected.insert(expected.end(), setupFirstNatCommands.begin(), setupFirstNatCommands.end());
187 expected.insert(expected.end(), startFirstNatCommands.begin(), startFirstNatCommands.end());
188 mTetherCtrl.enableNat("wlan0", "rmnet0");
189 expectIptablesRestoreCommands(expected);
190
191 ExpectedIptablesCommands startOtherNat = startNatCommands("usb0", "rmnet0");
192 mTetherCtrl.enableNat("usb0", "rmnet0");
193 expectIptablesRestoreCommands(startOtherNat);
194
195 ExpectedIptablesCommands stopOtherNat = stopNatCommands("wlan0", "rmnet0");
196 mTetherCtrl.disableNat("wlan0", "rmnet0");
197 expectIptablesRestoreCommands(stopOtherNat);
198
199 expected = stopNatCommands("usb0", "rmnet0");
200 expected.insert(expected.end(), FLUSH_COMMANDS.begin(), FLUSH_COMMANDS.end());
201 mTetherCtrl.disableNat("usb0", "rmnet0");
202 expectIptablesRestoreCommands(expected);
203}
204
Lorenzo Colitti09353392017-08-24 14:20:32 +0900205std::string kTetherCounterHeaders = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900206 "Chain tetherctrl_counters (4 references)",
Lorenzo Colitti09353392017-08-24 14:20:32 +0900207 " pkts bytes target prot opt in out source destination",
208}, '\n');
209
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900210std::string kIPv4TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900211 "Chain tetherctrl_counters (4 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900212 " pkts bytes target prot opt in out source destination",
213 " 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0",
214 " 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0",
215 " 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0",
216 " 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0",
217}, '\n');
218
219std::string kIPv6TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900220 "Chain tetherctrl_counters (2 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900221 " pkts bytes target prot opt in out source destination",
222 " 10000 10000000 RETURN all wlan0 rmnet0 ::/0 ::/0",
223 " 20000 20000000 RETURN all rmnet0 wlan0 ::/0 ::/0",
224}, '\n');
225
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900226void expectTetherStatsEqual(const TetherController::TetherStats& expected,
227 const TetherController::TetherStats& actual) {
228 EXPECT_EQ(expected.intIface, actual.intIface);
229 EXPECT_EQ(expected.extIface, actual.extIface);
230 EXPECT_EQ(expected.rxBytes, actual.rxBytes);
231 EXPECT_EQ(expected.txBytes, actual.txBytes);
232 EXPECT_EQ(expected.rxPackets, actual.rxPackets);
233 EXPECT_EQ(expected.txPackets, actual.txPackets);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900234}
235
236TEST_F(TetherControllerTest, TestGetTetherStats) {
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900237 // Finding no headers is an error.
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900238 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900239 clearIptablesRestoreOutput();
240
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900241 // Finding only v4 or only v6 headers is an error.
242 addIptablesRestoreOutput(kTetherCounterHeaders, "");
243 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
244 clearIptablesRestoreOutput();
245
246 addIptablesRestoreOutput("", kTetherCounterHeaders);
247 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
248 clearIptablesRestoreOutput();
249
250 // Finding headers but no stats is not an error.
251 addIptablesRestoreOutput(kTetherCounterHeaders, kTetherCounterHeaders);
252 StatusOr<TetherStatsList> result = mTetherCtrl.getTetherStats();
253 ASSERT_TRUE(isOk(result));
254 TetherStatsList actual = result.value();
255 ASSERT_EQ(0U, actual.size());
256 clearIptablesRestoreOutput();
257
258
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900259 addIptablesRestoreOutput(kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900260 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900261 clearIptablesRestoreOutput();
262
263 // IPv4 and IPv6 counters are properly added together.
264 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900265 TetherStats expected0("wlan0", "rmnet0", 20002002, 20027, 10002373, 10026);
266 TetherStats expected1("bt-pan", "rmnet0", 1708806, 1450, 107471, 1040);
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900267 result = mTetherCtrl.getTetherStats();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900268 ASSERT_TRUE(isOk(result));
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900269 actual = result.value();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900270 ASSERT_EQ(2U, actual.size());
271 expectTetherStatsEqual(expected0, result.value()[0]);
272 expectTetherStatsEqual(expected1, result.value()[1]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900273 clearIptablesRestoreOutput();
274
Lorenzo Colitti09353392017-08-24 14:20:32 +0900275 // No stats: error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900276 addIptablesRestoreOutput("", kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900277 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900278 clearIptablesRestoreOutput();
279
280 addIptablesRestoreOutput(kIPv4TetherCounters, "");
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900281 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900282 clearIptablesRestoreOutput();
283
284 // Include only one pair of interfaces and things are fine.
285 std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
286 std::vector<std::string> brokenCounterLines = counterLines;
287 counterLines.resize(4);
288 std::string counters = Join(counterLines, "\n") + "\n";
289 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900290 TetherStats expected1_0("wlan0", "rmnet0", 4004, 54, 4746, 52);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900291 result = mTetherCtrl.getTetherStats();
292 ASSERT_TRUE(isOk(result));
293 actual = result.value();
294 ASSERT_EQ(1U, actual.size());
295 expectTetherStatsEqual(expected1_0, actual[0]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900296 clearIptablesRestoreOutput();
297
298 // But if interfaces aren't paired, it's always an error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900299 counterLines.resize(3);
300 counters = Join(counterLines, "\n") + "\n";
301 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900302 result = mTetherCtrl.getTetherStats();
303 ASSERT_FALSE(isOk(result));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900304 clearIptablesRestoreOutput();
305
306 // Token unit test of the fact that we return the stats in the error message which the caller
307 // ignores.
308 std::string expectedError = counters;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900309 std::string err = result.status().msg();
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900310 ASSERT_LE(expectedError.size(), err.size());
311 EXPECT_TRUE(std::equal(expectedError.rbegin(), expectedError.rend(), err.rbegin()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900312}
313
314} // namespace net
315} // namespace android