xref: /aosp_15_r20/system/netd/server/TetherControllerTest.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker  * Copyright 2016 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker  *
4*8542734aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker  *
8*8542734aSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker  *
10*8542734aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker  * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker  *
16*8542734aSAndroid Build Coastguard Worker  * TetherControllerTest.cpp - unit tests for TetherController.cpp
17*8542734aSAndroid Build Coastguard Worker  */
18*8542734aSAndroid Build Coastguard Worker 
19*8542734aSAndroid Build Coastguard Worker #include <string>
20*8542734aSAndroid Build Coastguard Worker #include <vector>
21*8542734aSAndroid Build Coastguard Worker 
22*8542734aSAndroid Build Coastguard Worker #include <fcntl.h>
23*8542734aSAndroid Build Coastguard Worker #include <inttypes.h>
24*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
25*8542734aSAndroid Build Coastguard Worker #include <sys/types.h>
26*8542734aSAndroid Build Coastguard Worker #include <unistd.h>
27*8542734aSAndroid Build Coastguard Worker 
28*8542734aSAndroid Build Coastguard Worker #include <gtest/gtest.h>
29*8542734aSAndroid Build Coastguard Worker 
30*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
31*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
32*8542734aSAndroid Build Coastguard Worker #include <gmock/gmock.h>
33*8542734aSAndroid Build Coastguard Worker #include <netdutils/StatusOr.h>
34*8542734aSAndroid Build Coastguard Worker 
35*8542734aSAndroid Build Coastguard Worker #include "IptablesBaseTest.h"
36*8542734aSAndroid Build Coastguard Worker #include "TcUtils.h"
37*8542734aSAndroid Build Coastguard Worker #include "TetherController.h"
38*8542734aSAndroid Build Coastguard Worker 
39*8542734aSAndroid Build Coastguard Worker using android::base::Join;
40*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
41*8542734aSAndroid Build Coastguard Worker using android::netdutils::StatusOr;
42*8542734aSAndroid Build Coastguard Worker using TetherStats = android::net::TetherController::TetherStats;
43*8542734aSAndroid Build Coastguard Worker using TetherStatsList = android::net::TetherController::TetherStatsList;
44*8542734aSAndroid Build Coastguard Worker 
45*8542734aSAndroid Build Coastguard Worker namespace android {
46*8542734aSAndroid Build Coastguard Worker namespace net {
47*8542734aSAndroid Build Coastguard Worker 
48*8542734aSAndroid Build Coastguard Worker class TetherControllerTest : public IptablesBaseTest {
49*8542734aSAndroid Build Coastguard Worker public:
TetherControllerTest()50*8542734aSAndroid Build Coastguard Worker     TetherControllerTest() {
51*8542734aSAndroid Build Coastguard Worker         TetherController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
52*8542734aSAndroid Build Coastguard Worker     }
53*8542734aSAndroid Build Coastguard Worker 
54*8542734aSAndroid Build Coastguard Worker protected:
55*8542734aSAndroid Build Coastguard Worker     TetherController mTetherCtrl;
56*8542734aSAndroid Build Coastguard Worker 
setDefaults()57*8542734aSAndroid Build Coastguard Worker     int setDefaults() {
58*8542734aSAndroid Build Coastguard Worker         return mTetherCtrl.setDefaults();
59*8542734aSAndroid Build Coastguard Worker     }
60*8542734aSAndroid Build Coastguard Worker 
61*8542734aSAndroid Build Coastguard Worker     const ExpectedIptablesCommands FLUSH_COMMANDS = {
62*8542734aSAndroid Build Coastguard Worker             {V4,
63*8542734aSAndroid Build Coastguard Worker              "*filter\n"
64*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_FORWARD -\n"
65*8542734aSAndroid Build Coastguard Worker              "-A tetherctrl_FORWARD -j DROP\n"
66*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"
67*8542734aSAndroid Build Coastguard Worker              "*nat\n"
68*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_nat_POSTROUTING -\n"
69*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
70*8542734aSAndroid Build Coastguard Worker             {V6,
71*8542734aSAndroid Build Coastguard Worker              "*filter\n"
72*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_FORWARD -\n"
73*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"
74*8542734aSAndroid Build Coastguard Worker              "*raw\n"
75*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_raw_PREROUTING -\n"
76*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
77*8542734aSAndroid Build Coastguard Worker     };
78*8542734aSAndroid Build Coastguard Worker 
79*8542734aSAndroid Build Coastguard Worker     const ExpectedIptablesCommands SETUP_COMMANDS = {
80*8542734aSAndroid Build Coastguard Worker             {V4,
81*8542734aSAndroid Build Coastguard Worker              "*filter\n"
82*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_FORWARD -\n"
83*8542734aSAndroid Build Coastguard Worker              "-A tetherctrl_FORWARD -j DROP\n"
84*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"
85*8542734aSAndroid Build Coastguard Worker              "*nat\n"
86*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_nat_POSTROUTING -\n"
87*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
88*8542734aSAndroid Build Coastguard Worker             {V6,
89*8542734aSAndroid Build Coastguard Worker              "*filter\n"
90*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_FORWARD -\n"
91*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"
92*8542734aSAndroid Build Coastguard Worker              "*raw\n"
93*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_raw_PREROUTING -\n"
94*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
95*8542734aSAndroid Build Coastguard Worker             {V4,
96*8542734aSAndroid Build Coastguard Worker              "*mangle\n"
97*8542734aSAndroid Build Coastguard Worker              "-A tetherctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
98*8542734aSAndroid Build Coastguard Worker              "-j TCPMSS --clamp-mss-to-pmtu\n"
99*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
100*8542734aSAndroid Build Coastguard Worker             {V4V6,
101*8542734aSAndroid Build Coastguard Worker              "*filter\n"
102*8542734aSAndroid Build Coastguard Worker              ":tetherctrl_counters -\n"
103*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
104*8542734aSAndroid Build Coastguard Worker     };
105*8542734aSAndroid Build Coastguard Worker 
106*8542734aSAndroid Build Coastguard Worker     const ExpectedIptablesCommands ALERT_ADD_COMMAND = {
107*8542734aSAndroid Build Coastguard Worker             {V4V6,
108*8542734aSAndroid Build Coastguard Worker              "*filter\n"
109*8542734aSAndroid Build Coastguard Worker              "-I tetherctrl_FORWARD -j bw_global_alert\n"
110*8542734aSAndroid Build Coastguard Worker              "COMMIT\n"},
111*8542734aSAndroid Build Coastguard Worker     };
112*8542734aSAndroid Build Coastguard Worker 
firstIPv4UpstreamCommands(const char * extIf)113*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands firstIPv4UpstreamCommands(const char *extIf) {
114*8542734aSAndroid Build Coastguard Worker         std::string v4Cmd = StringPrintf(
115*8542734aSAndroid Build Coastguard Worker             "*nat\n"
116*8542734aSAndroid Build Coastguard Worker             "-A tetherctrl_nat_POSTROUTING -o %s -j MASQUERADE\n"
117*8542734aSAndroid Build Coastguard Worker             "COMMIT\n", extIf);
118*8542734aSAndroid Build Coastguard Worker         return {
119*8542734aSAndroid Build Coastguard Worker             { V4, v4Cmd },
120*8542734aSAndroid Build Coastguard Worker         };
121*8542734aSAndroid Build Coastguard Worker     }
122*8542734aSAndroid Build Coastguard Worker 
firstIPv6UpstreamCommands()123*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands firstIPv6UpstreamCommands() {
124*8542734aSAndroid Build Coastguard Worker         std::string v6Cmd =
125*8542734aSAndroid Build Coastguard Worker                 "*filter\n"
126*8542734aSAndroid Build Coastguard Worker                 "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
127*8542734aSAndroid Build Coastguard Worker                 "COMMIT\n";
128*8542734aSAndroid Build Coastguard Worker         return {
129*8542734aSAndroid Build Coastguard Worker             { V6, v6Cmd },
130*8542734aSAndroid Build Coastguard Worker         };
131*8542734aSAndroid Build Coastguard Worker     }
132*8542734aSAndroid Build Coastguard Worker 
133*8542734aSAndroid Build Coastguard Worker     template<typename T>
appendAll(std::vector<T> & cmds,const std::vector<T> & appendCmds)134*8542734aSAndroid Build Coastguard Worker     void appendAll(std::vector<T>& cmds, const std::vector<T>& appendCmds) {
135*8542734aSAndroid Build Coastguard Worker         cmds.insert(cmds.end(), appendCmds.begin(), appendCmds.end());
136*8542734aSAndroid Build Coastguard Worker     }
137*8542734aSAndroid Build Coastguard Worker 
startNatCommands(const char * intIf,const char * extIf,bool withCounterChainRules)138*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf,
139*8542734aSAndroid Build Coastguard Worker             bool withCounterChainRules) {
140*8542734aSAndroid Build Coastguard Worker         std::string rpfilterCmd = StringPrintf(
141*8542734aSAndroid Build Coastguard Worker             "*raw\n"
142*8542734aSAndroid Build Coastguard Worker             "-A tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
143*8542734aSAndroid Build Coastguard Worker             "COMMIT\n", intIf);
144*8542734aSAndroid Build Coastguard Worker 
145*8542734aSAndroid Build Coastguard Worker         std::vector<std::string> v4Cmds = {
146*8542734aSAndroid Build Coastguard Worker                 "*raw",
147*8542734aSAndroid Build Coastguard Worker                 StringPrintf(
148*8542734aSAndroid Build Coastguard Worker                         "-A tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
149*8542734aSAndroid Build Coastguard Worker                         intIf),
150*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-A tetherctrl_raw_PREROUTING -p tcp --dport 1723 -i %s -j CT "
151*8542734aSAndroid Build Coastguard Worker                              "--helper pptp",
152*8542734aSAndroid Build Coastguard Worker                              intIf),
153*8542734aSAndroid Build Coastguard Worker                 "COMMIT",
154*8542734aSAndroid Build Coastguard Worker                 "*filter",
155*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state"
156*8542734aSAndroid Build Coastguard Worker                              " ESTABLISHED,RELATED -g tetherctrl_counters",
157*8542734aSAndroid Build Coastguard Worker                              extIf, intIf),
158*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
159*8542734aSAndroid Build Coastguard Worker                              intIf, extIf),
160*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters", intIf,
161*8542734aSAndroid Build Coastguard Worker                              extIf),
162*8542734aSAndroid Build Coastguard Worker         };
163*8542734aSAndroid Build Coastguard Worker 
164*8542734aSAndroid Build Coastguard Worker         std::vector<std::string> v6Cmds = {
165*8542734aSAndroid Build Coastguard Worker             "*filter",
166*8542734aSAndroid Build Coastguard Worker         };
167*8542734aSAndroid Build Coastguard Worker 
168*8542734aSAndroid Build Coastguard Worker         if (withCounterChainRules) {
169*8542734aSAndroid Build Coastguard Worker             const std::vector<std::string> counterRules = {
170*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
171*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
172*8542734aSAndroid Build Coastguard Worker             };
173*8542734aSAndroid Build Coastguard Worker 
174*8542734aSAndroid Build Coastguard Worker             appendAll(v4Cmds, counterRules);
175*8542734aSAndroid Build Coastguard Worker             appendAll(v6Cmds, counterRules);
176*8542734aSAndroid Build Coastguard Worker         }
177*8542734aSAndroid Build Coastguard Worker 
178*8542734aSAndroid Build Coastguard Worker         appendAll(v4Cmds, {
179*8542734aSAndroid Build Coastguard Worker             "-D tetherctrl_FORWARD -j DROP",
180*8542734aSAndroid Build Coastguard Worker             "-A tetherctrl_FORWARD -j DROP",
181*8542734aSAndroid Build Coastguard Worker             "COMMIT\n",
182*8542734aSAndroid Build Coastguard Worker         });
183*8542734aSAndroid Build Coastguard Worker 
184*8542734aSAndroid Build Coastguard Worker         v6Cmds.push_back("COMMIT\n");
185*8542734aSAndroid Build Coastguard Worker 
186*8542734aSAndroid Build Coastguard Worker         return {
187*8542734aSAndroid Build Coastguard Worker             { V6, rpfilterCmd },
188*8542734aSAndroid Build Coastguard Worker             { V4, Join(v4Cmds, '\n') },
189*8542734aSAndroid Build Coastguard Worker             { V6, Join(v6Cmds, '\n') },
190*8542734aSAndroid Build Coastguard Worker         };
191*8542734aSAndroid Build Coastguard Worker     }
192*8542734aSAndroid Build Coastguard Worker 
193*8542734aSAndroid Build Coastguard Worker     constexpr static const bool WITH_COUNTERS = true;
194*8542734aSAndroid Build Coastguard Worker     constexpr static const bool NO_COUNTERS = false;
195*8542734aSAndroid Build Coastguard Worker     constexpr static const bool WITH_IPV6 = true;
196*8542734aSAndroid Build Coastguard Worker     constexpr static const bool NO_IPV6 = false;
allNewNatCommands(const char * intIf,const char * extIf,bool withCounterChainRules,bool withIPv6Upstream,bool firstEnableNat)197*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands allNewNatCommands(const char* intIf, const char* extIf,
198*8542734aSAndroid Build Coastguard Worker                                                bool withCounterChainRules, bool withIPv6Upstream,
199*8542734aSAndroid Build Coastguard Worker                                                bool firstEnableNat) {
200*8542734aSAndroid Build Coastguard Worker         ExpectedIptablesCommands commands;
201*8542734aSAndroid Build Coastguard Worker         ExpectedIptablesCommands setupFirstIPv4Commands = firstIPv4UpstreamCommands(extIf);
202*8542734aSAndroid Build Coastguard Worker         ExpectedIptablesCommands startFirstNatCommands = startNatCommands(intIf, extIf,
203*8542734aSAndroid Build Coastguard Worker             withCounterChainRules);
204*8542734aSAndroid Build Coastguard Worker 
205*8542734aSAndroid Build Coastguard Worker         appendAll(commands, setupFirstIPv4Commands);
206*8542734aSAndroid Build Coastguard Worker         if (withIPv6Upstream) {
207*8542734aSAndroid Build Coastguard Worker             ExpectedIptablesCommands setupFirstIPv6Commands = firstIPv6UpstreamCommands();
208*8542734aSAndroid Build Coastguard Worker             appendAll(commands, setupFirstIPv6Commands);
209*8542734aSAndroid Build Coastguard Worker         }
210*8542734aSAndroid Build Coastguard Worker         if (firstEnableNat) {
211*8542734aSAndroid Build Coastguard Worker             appendAll(commands, ALERT_ADD_COMMAND);
212*8542734aSAndroid Build Coastguard Worker         }
213*8542734aSAndroid Build Coastguard Worker         appendAll(commands, startFirstNatCommands);
214*8542734aSAndroid Build Coastguard Worker 
215*8542734aSAndroid Build Coastguard Worker         return commands;
216*8542734aSAndroid Build Coastguard Worker     }
217*8542734aSAndroid Build Coastguard Worker 
stopNatCommands(const char * intIf,const char * extIf)218*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) {
219*8542734aSAndroid Build Coastguard Worker         std::string rpfilterCmd = StringPrintf(
220*8542734aSAndroid Build Coastguard Worker             "*raw\n"
221*8542734aSAndroid Build Coastguard Worker             "-D tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
222*8542734aSAndroid Build Coastguard Worker             "COMMIT\n", intIf);
223*8542734aSAndroid Build Coastguard Worker 
224*8542734aSAndroid Build Coastguard Worker         std::vector<std::string> v4Cmds = {
225*8542734aSAndroid Build Coastguard Worker                 "*raw",
226*8542734aSAndroid Build Coastguard Worker                 StringPrintf(
227*8542734aSAndroid Build Coastguard Worker                         "-D tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
228*8542734aSAndroid Build Coastguard Worker                         intIf),
229*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-D tetherctrl_raw_PREROUTING -p tcp --dport 1723 -i %s -j CT "
230*8542734aSAndroid Build Coastguard Worker                              "--helper pptp",
231*8542734aSAndroid Build Coastguard Worker                              intIf),
232*8542734aSAndroid Build Coastguard Worker                 "COMMIT",
233*8542734aSAndroid Build Coastguard Worker                 "*filter",
234*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state"
235*8542734aSAndroid Build Coastguard Worker                              " ESTABLISHED,RELATED -g tetherctrl_counters",
236*8542734aSAndroid Build Coastguard Worker                              extIf, intIf),
237*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
238*8542734aSAndroid Build Coastguard Worker                              intIf, extIf),
239*8542734aSAndroid Build Coastguard Worker                 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters", intIf,
240*8542734aSAndroid Build Coastguard Worker                              extIf),
241*8542734aSAndroid Build Coastguard Worker                 "COMMIT\n",
242*8542734aSAndroid Build Coastguard Worker         };
243*8542734aSAndroid Build Coastguard Worker 
244*8542734aSAndroid Build Coastguard Worker         return {
245*8542734aSAndroid Build Coastguard Worker             { V6, rpfilterCmd },
246*8542734aSAndroid Build Coastguard Worker             { V4, Join(v4Cmds, '\n') },
247*8542734aSAndroid Build Coastguard Worker         };
248*8542734aSAndroid Build Coastguard Worker 
249*8542734aSAndroid Build Coastguard Worker     }
250*8542734aSAndroid Build Coastguard Worker };
251*8542734aSAndroid Build Coastguard Worker 
TEST_F(TetherControllerTest,TestSetupIptablesHooks)252*8542734aSAndroid Build Coastguard Worker TEST_F(TetherControllerTest, TestSetupIptablesHooks) {
253*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.setupIptablesHooks();
254*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(SETUP_COMMANDS);
255*8542734aSAndroid Build Coastguard Worker }
256*8542734aSAndroid Build Coastguard Worker 
TEST_F(TetherControllerTest,TestSetDefaults)257*8542734aSAndroid Build Coastguard Worker TEST_F(TetherControllerTest, TestSetDefaults) {
258*8542734aSAndroid Build Coastguard Worker     setDefaults();
259*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(FLUSH_COMMANDS);
260*8542734aSAndroid Build Coastguard Worker }
261*8542734aSAndroid Build Coastguard Worker 
TEST_F(TetherControllerTest,TestAddAndRemoveNat)262*8542734aSAndroid Build Coastguard Worker TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
263*8542734aSAndroid Build Coastguard Worker     // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
264*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands firstNat =
265*8542734aSAndroid Build Coastguard Worker             allNewNatCommands("wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6, true);
266*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.enableNat("wlan0", "rmnet0");
267*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(firstNat);
268*8542734aSAndroid Build Coastguard Worker 
269*8542734aSAndroid Build Coastguard Worker     // Start second NAT on same upstream. Expect only the counter rules to be created.
270*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands startOtherNatOnSameUpstream = startNatCommands(
271*8542734aSAndroid Build Coastguard Worker             "usb0", "rmnet0", WITH_COUNTERS);
272*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.enableNat("usb0", "rmnet0");
273*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(startOtherNatOnSameUpstream);
274*8542734aSAndroid Build Coastguard Worker 
275*8542734aSAndroid Build Coastguard Worker     // Remove the first NAT.
276*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
277*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.disableNat("wlan0", "rmnet0");
278*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(stopFirstNat);
279*8542734aSAndroid Build Coastguard Worker 
280*8542734aSAndroid Build Coastguard Worker     // Remove the last NAT. Expect rules to be cleared.
281*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands stopLastNat = stopNatCommands("usb0", "rmnet0");
282*8542734aSAndroid Build Coastguard Worker 
283*8542734aSAndroid Build Coastguard Worker     appendAll(stopLastNat, FLUSH_COMMANDS);
284*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.disableNat("usb0", "rmnet0");
285*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(stopLastNat);
286*8542734aSAndroid Build Coastguard Worker 
287*8542734aSAndroid Build Coastguard Worker     // Re-add a NAT removed previously: tetherctrl_counters chain rules are not re-added
288*8542734aSAndroid Build Coastguard Worker     firstNat = allNewNatCommands("wlan0", "rmnet0", NO_COUNTERS, WITH_IPV6, true);
289*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.enableNat("wlan0", "rmnet0");
290*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(firstNat);
291*8542734aSAndroid Build Coastguard Worker 
292*8542734aSAndroid Build Coastguard Worker     // Remove it again. Expect rules to be cleared.
293*8542734aSAndroid Build Coastguard Worker     stopLastNat = stopNatCommands("wlan0", "rmnet0");
294*8542734aSAndroid Build Coastguard Worker     appendAll(stopLastNat, FLUSH_COMMANDS);
295*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.disableNat("wlan0", "rmnet0");
296*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(stopLastNat);
297*8542734aSAndroid Build Coastguard Worker }
298*8542734aSAndroid Build Coastguard Worker 
TEST_F(TetherControllerTest,TestMultipleUpstreams)299*8542734aSAndroid Build Coastguard Worker TEST_F(TetherControllerTest, TestMultipleUpstreams) {
300*8542734aSAndroid Build Coastguard Worker     // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
301*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands firstNat =
302*8542734aSAndroid Build Coastguard Worker             allNewNatCommands("wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6, true);
303*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.enableNat("wlan0", "rmnet0");
304*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(firstNat);
305*8542734aSAndroid Build Coastguard Worker 
306*8542734aSAndroid Build Coastguard Worker     // Start second NAT, on new upstream. Expect the upstream and NAT rules to be created for IPv4,
307*8542734aSAndroid Build Coastguard Worker     // but no counter rules for IPv6.
308*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands secondNat =
309*8542734aSAndroid Build Coastguard Worker             allNewNatCommands("wlan0", "v4-rmnet0", WITH_COUNTERS, NO_IPV6, false);
310*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
311*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(secondNat);
312*8542734aSAndroid Build Coastguard Worker 
313*8542734aSAndroid Build Coastguard Worker     // Pretend that the caller has forgotten that it set up the second NAT, and asks us to do so
314*8542734aSAndroid Build Coastguard Worker     // again. Expect that we take no action.
315*8542734aSAndroid Build Coastguard Worker     const ExpectedIptablesCommands NONE = {};
316*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
317*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(NONE);
318*8542734aSAndroid Build Coastguard Worker 
319*8542734aSAndroid Build Coastguard Worker     // Remove the second NAT.
320*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands stopSecondNat = stopNatCommands("wlan0", "v4-rmnet0");
321*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.disableNat("wlan0", "v4-rmnet0");
322*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(stopSecondNat);
323*8542734aSAndroid Build Coastguard Worker 
324*8542734aSAndroid Build Coastguard Worker     // Remove the first NAT. Expect rules to be cleared.
325*8542734aSAndroid Build Coastguard Worker     ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
326*8542734aSAndroid Build Coastguard Worker     appendAll(stopFirstNat, FLUSH_COMMANDS);
327*8542734aSAndroid Build Coastguard Worker     mTetherCtrl.disableNat("wlan0", "rmnet0");
328*8542734aSAndroid Build Coastguard Worker     expectIptablesRestoreCommands(stopFirstNat);
329*8542734aSAndroid Build Coastguard Worker }
330*8542734aSAndroid Build Coastguard Worker 
331*8542734aSAndroid Build Coastguard Worker std::string kTetherCounterHeaders = Join(std::vector<std::string> {
332*8542734aSAndroid Build Coastguard Worker     "Chain tetherctrl_counters (4 references)",
333*8542734aSAndroid Build Coastguard Worker     "    pkts      bytes target     prot opt in     out     source               destination",
334*8542734aSAndroid Build Coastguard Worker }, '\n');
335*8542734aSAndroid Build Coastguard Worker 
336*8542734aSAndroid Build Coastguard Worker std::string kIPv4TetherCounters = Join(std::vector<std::string> {
337*8542734aSAndroid Build Coastguard Worker     "Chain tetherctrl_counters (4 references)",
338*8542734aSAndroid Build Coastguard Worker     "    pkts      bytes target     prot opt in     out     source               destination",
339*8542734aSAndroid Build Coastguard Worker     "      26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0",
340*8542734aSAndroid Build Coastguard Worker     "      27     2002 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0",
341*8542734aSAndroid Build Coastguard Worker     "    1040   107471 RETURN     all  --  bt-pan rmnet0  0.0.0.0/0            0.0.0.0/0",
342*8542734aSAndroid Build Coastguard Worker     "    1450  1708806 RETURN     all  --  rmnet0 bt-pan  0.0.0.0/0            0.0.0.0/0",
343*8542734aSAndroid Build Coastguard Worker }, '\n');
344*8542734aSAndroid Build Coastguard Worker 
345*8542734aSAndroid Build Coastguard Worker std::string kIPv6TetherCounters = Join(std::vector<std::string> {
346*8542734aSAndroid Build Coastguard Worker     "Chain tetherctrl_counters (2 references)",
347*8542734aSAndroid Build Coastguard Worker     "    pkts      bytes target     prot opt in     out     source               destination",
348*8542734aSAndroid Build Coastguard Worker     "   10000 10000000 RETURN     all  --  wlan0  rmnet0  ::/0                 ::/0",
349*8542734aSAndroid Build Coastguard Worker     "   20000 20000000 RETURN     all  --  rmnet0 wlan0   ::/0                 ::/0",
350*8542734aSAndroid Build Coastguard Worker }, '\n');
351*8542734aSAndroid Build Coastguard Worker 
expectTetherStatsEqual(const TetherController::TetherStats & expected,const TetherController::TetherStats & actual)352*8542734aSAndroid Build Coastguard Worker void expectTetherStatsEqual(const TetherController::TetherStats& expected,
353*8542734aSAndroid Build Coastguard Worker                             const TetherController::TetherStats& actual) {
354*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(expected.intIface, actual.intIface);
355*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(expected.extIface, actual.extIface);
356*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(expected.rxBytes, actual.rxBytes);
357*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(expected.txBytes, actual.txBytes);
358*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(expected.rxPackets, actual.rxPackets);
359*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(expected.txPackets, actual.txPackets);
360*8542734aSAndroid Build Coastguard Worker }
361*8542734aSAndroid Build Coastguard Worker 
TEST_F(TetherControllerTest,TestGetTetherStats)362*8542734aSAndroid Build Coastguard Worker TEST_F(TetherControllerTest, TestGetTetherStats) {
363*8542734aSAndroid Build Coastguard Worker     // Finding no headers is an error.
364*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
365*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
366*8542734aSAndroid Build Coastguard Worker 
367*8542734aSAndroid Build Coastguard Worker     // Finding only v4 or only v6 headers is an error.
368*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(kTetherCounterHeaders, "");
369*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
370*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
371*8542734aSAndroid Build Coastguard Worker 
372*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput("", kTetherCounterHeaders);
373*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
374*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
375*8542734aSAndroid Build Coastguard Worker 
376*8542734aSAndroid Build Coastguard Worker     // Finding headers but no stats is not an error.
377*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(kTetherCounterHeaders, kTetherCounterHeaders);
378*8542734aSAndroid Build Coastguard Worker     StatusOr<TetherStatsList> result = mTetherCtrl.getTetherStats();
379*8542734aSAndroid Build Coastguard Worker     ASSERT_TRUE(isOk(result));
380*8542734aSAndroid Build Coastguard Worker     TetherStatsList actual = result.value();
381*8542734aSAndroid Build Coastguard Worker     ASSERT_EQ(0U, actual.size());
382*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
383*8542734aSAndroid Build Coastguard Worker 
384*8542734aSAndroid Build Coastguard Worker 
385*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(kIPv6TetherCounters);
386*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
387*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
388*8542734aSAndroid Build Coastguard Worker 
389*8542734aSAndroid Build Coastguard Worker     // IPv4 and IPv6 counters are properly added together.
390*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
391*8542734aSAndroid Build Coastguard Worker     TetherStats expected0("wlan0", "rmnet0", 20002002, 20027, 10002373, 10026);
392*8542734aSAndroid Build Coastguard Worker     TetherStats expected1("bt-pan", "rmnet0", 1708806, 1450, 107471, 1040);
393*8542734aSAndroid Build Coastguard Worker     result = mTetherCtrl.getTetherStats();
394*8542734aSAndroid Build Coastguard Worker     ASSERT_TRUE(isOk(result));
395*8542734aSAndroid Build Coastguard Worker     actual = result.value();
396*8542734aSAndroid Build Coastguard Worker     ASSERT_EQ(2U, actual.size());
397*8542734aSAndroid Build Coastguard Worker     expectTetherStatsEqual(expected0, result.value()[0]);
398*8542734aSAndroid Build Coastguard Worker     expectTetherStatsEqual(expected1, result.value()[1]);
399*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
400*8542734aSAndroid Build Coastguard Worker 
401*8542734aSAndroid Build Coastguard Worker     // No stats: error.
402*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput("", kIPv6TetherCounters);
403*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
404*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
405*8542734aSAndroid Build Coastguard Worker 
406*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(kIPv4TetherCounters, "");
407*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
408*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
409*8542734aSAndroid Build Coastguard Worker 
410*8542734aSAndroid Build Coastguard Worker     // Include only one pair of interfaces and things are fine.
411*8542734aSAndroid Build Coastguard Worker     std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
412*8542734aSAndroid Build Coastguard Worker     std::vector<std::string> brokenCounterLines = counterLines;
413*8542734aSAndroid Build Coastguard Worker     counterLines.resize(4);
414*8542734aSAndroid Build Coastguard Worker     std::string counters = Join(counterLines, "\n") + "\n";
415*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(counters, counters);
416*8542734aSAndroid Build Coastguard Worker     TetherStats expected1_0("wlan0", "rmnet0", 4004, 54, 4746, 52);
417*8542734aSAndroid Build Coastguard Worker     result = mTetherCtrl.getTetherStats();
418*8542734aSAndroid Build Coastguard Worker     ASSERT_TRUE(isOk(result));
419*8542734aSAndroid Build Coastguard Worker     actual = result.value();
420*8542734aSAndroid Build Coastguard Worker     ASSERT_EQ(1U, actual.size());
421*8542734aSAndroid Build Coastguard Worker     expectTetherStatsEqual(expected1_0, actual[0]);
422*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
423*8542734aSAndroid Build Coastguard Worker 
424*8542734aSAndroid Build Coastguard Worker     // But if interfaces aren't paired, it's always an error.
425*8542734aSAndroid Build Coastguard Worker     counterLines.resize(3);
426*8542734aSAndroid Build Coastguard Worker     counters = Join(counterLines, "\n") + "\n";
427*8542734aSAndroid Build Coastguard Worker     addIptablesRestoreOutput(counters, counters);
428*8542734aSAndroid Build Coastguard Worker     result = mTetherCtrl.getTetherStats();
429*8542734aSAndroid Build Coastguard Worker     ASSERT_FALSE(isOk(result));
430*8542734aSAndroid Build Coastguard Worker     clearIptablesRestoreOutput();
431*8542734aSAndroid Build Coastguard Worker 
432*8542734aSAndroid Build Coastguard Worker     // Token unit test of the fact that we return the stats in the error message which the caller
433*8542734aSAndroid Build Coastguard Worker     // ignores.
434*8542734aSAndroid Build Coastguard Worker     // Skip header since we only saved the last line we parsed.
435*8542734aSAndroid Build Coastguard Worker     std::string expectedError = counterLines[2];
436*8542734aSAndroid Build Coastguard Worker     std::string err = result.status().msg();
437*8542734aSAndroid Build Coastguard Worker     ASSERT_LE(expectedError.size(), err.size());
438*8542734aSAndroid Build Coastguard Worker     EXPECT_TRUE(std::equal(expectedError.rbegin(), expectedError.rend(), err.rbegin()));
439*8542734aSAndroid Build Coastguard Worker }
440*8542734aSAndroid Build Coastguard Worker 
441*8542734aSAndroid Build Coastguard Worker }  // namespace net
442*8542734aSAndroid Build Coastguard Worker }  // namespace android
443