blob: 44b8b4a462946c88b57d62e2e3b43a5eec00992e [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"
31#include <cutils/log.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080032#include <logwrap/logwrap.h>
San Mehat9ff78fb2010-01-19 12:59:15 -080033
34#include "NatController.h"
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050035#include "NetworkController.h"
Robert Greenwaltfc97b822011-11-02 16:48:36 -070036#include "SecondaryTableController.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080037#include "NetdConstants.h"
San Mehat9ff78fb2010-01-19 12:59:15 -080038
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070039const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
40const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
JP Abgrallbaeccc42013-06-25 09:44:10 -070041const char* NatController::LOCAL_TETHER_COUNTERS_CHAIN = "natctrl_tether_counters";
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070042
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050043NatController::NatController(SecondaryTableController *table_ctrl, NetworkController* net_ctrl) :
44 mSecondaryTableCtrl(table_ctrl), mNetCtrl(net_ctrl) {
San Mehat9ff78fb2010-01-19 12:59:15 -080045}
46
47NatController::~NatController() {
48}
49
JP Abgrall4ae80de2013-03-14 20:06:20 -070050struct CommandsAndArgs {
51 /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */
52 const char *cmd[32];
53 bool checkRes;
54};
55
Rom Lemarchand001f0a42013-01-31 12:41:03 -080056int NatController::runCmd(int argc, const char **argv) {
JP Abgrall11b4e9b2011-08-11 15:34:49 -070057 int res;
San Mehat9ff78fb2010-01-19 12:59:15 -080058
Rom Lemarchand001f0a42013-01-31 12:41:03 -080059 res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
JP Abgrallbaeccc42013-06-25 09:44:10 -070060
61#if !LOG_NDEBUG
62 std::string full_cmd = argv[0];
63 argc--; argv++;
64 /*
65 * HACK: Sometimes runCmd() is called with a ridcously large value (32)
66 * and it works because the argv[] contains a NULL after the last
67 * true argv. So here we use the NULL argv[] to terminate when the argc
68 * is horribly wrong, and argc for the normal cases.
69 */
70 for (; argc && argv[0]; argc--, argv++) {
71 full_cmd += " ";
72 full_cmd += argv[0];
73 }
74 ALOGV("runCmd(%s) res=%d", full_cmd.c_str(), res);
75#endif
JP Abgrall11b4e9b2011-08-11 15:34:49 -070076 return res;
San Mehat9ff78fb2010-01-19 12:59:15 -080077}
78
JP Abgrall0031cea2012-04-17 16:38:23 -070079int NatController::setupIptablesHooks() {
JP Abgrallbaeccc42013-06-25 09:44:10 -070080 int res;
81 res = setDefaults();
82 if (res < 0) {
83 return res;
84 }
85
86 struct CommandsAndArgs defaultCommands[] = {
87 /*
88 * Chain for tethering counters.
89 * This chain is reached via --goto, and then RETURNS.
90 */
91 {{IPTABLES_PATH, "-F", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
92 {{IPTABLES_PATH, "-X", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
93 {{IPTABLES_PATH, "-N", LOCAL_TETHER_COUNTERS_CHAIN,}, 1},
94 };
95 for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
96 if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
97 defaultCommands[cmdNum].checkRes) {
98 return -1;
99 }
100 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700101 ifacePairList.clear();
JP Abgrallbaeccc42013-06-25 09:44:10 -0700102
JP Abgrall0031cea2012-04-17 16:38:23 -0700103 return 0;
104}
105
106int NatController::setDefaults() {
JP Abgrallbaeccc42013-06-25 09:44:10 -0700107 /*
108 * The following only works because:
109 * - the defaultsCommands[].cmd array is padded with NULL, and
110 * - the 1st argc of runCmd() will just be the max for the CommandsAndArgs[].cmd, and
111 * - internally it will be memcopied to an array and terminated with a NULL.
112 */
JP Abgrall4ae80de2013-03-14 20:06:20 -0700113 struct CommandsAndArgs defaultCommands[] = {
JP Abgrallbaeccc42013-06-25 09:44:10 -0700114 {{IPTABLES_PATH, "-F", LOCAL_FORWARD,}, 1},
115 {{IPTABLES_PATH, "-A", LOCAL_FORWARD, "-j", "DROP"}, 1},
116 {{IPTABLES_PATH, "-t", "nat", "-F", LOCAL_NAT_POSTROUTING}, 1},
JP Abgrall4ae80de2013-03-14 20:06:20 -0700117 {{IP_PATH, "rule", "flush"}, 0},
118 {{IP_PATH, "-6", "rule", "flush"}, 0},
119 {{IP_PATH, "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
120 {{IP_PATH, "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
121 {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
122 {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
123 {{IP_PATH, "route", "flush", "cache"}, 0},
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800124 };
JP Abgrall4ae80de2013-03-14 20:06:20 -0700125 for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
126 if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
127 defaultCommands[cmdNum].checkRes) {
128 return -1;
129 }
130 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700131
132 natCount = 0;
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600133
San Mehat9ff78fb2010-01-19 12:59:15 -0800134 return 0;
135}
136
JP Abgrall4ae80de2013-03-14 20:06:20 -0700137int NatController::routesOp(bool add, const char *intIface, const char *extIface, char **argv, int addrCount) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500138 unsigned netId = mNetCtrl->getNetworkId(extIface);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700139 int ret = 0;
140
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500141 for (int i = 0; i < addrCount; i++) {
142 if (add) {
143 ret |= mSecondaryTableCtrl->modifyFromRule(netId, ADD, argv[5+i]);
144 ret |= mSecondaryTableCtrl->modifyLocalRoute(netId, ADD, intIface, argv[5+i]);
145 } else {
146 ret |= mSecondaryTableCtrl->modifyLocalRoute(netId, DEL, intIface, argv[5+i]);
147 ret |= mSecondaryTableCtrl->modifyFromRule(netId, DEL, argv[5+i]);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700148 }
JP Abgrall4ae80de2013-03-14 20:06:20 -0700149 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500150 const char *cmd[] = {
151 IP_PATH,
152 "route",
153 "flush",
154 "cache"
155 };
156 runCmd(ARRAY_SIZE(cmd), cmd);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700157 return ret;
158}
159
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700160// 0 1 2 3 4 5
161// nat enable intface extface addrcnt nated-ipaddr/prelength
162int NatController::enableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700163 int addrCount = atoi(argv[4]);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700164 const char *intIface = argv[2];
165 const char *extIface = argv[3];
San Mehat9ff78fb2010-01-19 12:59:15 -0800166
JP Abgrallbaeccc42013-06-25 09:44:10 -0700167 ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
168
JP Abgrall69261cb2014-06-19 18:35:24 -0700169 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800170 errno = ENODEV;
171 return -1;
172 }
173
JP Abgrallbaeccc42013-06-25 09:44:10 -0700174 /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
175 if (!strcmp(intIface, extIface)) {
176 ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
177 errno = EINVAL;
178 return -1;
179 }
180
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700181 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000182 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700183 errno = EINVAL;
184 return -1;
185 }
JP Abgrall659692a2013-03-14 20:07:17 -0700186 if (routesOp(true, intIface, extIface, argv, addrCount)) {
187 ALOGE("Error setting route rules");
188 routesOp(false, intIface, extIface, argv, addrCount);
189 errno = ENODEV;
190 return -1;
191 }
192
193 // add this if we are the first added nat
194 if (natCount == 0) {
195 const char *cmd[] = {
196 IPTABLES_PATH,
197 "-t",
198 "nat",
199 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700200 LOCAL_NAT_POSTROUTING,
JP Abgrall659692a2013-03-14 20:07:17 -0700201 "-o",
202 extIface,
203 "-j",
204 "MASQUERADE"
205 };
206 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
207 ALOGE("Error seting postroute rule: iface=%s", extIface);
208 // unwind what's been done, but don't care about success - what more could we do?
209 routesOp(false, intIface, extIface, argv, addrCount);
210 setDefaults();
211 return -1;
212 }
213 }
214
215
216 if (setForwardRules(true, intIface, extIface) != 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000217 ALOGE("Error setting forward rules");
JP Abgrall4ae80de2013-03-14 20:06:20 -0700218 routesOp(false, intIface, extIface, argv, addrCount);
JP Abgrall659692a2013-03-14 20:07:17 -0700219 if (natCount == 0) {
220 setDefaults();
221 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700222 errno = ENODEV;
223 return -1;
224 }
225
JP Abgrall0031cea2012-04-17 16:38:23 -0700226 /* Always make sure the drop rule is at the end */
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800227 const char *cmd1[] = {
228 IPTABLES_PATH,
229 "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700230 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800231 "-j",
232 "DROP"
233 };
234 runCmd(ARRAY_SIZE(cmd1), cmd1);
235 const char *cmd2[] = {
236 IPTABLES_PATH,
237 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700238 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800239 "-j",
240 "DROP"
241 };
242 runCmd(ARRAY_SIZE(cmd2), cmd2);
JP Abgrall0031cea2012-04-17 16:38:23 -0700243
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700244 natCount++;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700245 return 0;
246}
247
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700248bool NatController::checkTetherCountingRuleExist(const char *pair_name) {
249 std::list<std::string>::iterator it;
250
251 for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
252 if (*it == pair_name) {
253 /* We already have this counter */
254 return true;
255 }
256 }
257 return false;
258}
259
JP Abgrallbaeccc42013-06-25 09:44:10 -0700260int NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
261
262 /* We only ever add tethering quota rules so that they stick. */
263 if (!add) {
264 return 0;
265 }
Sreeram Ramachandran56afacf2014-05-28 15:07:00 -0700266 char *pair_name;
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700267 asprintf(&pair_name, "%s_%s", intIface, extIface);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700268
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700269 if (checkTetherCountingRuleExist(pair_name)) {
270 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700271 return 0;
272 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700273 const char *cmd2b[] = {
274 IPTABLES_PATH,
275 "-A",
276 LOCAL_TETHER_COUNTERS_CHAIN,
277 "-i",
278 intIface,
279 "-o",
280 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700281 "-j",
282 "RETURN"
283 };
284
285 if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) && add) {
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700286 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700287 return -1;
288 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700289 ifacePairList.push_front(pair_name);
290 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700291
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700292 asprintf(&pair_name, "%s_%s", extIface, intIface);
293 if (checkTetherCountingRuleExist(pair_name)) {
294 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700295 return 0;
296 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700297
298 const char *cmd3b[] = {
299 IPTABLES_PATH,
300 "-A",
301 LOCAL_TETHER_COUNTERS_CHAIN,
302 "-i",
303 extIface,
304 "-o",
305 intIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700306 "-j",
307 "RETURN"
308 };
309
310 if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) && add) {
311 // unwind what's been done, but don't care about success - what more could we do?
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700312 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700313 return -1;
314 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700315 ifacePairList.push_front(pair_name);
316 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700317 return 0;
318}
319
320int NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800321 const char *cmd1[] = {
322 IPTABLES_PATH,
323 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700324 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800325 "-i",
326 extIface,
327 "-o",
328 intIface,
329 "-m",
330 "state",
331 "--state",
332 "ESTABLISHED,RELATED",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700333 "-g",
334 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800335 };
336 int rc = 0;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700337
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800338 if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800339 return -1;
340 }
341
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800342 const char *cmd2[] = {
343 IPTABLES_PATH,
344 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,
350 "-m",
351 "state",
352 "--state",
353 "INVALID",
354 "-j",
355 "DROP"
356 };
357
358 const char *cmd3[] = {
359 IPTABLES_PATH,
360 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700361 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800362 "-i",
363 intIface,
364 "-o",
365 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700366 "-g",
367 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800368 };
369
370 if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
Robert Greenwaltf7bf29c2011-11-01 22:07:28 -0700371 // bail on error, but only if adding
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800372 rc = -1;
373 goto err_invalid_drop;
Robert Greenwaltddb9f6e2011-08-02 13:00:11 -0700374 }
375
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800376 if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
Robert Greenwalt210b9772010-03-25 14:54:45 -0700377 // unwind what's been done, but don't care about success - what more could we do?
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800378 rc = -1;
379 goto err_return;
San Mehat9ff78fb2010-01-19 12:59:15 -0800380 }
JP Abgrall0031cea2012-04-17 16:38:23 -0700381
JP Abgrallbaeccc42013-06-25 09:44:10 -0700382 if (setTetherCountingRules(add, intIface, extIface) && add) {
383 rc = -1;
384 goto err_return;
385 }
386
San Mehat9ff78fb2010-01-19 12:59:15 -0800387 return 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800388
389err_return:
390 cmd2[1] = "-D";
391 runCmd(ARRAY_SIZE(cmd2), cmd2);
392err_invalid_drop:
393 cmd1[1] = "-D";
394 runCmd(ARRAY_SIZE(cmd1), cmd1);
395 return rc;
San Mehat9ff78fb2010-01-19 12:59:15 -0800396}
397
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700398// nat disable intface extface
399// 0 1 2 3 4 5
400// nat enable intface extface addrcnt nated-ipaddr/prelength
401int NatController::disableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700402 int addrCount = atoi(argv[4]);
403 const char *intIface = argv[2];
404 const char *extIface = argv[3];
Robert Greenwalt1caafe62010-03-24 15:43:00 -0700405
JP Abgrall69261cb2014-06-19 18:35:24 -0700406 if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700407 errno = ENODEV;
408 return -1;
409 }
410
411 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000412 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700413 errno = EINVAL;
414 return -1;
415 }
416
417 setForwardRules(false, intIface, extIface);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700418 routesOp(false, intIface, extIface, argv, addrCount);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700419 if (--natCount <= 0) {
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600420 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
421 setDefaults();
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700422 }
423 return 0;
San Mehat9ff78fb2010-01-19 12:59:15 -0800424}