blob: 85a7ee1c474e993fb9389f26b99823b7b8a94959 [file] [log] [blame]
San Mehat9ff78fb2010-01-19 12:59:15 -08001/*
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
JP Abgrallbaeccc42013-06-25 09:44:10 -070017#define LOG_NDEBUG 0
JP Abgrall0031cea2012-04-17 16:38:23 -070018
San Mehat9ff78fb2010-01-19 12:59:15 -080019#include <stdlib.h>
20#include <errno.h>
21#include <sys/socket.h>
22#include <sys/stat.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080023#include <sys/wait.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080024#include <fcntl.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080027#include <string.h>
John Michelauac208602011-05-27 22:07:20 -050028#include <cutils/properties.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080029
30#define LOG_TAG "NatController"
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +090031#include <android-base/stringprintf.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080032#include <cutils/log.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080033#include <logwrap/logwrap.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080034
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +090035#include "NetdConstants.h"
San Mehat9ff78fb2010-01-19 12:59:15 -080036#include "NatController.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080037#include "NetdConstants.h"
Sreeram Ramachandran87475a12014-07-15 16:20:28 -070038#include "RouteController.h"
San Mehat9ff78fb2010-01-19 12:59:15 -080039
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +090040using android::base::StringPrintf;
41
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070042const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
Lorenzo Colittie8164dd2014-10-02 20:46:23 +090043const char* NatController::LOCAL_MANGLE_FORWARD = "natctrl_mangle_FORWARD";
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070044const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
Lorenzo Colitti8917e452016-08-01 16:47:50 +090045const char* NatController::LOCAL_RAW_PREROUTING = "natctrl_raw_PREROUTING";
JP Abgrallbaeccc42013-06-25 09:44:10 -070046const char* NatController::LOCAL_TETHER_COUNTERS_CHAIN = "natctrl_tether_counters";
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070047
Lorenzo Colitti8e1cee92016-07-09 14:24:08 +090048auto NatController::execFunction = android_fork_execvp;
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +090049auto NatController::iptablesRestoreFunction = execIptablesRestore;
Lorenzo Colitti8e1cee92016-07-09 14:24:08 +090050
Sreeram Ramachandran87475a12014-07-15 16:20:28 -070051NatController::NatController() {
San Mehat9ff78fb2010-01-19 12:59:15 -080052}
53
54NatController::~NatController() {
55}
56
JP Abgrall4ae80de2013-03-14 20:06:20 -070057struct CommandsAndArgs {
58 /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */
59 const char *cmd[32];
60 bool checkRes;
61};
62
Rom Lemarchand001f0a42013-01-31 12:41:03 -080063int NatController::runCmd(int argc, const char **argv) {
JP Abgrall11b4e9b2011-08-11 15:34:49 -070064 int res;
San Mehat9ff78fb2010-01-19 12:59:15 -080065
Lorenzo Colitti8e1cee92016-07-09 14:24:08 +090066 res = execFunction(argc, (char **)argv, NULL, false, false);
JP Abgrallbaeccc42013-06-25 09:44:10 -070067
68#if !LOG_NDEBUG
69 std::string full_cmd = argv[0];
70 argc--; argv++;
71 /*
72 * HACK: Sometimes runCmd() is called with a ridcously large value (32)
73 * and it works because the argv[] contains a NULL after the last
74 * true argv. So here we use the NULL argv[] to terminate when the argc
75 * is horribly wrong, and argc for the normal cases.
76 */
77 for (; argc && argv[0]; argc--, argv++) {
78 full_cmd += " ";
79 full_cmd += argv[0];
80 }
81 ALOGV("runCmd(%s) res=%d", full_cmd.c_str(), res);
82#endif
JP Abgrall11b4e9b2011-08-11 15:34:49 -070083 return res;
San Mehat9ff78fb2010-01-19 12:59:15 -080084}
85
JP Abgrall0031cea2012-04-17 16:38:23 -070086int NatController::setupIptablesHooks() {
JP Abgrallbaeccc42013-06-25 09:44:10 -070087 int res;
88 res = setDefaults();
89 if (res < 0) {
90 return res;
91 }
92
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +090093 // Used to limit downstream mss to the upstream pmtu so we don't end up fragmenting every large
94 // packet tethered devices send. This is IPv4-only, because in IPv6 we send the MTU in the RA.
95 // This is no longer optional and tethering will fail to start if it fails.
96 std::string mssRewriteCommand = StringPrintf(
97 "*mangle\n"
98 "-A %s -p tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu\n"
99 "COMMIT\n", LOCAL_MANGLE_FORWARD);
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900100
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +0900101 // This is for tethering counters. This chain is reached via --goto, and then RETURNS.
102 std::string defaultCommands = StringPrintf(
103 "*filter\n"
104 ":%s -\n"
105 "COMMIT\n", LOCAL_TETHER_COUNTERS_CHAIN);
106
107 res = iptablesRestoreFunction(V4, mssRewriteCommand);
108 if (res < 0) {
109 return res;
JP Abgrallbaeccc42013-06-25 09:44:10 -0700110 }
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +0900111
112 res = iptablesRestoreFunction(V4V6, defaultCommands);
113 if (res < 0) {
114 return res;
115 }
116
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700117 ifacePairList.clear();
JP Abgrallbaeccc42013-06-25 09:44:10 -0700118
JP Abgrall0031cea2012-04-17 16:38:23 -0700119 return 0;
120}
121
122int NatController::setDefaults() {
Lorenzo Colitti4fcb4a02017-02-03 14:08:37 +0900123 std::string v4Cmd = StringPrintf(
124 "*filter\n"
125 ":%s -\n"
126 "-A %s -j DROP\n"
127 "COMMIT\n"
128 "*nat\n"
129 ":%s -\n"
130 "COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
131
132 std::string v6Cmd = StringPrintf(
133 "*filter\n"
134 ":%s -\n"
135 "COMMIT\n"
136 "*raw\n"
137 ":%s -\n"
138 "COMMIT\n", LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
139
140 int res = iptablesRestoreFunction(V4, v4Cmd);
141 if (res < 0) {
142 return res;
143 }
144
145 res = iptablesRestoreFunction(V6, v6Cmd);
146 if (res < 0) {
147 return res;
JP Abgrall4ae80de2013-03-14 20:06:20 -0700148 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700149
150 natCount = 0;
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600151
San Mehat9ff78fb2010-01-19 12:59:15 -0800152 return 0;
153}
154
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700155int NatController::enableNat(const char* intIface, const char* extIface) {
JP Abgrallbaeccc42013-06-25 09:44:10 -0700156 ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
157
JP Abgrall69261cb2014-06-19 18:35:24 -0700158 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800159 errno = ENODEV;
160 return -1;
161 }
162
JP Abgrallbaeccc42013-06-25 09:44:10 -0700163 /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
164 if (!strcmp(intIface, extIface)) {
165 ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
166 errno = EINVAL;
167 return -1;
168 }
169
JP Abgrall659692a2013-03-14 20:07:17 -0700170 // add this if we are the first added nat
171 if (natCount == 0) {
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900172 const char *v4Cmd[] = {
JP Abgrall659692a2013-03-14 20:07:17 -0700173 IPTABLES_PATH,
Paul Jensen94b2ab92015-08-04 10:35:05 -0400174 "-w",
JP Abgrall659692a2013-03-14 20:07:17 -0700175 "-t",
176 "nat",
177 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700178 LOCAL_NAT_POSTROUTING,
JP Abgrall659692a2013-03-14 20:07:17 -0700179 "-o",
180 extIface,
181 "-j",
182 "MASQUERADE"
183 };
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900184
185 /*
186 * IPv6 tethering doesn't need the state-based conntrack rules, so
187 * it unconditionally jumps to the tether counters chain all the time.
188 */
189 const char *v6Cmd[] = {IP6TABLES_PATH, "-w", "-A", LOCAL_FORWARD,
190 "-g", LOCAL_TETHER_COUNTERS_CHAIN};
191
192 if (runCmd(ARRAY_SIZE(v4Cmd), v4Cmd) || runCmd(ARRAY_SIZE(v6Cmd), v6Cmd)) {
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700193 ALOGE("Error setting postroute rule: iface=%s", extIface);
JP Abgrall659692a2013-03-14 20:07:17 -0700194 // unwind what's been done, but don't care about success - what more could we do?
JP Abgrall659692a2013-03-14 20:07:17 -0700195 setDefaults();
196 return -1;
197 }
198 }
199
JP Abgrall659692a2013-03-14 20:07:17 -0700200 if (setForwardRules(true, intIface, extIface) != 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000201 ALOGE("Error setting forward rules");
JP Abgrall659692a2013-03-14 20:07:17 -0700202 if (natCount == 0) {
203 setDefaults();
204 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700205 errno = ENODEV;
206 return -1;
207 }
208
JP Abgrall0031cea2012-04-17 16:38:23 -0700209 /* Always make sure the drop rule is at the end */
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800210 const char *cmd1[] = {
211 IPTABLES_PATH,
Paul Jensen94b2ab92015-08-04 10:35:05 -0400212 "-w",
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800213 "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700214 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800215 "-j",
216 "DROP"
217 };
218 runCmd(ARRAY_SIZE(cmd1), cmd1);
219 const char *cmd2[] = {
220 IPTABLES_PATH,
Paul Jensen94b2ab92015-08-04 10:35:05 -0400221 "-w",
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800222 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700223 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800224 "-j",
225 "DROP"
226 };
227 runCmd(ARRAY_SIZE(cmd2), cmd2);
JP Abgrall0031cea2012-04-17 16:38:23 -0700228
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700229 natCount++;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700230 return 0;
231}
232
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700233bool NatController::checkTetherCountingRuleExist(const char *pair_name) {
234 std::list<std::string>::iterator it;
235
236 for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
237 if (*it == pair_name) {
238 /* We already have this counter */
239 return true;
240 }
241 }
242 return false;
243}
244
JP Abgrallbaeccc42013-06-25 09:44:10 -0700245int NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
246
247 /* We only ever add tethering quota rules so that they stick. */
248 if (!add) {
249 return 0;
250 }
Sreeram Ramachandran56afacf2014-05-28 15:07:00 -0700251 char *pair_name;
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700252 asprintf(&pair_name, "%s_%s", intIface, extIface);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700253
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700254 if (checkTetherCountingRuleExist(pair_name)) {
255 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700256 return 0;
257 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700258 const char *cmd2b[] = {
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900259 IPTABLES_PATH,
260 "-w", "-A", LOCAL_TETHER_COUNTERS_CHAIN, "-i", intIface, "-o", extIface, "-j", "RETURN"
JP Abgrallbaeccc42013-06-25 09:44:10 -0700261 };
262
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900263 const char *cmd2c[] = {
264 IP6TABLES_PATH,
265 "-w", "-A", LOCAL_TETHER_COUNTERS_CHAIN, "-i", intIface, "-o", extIface, "-j", "RETURN"
266 };
267
268 if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) || runCmd(ARRAY_SIZE(cmd2c), cmd2c)) {
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700269 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700270 return -1;
271 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700272 ifacePairList.push_front(pair_name);
273 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700274
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700275 asprintf(&pair_name, "%s_%s", extIface, intIface);
276 if (checkTetherCountingRuleExist(pair_name)) {
277 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700278 return 0;
279 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700280
281 const char *cmd3b[] = {
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900282 IPTABLES_PATH,
283 "-w", "-A", LOCAL_TETHER_COUNTERS_CHAIN, "-i", extIface, "-o", intIface, "-j", "RETURN"
JP Abgrallbaeccc42013-06-25 09:44:10 -0700284 };
285
Lorenzo Colitti05cfd252016-07-10 23:15:46 +0900286 const char *cmd3c[] = {
287 IP6TABLES_PATH,
288 "-w", "-A", LOCAL_TETHER_COUNTERS_CHAIN, "-i", extIface, "-o", intIface, "-j", "RETURN"
289 };
290
291 if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) || runCmd(ARRAY_SIZE(cmd3c), cmd3c)) {
JP Abgrallbaeccc42013-06-25 09:44:10 -0700292 // unwind what's been done, but don't care about success - what more could we do?
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700293 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700294 return -1;
295 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700296 ifacePairList.push_front(pair_name);
297 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700298 return 0;
299}
300
301int NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800302 const char *cmd1[] = {
303 IPTABLES_PATH,
Paul Jensen94b2ab92015-08-04 10:35:05 -0400304 "-w",
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800305 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700306 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800307 "-i",
308 extIface,
309 "-o",
310 intIface,
311 "-m",
312 "state",
313 "--state",
314 "ESTABLISHED,RELATED",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700315 "-g",
316 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800317 };
318 int rc = 0;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700319
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800320 if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800321 return -1;
322 }
323
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800324 const char *cmd2[] = {
325 IPTABLES_PATH,
Paul Jensen94b2ab92015-08-04 10:35:05 -0400326 "-w",
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800327 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700328 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800329 "-i",
330 intIface,
331 "-o",
332 extIface,
333 "-m",
334 "state",
335 "--state",
336 "INVALID",
337 "-j",
338 "DROP"
339 };
340
341 const char *cmd3[] = {
342 IPTABLES_PATH,
Paul Jensen94b2ab92015-08-04 10:35:05 -0400343 "-w",
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800344 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700345 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800346 "-i",
347 intIface,
348 "-o",
349 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700350 "-g",
351 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800352 };
353
Lorenzo Colitti8917e452016-08-01 16:47:50 +0900354 const char *cmd4[] = {
355 IP6TABLES_PATH,
356 "-w",
357 "-t",
358 "raw",
359 add ? "-A" : "-D",
360 LOCAL_RAW_PREROUTING,
361 "-i",
362 intIface,
363 "-m",
364 "rpfilter",
365 "--invert",
366 "!",
367 "-s",
368 "fe80::/64",
369 "-j",
370 "DROP"
371 };
372
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800373 if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
Robert Greenwaltf7bf29c2011-11-01 22:07:28 -0700374 // bail on error, but only if adding
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800375 rc = -1;
376 goto err_invalid_drop;
Robert Greenwaltddb9f6e2011-08-02 13:00:11 -0700377 }
378
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800379 if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
Robert Greenwalt210b9772010-03-25 14:54:45 -0700380 // unwind what's been done, but don't care about success - what more could we do?
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800381 rc = -1;
382 goto err_return;
San Mehat9ff78fb2010-01-19 12:59:15 -0800383 }
JP Abgrall0031cea2012-04-17 16:38:23 -0700384
Lorenzo Colittibd96d952016-08-01 18:14:31 +0900385 if (runCmd(ARRAY_SIZE(cmd4), cmd4) && add) {
Lorenzo Colitti8917e452016-08-01 16:47:50 +0900386 rc = -1;
387 goto err_rpfilter;
388 }
389
JP Abgrallbaeccc42013-06-25 09:44:10 -0700390 if (setTetherCountingRules(add, intIface, extIface) && add) {
391 rc = -1;
392 goto err_return;
393 }
394
San Mehat9ff78fb2010-01-19 12:59:15 -0800395 return 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800396
Lorenzo Colitti8917e452016-08-01 16:47:50 +0900397err_rpfilter:
398 cmd3[2] = "-D";
399 runCmd(ARRAY_SIZE(cmd3), cmd3);
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800400err_return:
Paul Jensen94b2ab92015-08-04 10:35:05 -0400401 cmd2[2] = "-D";
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800402 runCmd(ARRAY_SIZE(cmd2), cmd2);
403err_invalid_drop:
Paul Jensen94b2ab92015-08-04 10:35:05 -0400404 cmd1[2] = "-D";
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800405 runCmd(ARRAY_SIZE(cmd1), cmd1);
406 return rc;
San Mehat9ff78fb2010-01-19 12:59:15 -0800407}
408
Sreeram Ramachandran87475a12014-07-15 16:20:28 -0700409int NatController::disableNat(const char* intIface, const char* extIface) {
JP Abgrall69261cb2014-06-19 18:35:24 -0700410 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700411 errno = ENODEV;
412 return -1;
413 }
414
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700415 setForwardRules(false, intIface, extIface);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700416 if (--natCount <= 0) {
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600417 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
418 setDefaults();
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700419 }
420 return 0;
San Mehat9ff78fb2010-01-19 12:59:15 -0800421}