1 /*
2 * Copyright (C) 2008 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
17 #define LOG_NDEBUG 0
18
19 #include <string>
20 #include <vector>
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <arpa/inet.h>
27 #include <linux/in.h>
28 #include <netinet/in.h>
29 #include <sys/socket.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32
33 #define LOG_TAG "NatController"
34 #include <android-base/strings.h>
35 #include <android-base/stringprintf.h>
36 #include <cutils/log.h>
37 #include <cutils/properties.h>
38 #include <logwrap/logwrap.h>
39
40 #include "NatController.h"
41 #include "NetdConstants.h"
42 #include "RouteController.h"
43
44 using android::base::Join;
45 using android::base::StringPrintf;
46
47 const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
48 const char* NatController::LOCAL_MANGLE_FORWARD = "natctrl_mangle_FORWARD";
49 const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
50 const char* NatController::LOCAL_RAW_PREROUTING = "natctrl_raw_PREROUTING";
51 const char* NatController::LOCAL_TETHER_COUNTERS_CHAIN = "natctrl_tether_counters";
52
53 auto NatController::execFunction = android_fork_execvp;
54 auto NatController::iptablesRestoreFunction = execIptablesRestore;
55
NatController()56 NatController::NatController() {
57 }
58
~NatController()59 NatController::~NatController() {
60 }
61
62 struct CommandsAndArgs {
63 /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */
64 const char *cmd[32];
65 bool checkRes;
66 };
67
setupIptablesHooks()68 int NatController::setupIptablesHooks() {
69 int res;
70 res = setDefaults();
71 if (res < 0) {
72 return res;
73 }
74
75 // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large
76 // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA.
77 // This is no longer optional and tethering will fail to start if it fails.
78 std::string mssRewriteCommand = StringPrintf(
79 "*mangle\n"
80 "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n"
81 "COMMIT\n", LOCAL_MANGLE_FORWARD);
82
83 // This is for tethering counters. This chain is reached via --goto, and then RETURNS.
84 std::string defaultCommands = StringPrintf(
85 "*filter\n"
86 ":%s -\n"
87 "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN);
88
89 res = iptablesRestoreFunction(V4, mssRewriteCommand);
90 if (res < 0) {
91 return res;
92 }
93
94 res = iptablesRestoreFunction(V4V6, defaultCommands);
95 if (res < 0) {
96 return res;
97 }
98
99 ifacePairList.clear();
100
101 return 0;
102 }
103
setDefaults()104 int NatController::setDefaults() {
105 std::string v4Cmd = StringPrintf(
106 "*filter\n"
107 ":%s -\n"
108 "-A %s -j DROP\n"
109 "COMMIT\n"
110 "*nat\n"
111 ":%s -\n"
112 "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
113
114 std::string v6Cmd = StringPrintf(
115 "*filter\n"
116 ":%s -\n"
117 "COMMIT\n"
118 "*raw\n"
119 ":%s -\n"
120 "COMMIT\n", LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
121
122 int res = iptablesRestoreFunction(V4, v4Cmd);
123 if (res < 0) {
124 return res;
125 }
126
127 res = iptablesRestoreFunction(V6, v6Cmd);
128 if (res < 0) {
129 return res;
130 }
131
132 natCount = 0;
133
134 return 0;
135 }
136
enableNat(const char * intIface,const char * extIface)137 int NatController::enableNat(const char* intIface, const char* extIface) {
138 ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
139
140 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
141 errno = ENODEV;
142 return -1;
143 }
144
145 /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
146 if (!strcmp(intIface, extIface)) {
147 ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
148 errno = EINVAL;
149 return -1;
150 }
151
152 // add this if we are the first added nat
153 if (natCount == 0) {
154 std::vector<std::string> v4Cmds = {
155 "*nat",
156 StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
157 "COMMIT\n"
158 };
159
160 /*
161 * IPv6 tethering doesn't need the state-based conntrack rules, so
162 * it unconditionally jumps to the tether counters chain all the time.
163 */
164 std::vector<std::string> v6Cmds = {
165 "*filter",
166 StringPrintf("-A %s -g %s", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN),
167 "COMMIT\n"
168 };
169
170 if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n')) ||
171 iptablesRestoreFunction(V6, Join(v6Cmds, '\n'))) {
172 ALOGE("Error setting postroute rule: iface=%s", extIface);
173 // unwind what's been done, but don't care about success - what more could we do?
174 setDefaults();
175 return -1;
176 }
177 }
178
179 if (setForwardRules(true, intIface, extIface) != 0) {
180 ALOGE("Error setting forward rules");
181 if (natCount == 0) {
182 setDefaults();
183 }
184 errno = ENODEV;
185 return -1;
186 }
187
188 natCount++;
189 return 0;
190 }
191
checkTetherCountingRuleExist(const std::string & pair_name)192 bool NatController::checkTetherCountingRuleExist(const std::string& pair_name) {
193 return std::find(ifacePairList.begin(), ifacePairList.end(), pair_name) != ifacePairList.end();
194 }
195
196 /* static */
makeTetherCountingRule(const char * if1,const char * if2)197 std::string NatController::makeTetherCountingRule(const char *if1, const char *if2) {
198 return StringPrintf("-A %s -i %s -o %s -j RETURN", LOCAL_TETHER_COUNTERS_CHAIN, if1, if2);
199 }
200
setForwardRules(bool add,const char * intIface,const char * extIface)201 int NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
202 const char *op = add ? "-A" : "-D";
203
204 std::string rpfilterCmd = StringPrintf(
205 "*raw\n"
206 "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
207 "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface);
208 if (iptablesRestoreFunction(V6, rpfilterCmd) == -1 && add) {
209 return -1;
210 }
211
212 std::vector<std::string> v4 = {
213 "*filter",
214 StringPrintf("%s %s -i %s -o %s -m state --state ESTABLISHED,RELATED -g %s",
215 op, LOCAL_FORWARD, extIface, intIface, LOCAL_TETHER_COUNTERS_CHAIN),
216 StringPrintf("%s %s -i %s -o %s -m state --state INVALID -j DROP",
217 op, LOCAL_FORWARD, intIface, extIface),
218 StringPrintf("%s %s -i %s -o %s -g %s",
219 op, LOCAL_FORWARD, intIface, extIface, LOCAL_TETHER_COUNTERS_CHAIN),
220 };
221
222 std::vector<std::string> v6 = {
223 "*filter",
224 };
225
226 /* We only ever add tethering quota rules so that they stick. */
227 std::string pair1 = StringPrintf("%s_%s", intIface, extIface);
228 if (add && !checkTetherCountingRuleExist(pair1)) {
229 v4.push_back(makeTetherCountingRule(intIface, extIface));
230 v6.push_back(makeTetherCountingRule(intIface, extIface));
231 }
232 std::string pair2 = StringPrintf("%s_%s", extIface, intIface);
233 if (add && !checkTetherCountingRuleExist(pair2)) {
234 v4.push_back(makeTetherCountingRule(extIface, intIface));
235 v6.push_back(makeTetherCountingRule(extIface, intIface));
236 }
237
238 // Always make sure the drop rule is at the end.
239 // TODO: instead of doing this, consider just rebuilding LOCAL_FORWARD completely from scratch
240 // every time, starting with ":natctrl_FORWARD -\n". This method would likely be a bit simpler.
241 if (add) {
242 v4.push_back(StringPrintf("-D %s -j DROP", LOCAL_FORWARD));
243 v4.push_back(StringPrintf("-A %s -j DROP", LOCAL_FORWARD));
244 }
245
246 v4.push_back("COMMIT\n");
247 v6.push_back("COMMIT\n");
248
249 // We only add IPv6 rules here, never remove them.
250 if (iptablesRestoreFunction(V4, Join(v4, '\n')) == -1 ||
251 (add && iptablesRestoreFunction(V6, Join(v6, '\n')) == -1)) {
252 // unwind what's been done, but don't care about success - what more could we do?
253 if (add) {
254 setForwardRules(false, intIface, extIface);
255 }
256 return -1;
257 }
258
259 if (add && !checkTetherCountingRuleExist(pair1)) {
260 ifacePairList.push_front(pair1);
261 }
262 if (add && !checkTetherCountingRuleExist(pair2)) {
263 ifacePairList.push_front(pair2);
264 }
265
266 return 0;
267 }
268
disableNat(const char * intIface,const char * extIface)269 int NatController::disableNat(const char* intIface, const char* extIface) {
270 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
271 errno = ENODEV;
272 return -1;
273 }
274
275 setForwardRules(false, intIface, extIface);
276 if (--natCount <= 0) {
277 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
278 setDefaults();
279 }
280 return 0;
281 }
282