1 /* 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 * NatControllerTest.cpp - unit tests for NatController.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 "NatController.h" 33 #include "IptablesBaseTest.h" 34 35 using android::base::StringPrintf; 36 37 class NatControllerTest : public IptablesBaseTest { 38 public: 39 NatControllerTest() { 40 NatController::execFunction = fake_android_fork_exec; 41 NatController::iptablesRestoreFunction = fakeExecIptablesRestore; 42 } 43 44 protected: 45 NatController mNatCtrl; 46 47 int setDefaults() { 48 return mNatCtrl.setDefaults(); 49 } 50 51 const ExpectedIptablesCommands FLUSH_COMMANDS = { 52 { V4, "*filter\n" 53 ":natctrl_FORWARD -\n" 54 "-A natctrl_FORWARD -j DROP\n" 55 "COMMIT\n" 56 "*nat\n" 57 ":natctrl_nat_POSTROUTING -\n" 58 "COMMIT\n" }, 59 { V6, "*filter\n" 60 ":natctrl_FORWARD -\n" 61 "COMMIT\n" 62 "*raw\n" 63 ":natctrl_raw_PREROUTING -\n" 64 "COMMIT\n" }, 65 }; 66 67 const ExpectedIptablesCommands SETUP_COMMANDS = { 68 { V4, "*filter\n" 69 ":natctrl_FORWARD -\n" 70 "-A natctrl_FORWARD -j DROP\n" 71 "COMMIT\n" 72 "*nat\n" 73 ":natctrl_nat_POSTROUTING -\n" 74 "COMMIT\n" }, 75 { V6, "*filter\n" 76 ":natctrl_FORWARD -\n" 77 "COMMIT\n" 78 "*raw\n" 79 ":natctrl_raw_PREROUTING -\n" 80 "COMMIT\n" }, 81 { V4, "*mangle\n" 82 "-A natctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN " 83 "-j TCPMSS --clamp-mss-to-pmtu\n" 84 "COMMIT\n" }, 85 { V4V6, "*filter\n" 86 ":natctrl_tether_counters -\n" 87 "COMMIT\n" }, 88 }; 89 90 const ExpectedIptablesCommands TWIDDLE_COMMANDS = { 91 { V4, "-D natctrl_FORWARD -j DROP" }, 92 { V4, "-A natctrl_FORWARD -j DROP" }, 93 }; 94 95 ExpectedIptablesCommands firstNatCommands(const char *extIf) { 96 return { 97 { V4, StringPrintf("-t nat -A natctrl_nat_POSTROUTING -o %s -j MASQUERADE", extIf) }, 98 { V6, "-A natctrl_FORWARD -g natctrl_tether_counters" }, 99 }; 100 } 101 102 ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf) { 103 return { 104 { V4, StringPrintf("-A natctrl_FORWARD -i %s -o %s -m state --state" 105 " ESTABLISHED,RELATED -g natctrl_tether_counters", extIf, intIf) }, 106 { V4, StringPrintf("-A natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP", 107 intIf, extIf) }, 108 { V4, StringPrintf("-A natctrl_FORWARD -i %s -o %s -g natctrl_tether_counters", 109 intIf, extIf) }, 110 { V6, StringPrintf("-t raw -A natctrl_raw_PREROUTING -i %s -m rpfilter --invert" 111 " ! -s fe80::/64 -j DROP", intIf) }, 112 { V4V6, StringPrintf("-A natctrl_tether_counters -i %s -o %s -j RETURN", 113 intIf, extIf) }, 114 { V4V6, StringPrintf("-A natctrl_tether_counters -i %s -o %s -j RETURN", 115 extIf, intIf) }, 116 }; 117 } 118 119 ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) { 120 return { 121 { V4, StringPrintf("-D natctrl_FORWARD -i %s -o %s -m state --state" 122 " ESTABLISHED,RELATED -g natctrl_tether_counters", extIf, intIf) }, 123 { V4, StringPrintf("-D natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP", 124 intIf, extIf) }, 125 { V4, StringPrintf("-D natctrl_FORWARD -i %s -o %s -g natctrl_tether_counters", 126 intIf, extIf) }, 127 { V6, StringPrintf("-t raw -D natctrl_raw_PREROUTING -i %s -m rpfilter --invert" 128 " ! -s fe80::/64 -j DROP", intIf) }, 129 }; 130 } 131 }; 132 133 TEST_F(NatControllerTest, TestSetupIptablesHooks) { 134 mNatCtrl.setupIptablesHooks(); 135 expectIptablesRestoreCommands(SETUP_COMMANDS); 136 } 137 138 TEST_F(NatControllerTest, TestSetDefaults) { 139 setDefaults(); 140 expectIptablesRestoreCommands(FLUSH_COMMANDS); 141 } 142 143 TEST_F(NatControllerTest, TestAddAndRemoveNat) { 144 145 std::vector<ExpectedIptablesCommands> startFirstNat = { 146 firstNatCommands("rmnet0"), 147 startNatCommands("wlan0", "rmnet0"), 148 TWIDDLE_COMMANDS, 149 }; 150 mNatCtrl.enableNat("wlan0", "rmnet0"); 151 expectIptablesCommands(startFirstNat); 152 153 std::vector<ExpectedIptablesCommands> startOtherNat = { 154 startNatCommands("usb0", "rmnet0"), 155 TWIDDLE_COMMANDS, 156 }; 157 mNatCtrl.enableNat("usb0", "rmnet0"); 158 expectIptablesCommands(startOtherNat); 159 160 ExpectedIptablesCommands stopOtherNat = stopNatCommands("wlan0", "rmnet0"); 161 mNatCtrl.disableNat("wlan0", "rmnet0"); 162 expectIptablesCommands(stopOtherNat); 163 164 ExpectedIptablesCommands stopLastNat = stopNatCommands("usb0", "rmnet0"); 165 mNatCtrl.disableNat("usb0", "rmnet0"); 166 expectIptablesCommands(stopLastNat); 167 expectIptablesRestoreCommands(FLUSH_COMMANDS); 168 } 169