blob: fbf5f8a0377c36db5fd4f412a11c03e60c62091a [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
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700137bool NatController::checkInterface(const char *iface) {
Jaime A Lopez-Sollanod14fd4f2012-01-11 16:29:28 -0800138 if (strlen(iface) > IFNAMSIZ) return false;
San Mehat9ff78fb2010-01-19 12:59:15 -0800139 return true;
140}
141
JP Abgrall4ae80de2013-03-14 20:06:20 -0700142int NatController::routesOp(bool add, const char *intIface, const char *extIface, char **argv, int addrCount) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500143 unsigned netId = mNetCtrl->getNetworkId(extIface);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700144 int ret = 0;
145
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500146 for (int i = 0; i < addrCount; i++) {
147 if (add) {
148 ret |= mSecondaryTableCtrl->modifyFromRule(netId, ADD, argv[5+i]);
149 ret |= mSecondaryTableCtrl->modifyLocalRoute(netId, ADD, intIface, argv[5+i]);
150 } else {
151 ret |= mSecondaryTableCtrl->modifyLocalRoute(netId, DEL, intIface, argv[5+i]);
152 ret |= mSecondaryTableCtrl->modifyFromRule(netId, DEL, argv[5+i]);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700153 }
JP Abgrall4ae80de2013-03-14 20:06:20 -0700154 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500155 const char *cmd[] = {
156 IP_PATH,
157 "route",
158 "flush",
159 "cache"
160 };
161 runCmd(ARRAY_SIZE(cmd), cmd);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700162 return ret;
163}
164
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700165// 0 1 2 3 4 5
166// nat enable intface extface addrcnt nated-ipaddr/prelength
167int NatController::enableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700168 int i;
169 int addrCount = atoi(argv[4]);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700170 const char *intIface = argv[2];
171 const char *extIface = argv[3];
172 int tableNumber;
San Mehat9ff78fb2010-01-19 12:59:15 -0800173
JP Abgrallbaeccc42013-06-25 09:44:10 -0700174 ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
175
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700176 if (!checkInterface(intIface) || !checkInterface(extIface)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000177 ALOGE("Invalid interface specified");
San Mehat9ff78fb2010-01-19 12:59:15 -0800178 errno = ENODEV;
179 return -1;
180 }
181
JP Abgrallbaeccc42013-06-25 09:44:10 -0700182 /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
183 if (!strcmp(intIface, extIface)) {
184 ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
185 errno = EINVAL;
186 return -1;
187 }
188
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700189 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000190 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700191 errno = EINVAL;
192 return -1;
193 }
JP Abgrall659692a2013-03-14 20:07:17 -0700194 if (routesOp(true, intIface, extIface, argv, addrCount)) {
195 ALOGE("Error setting route rules");
196 routesOp(false, intIface, extIface, argv, addrCount);
197 errno = ENODEV;
198 return -1;
199 }
200
201 // add this if we are the first added nat
202 if (natCount == 0) {
203 const char *cmd[] = {
204 IPTABLES_PATH,
205 "-t",
206 "nat",
207 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700208 LOCAL_NAT_POSTROUTING,
JP Abgrall659692a2013-03-14 20:07:17 -0700209 "-o",
210 extIface,
211 "-j",
212 "MASQUERADE"
213 };
214 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
215 ALOGE("Error seting postroute rule: iface=%s", extIface);
216 // unwind what's been done, but don't care about success - what more could we do?
217 routesOp(false, intIface, extIface, argv, addrCount);
218 setDefaults();
219 return -1;
220 }
221 }
222
223
224 if (setForwardRules(true, intIface, extIface) != 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000225 ALOGE("Error setting forward rules");
JP Abgrall4ae80de2013-03-14 20:06:20 -0700226 routesOp(false, intIface, extIface, argv, addrCount);
JP Abgrall659692a2013-03-14 20:07:17 -0700227 if (natCount == 0) {
228 setDefaults();
229 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700230 errno = ENODEV;
231 return -1;
232 }
233
JP Abgrall0031cea2012-04-17 16:38:23 -0700234 /* Always make sure the drop rule is at the end */
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800235 const char *cmd1[] = {
236 IPTABLES_PATH,
237 "-D",
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(cmd1), cmd1);
243 const char *cmd2[] = {
244 IPTABLES_PATH,
245 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700246 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800247 "-j",
248 "DROP"
249 };
250 runCmd(ARRAY_SIZE(cmd2), cmd2);
JP Abgrall0031cea2012-04-17 16:38:23 -0700251
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700252 natCount++;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700253 return 0;
254}
255
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700256bool NatController::checkTetherCountingRuleExist(const char *pair_name) {
257 std::list<std::string>::iterator it;
258
259 for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
260 if (*it == pair_name) {
261 /* We already have this counter */
262 return true;
263 }
264 }
265 return false;
266}
267
JP Abgrallbaeccc42013-06-25 09:44:10 -0700268int NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
269
270 /* We only ever add tethering quota rules so that they stick. */
271 if (!add) {
272 return 0;
273 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700274 char *pair_name, *proc_path;
JP Abgrallbaeccc42013-06-25 09:44:10 -0700275 int quota_fd;
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700276 asprintf(&pair_name, "%s_%s", intIface, extIface);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700277
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700278 if (checkTetherCountingRuleExist(pair_name)) {
279 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700280 return 0;
281 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700282 const char *cmd2b[] = {
283 IPTABLES_PATH,
284 "-A",
285 LOCAL_TETHER_COUNTERS_CHAIN,
286 "-i",
287 intIface,
288 "-o",
289 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700290 "-j",
291 "RETURN"
292 };
293
294 if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) && add) {
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700295 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700296 return -1;
297 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700298 ifacePairList.push_front(pair_name);
299 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700300
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700301 asprintf(&pair_name, "%s_%s", extIface, intIface);
302 if (checkTetherCountingRuleExist(pair_name)) {
303 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700304 return 0;
305 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700306
307 const char *cmd3b[] = {
308 IPTABLES_PATH,
309 "-A",
310 LOCAL_TETHER_COUNTERS_CHAIN,
311 "-i",
312 extIface,
313 "-o",
314 intIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700315 "-j",
316 "RETURN"
317 };
318
319 if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) && add) {
320 // unwind what's been done, but don't care about success - what more could we do?
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700321 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700322 return -1;
323 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700324 ifacePairList.push_front(pair_name);
325 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700326 return 0;
327}
328
329int NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800330 const char *cmd1[] = {
331 IPTABLES_PATH,
332 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700333 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800334 "-i",
335 extIface,
336 "-o",
337 intIface,
338 "-m",
339 "state",
340 "--state",
341 "ESTABLISHED,RELATED",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700342 "-g",
343 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800344 };
345 int rc = 0;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700346
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800347 if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800348 return -1;
349 }
350
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800351 const char *cmd2[] = {
352 IPTABLES_PATH,
353 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700354 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800355 "-i",
356 intIface,
357 "-o",
358 extIface,
359 "-m",
360 "state",
361 "--state",
362 "INVALID",
363 "-j",
364 "DROP"
365 };
366
367 const char *cmd3[] = {
368 IPTABLES_PATH,
369 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700370 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800371 "-i",
372 intIface,
373 "-o",
374 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700375 "-g",
376 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800377 };
378
379 if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
Robert Greenwaltf7bf29c2011-11-01 22:07:28 -0700380 // bail on error, but only if adding
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800381 rc = -1;
382 goto err_invalid_drop;
Robert Greenwaltddb9f6e2011-08-02 13:00:11 -0700383 }
384
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800385 if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
Robert Greenwalt210b9772010-03-25 14:54:45 -0700386 // unwind what's been done, but don't care about success - what more could we do?
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800387 rc = -1;
388 goto err_return;
San Mehat9ff78fb2010-01-19 12:59:15 -0800389 }
JP Abgrall0031cea2012-04-17 16:38:23 -0700390
JP Abgrallbaeccc42013-06-25 09:44:10 -0700391 if (setTetherCountingRules(add, intIface, extIface) && add) {
392 rc = -1;
393 goto err_return;
394 }
395
San Mehat9ff78fb2010-01-19 12:59:15 -0800396 return 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800397
398err_return:
399 cmd2[1] = "-D";
400 runCmd(ARRAY_SIZE(cmd2), cmd2);
401err_invalid_drop:
402 cmd1[1] = "-D";
403 runCmd(ARRAY_SIZE(cmd1), cmd1);
404 return rc;
San Mehat9ff78fb2010-01-19 12:59:15 -0800405}
406
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700407// nat disable intface extface
408// 0 1 2 3 4 5
409// nat enable intface extface addrcnt nated-ipaddr/prelength
410int NatController::disableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700411 int i;
412 int addrCount = atoi(argv[4]);
413 const char *intIface = argv[2];
414 const char *extIface = argv[3];
415 int tableNumber;
Robert Greenwalt1caafe62010-03-24 15:43:00 -0700416
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700417 if (!checkInterface(intIface) || !checkInterface(extIface)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000418 ALOGE("Invalid interface specified");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700419 errno = ENODEV;
420 return -1;
421 }
422
423 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000424 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700425 errno = EINVAL;
426 return -1;
427 }
428
429 setForwardRules(false, intIface, extIface);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700430 routesOp(false, intIface, extIface, argv, addrCount);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700431 if (--natCount <= 0) {
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600432 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
433 setDefaults();
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700434 }
435 return 0;
San Mehat9ff78fb2010-01-19 12:59:15 -0800436}