blob: 8391ad7ad04f28b1df30d70a4ed22a9228f9a23e [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 addrCount = atoi(argv[4]);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700169 const char *intIface = argv[2];
170 const char *extIface = argv[3];
San Mehat9ff78fb2010-01-19 12:59:15 -0800171
JP Abgrallbaeccc42013-06-25 09:44:10 -0700172 ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
173
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700174 if (!checkInterface(intIface) || !checkInterface(extIface)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000175 ALOGE("Invalid interface specified");
San Mehat9ff78fb2010-01-19 12:59:15 -0800176 errno = ENODEV;
177 return -1;
178 }
179
JP Abgrallbaeccc42013-06-25 09:44:10 -0700180 /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
181 if (!strcmp(intIface, extIface)) {
182 ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
183 errno = EINVAL;
184 return -1;
185 }
186
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700187 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000188 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700189 errno = EINVAL;
190 return -1;
191 }
JP Abgrall659692a2013-03-14 20:07:17 -0700192 if (routesOp(true, intIface, extIface, argv, addrCount)) {
193 ALOGE("Error setting route rules");
194 routesOp(false, intIface, extIface, argv, addrCount);
195 errno = ENODEV;
196 return -1;
197 }
198
199 // add this if we are the first added nat
200 if (natCount == 0) {
201 const char *cmd[] = {
202 IPTABLES_PATH,
203 "-t",
204 "nat",
205 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700206 LOCAL_NAT_POSTROUTING,
JP Abgrall659692a2013-03-14 20:07:17 -0700207 "-o",
208 extIface,
209 "-j",
210 "MASQUERADE"
211 };
212 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
213 ALOGE("Error seting postroute rule: iface=%s", extIface);
214 // unwind what's been done, but don't care about success - what more could we do?
215 routesOp(false, intIface, extIface, argv, addrCount);
216 setDefaults();
217 return -1;
218 }
219 }
220
221
222 if (setForwardRules(true, intIface, extIface) != 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000223 ALOGE("Error setting forward rules");
JP Abgrall4ae80de2013-03-14 20:06:20 -0700224 routesOp(false, intIface, extIface, argv, addrCount);
JP Abgrall659692a2013-03-14 20:07:17 -0700225 if (natCount == 0) {
226 setDefaults();
227 }
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700228 errno = ENODEV;
229 return -1;
230 }
231
JP Abgrall0031cea2012-04-17 16:38:23 -0700232 /* Always make sure the drop rule is at the end */
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800233 const char *cmd1[] = {
234 IPTABLES_PATH,
235 "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700236 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800237 "-j",
238 "DROP"
239 };
240 runCmd(ARRAY_SIZE(cmd1), cmd1);
241 const char *cmd2[] = {
242 IPTABLES_PATH,
243 "-A",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700244 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800245 "-j",
246 "DROP"
247 };
248 runCmd(ARRAY_SIZE(cmd2), cmd2);
JP Abgrall0031cea2012-04-17 16:38:23 -0700249
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700250 natCount++;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700251 return 0;
252}
253
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700254bool NatController::checkTetherCountingRuleExist(const char *pair_name) {
255 std::list<std::string>::iterator it;
256
257 for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
258 if (*it == pair_name) {
259 /* We already have this counter */
260 return true;
261 }
262 }
263 return false;
264}
265
JP Abgrallbaeccc42013-06-25 09:44:10 -0700266int NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
267
268 /* We only ever add tethering quota rules so that they stick. */
269 if (!add) {
270 return 0;
271 }
Sreeram Ramachandran56afacf2014-05-28 15:07:00 -0700272 char *pair_name;
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700273 asprintf(&pair_name, "%s_%s", intIface, extIface);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700274
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700275 if (checkTetherCountingRuleExist(pair_name)) {
276 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700277 return 0;
278 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700279 const char *cmd2b[] = {
280 IPTABLES_PATH,
281 "-A",
282 LOCAL_TETHER_COUNTERS_CHAIN,
283 "-i",
284 intIface,
285 "-o",
286 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700287 "-j",
288 "RETURN"
289 };
290
291 if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) && add) {
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700292 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700293 return -1;
294 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700295 ifacePairList.push_front(pair_name);
296 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700297
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700298 asprintf(&pair_name, "%s_%s", extIface, intIface);
299 if (checkTetherCountingRuleExist(pair_name)) {
300 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700301 return 0;
302 }
JP Abgrallbaeccc42013-06-25 09:44:10 -0700303
304 const char *cmd3b[] = {
305 IPTABLES_PATH,
306 "-A",
307 LOCAL_TETHER_COUNTERS_CHAIN,
308 "-i",
309 extIface,
310 "-o",
311 intIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700312 "-j",
313 "RETURN"
314 };
315
316 if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) && add) {
317 // unwind what's been done, but don't care about success - what more could we do?
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700318 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700319 return -1;
320 }
JP Abgrallf3cc83f2013-09-11 20:01:59 -0700321 ifacePairList.push_front(pair_name);
322 free(pair_name);
JP Abgrallbaeccc42013-06-25 09:44:10 -0700323 return 0;
324}
325
326int NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800327 const char *cmd1[] = {
328 IPTABLES_PATH,
329 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700330 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800331 "-i",
332 extIface,
333 "-o",
334 intIface,
335 "-m",
336 "state",
337 "--state",
338 "ESTABLISHED,RELATED",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700339 "-g",
340 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800341 };
342 int rc = 0;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700343
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800344 if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
San Mehat9ff78fb2010-01-19 12:59:15 -0800345 return -1;
346 }
347
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800348 const char *cmd2[] = {
349 IPTABLES_PATH,
350 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700351 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800352 "-i",
353 intIface,
354 "-o",
355 extIface,
356 "-m",
357 "state",
358 "--state",
359 "INVALID",
360 "-j",
361 "DROP"
362 };
363
364 const char *cmd3[] = {
365 IPTABLES_PATH,
366 add ? "-A" : "-D",
JP Abgrallbaeccc42013-06-25 09:44:10 -0700367 LOCAL_FORWARD,
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800368 "-i",
369 intIface,
370 "-o",
371 extIface,
JP Abgrallbaeccc42013-06-25 09:44:10 -0700372 "-g",
373 LOCAL_TETHER_COUNTERS_CHAIN
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800374 };
375
376 if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
Robert Greenwaltf7bf29c2011-11-01 22:07:28 -0700377 // bail on error, but only if adding
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800378 rc = -1;
379 goto err_invalid_drop;
Robert Greenwaltddb9f6e2011-08-02 13:00:11 -0700380 }
381
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800382 if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
Robert Greenwalt210b9772010-03-25 14:54:45 -0700383 // unwind what's been done, but don't care about success - what more could we do?
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800384 rc = -1;
385 goto err_return;
San Mehat9ff78fb2010-01-19 12:59:15 -0800386 }
JP Abgrall0031cea2012-04-17 16:38:23 -0700387
JP Abgrallbaeccc42013-06-25 09:44:10 -0700388 if (setTetherCountingRules(add, intIface, extIface) && add) {
389 rc = -1;
390 goto err_return;
391 }
392
San Mehat9ff78fb2010-01-19 12:59:15 -0800393 return 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800394
395err_return:
396 cmd2[1] = "-D";
397 runCmd(ARRAY_SIZE(cmd2), cmd2);
398err_invalid_drop:
399 cmd1[1] = "-D";
400 runCmd(ARRAY_SIZE(cmd1), cmd1);
401 return rc;
San Mehat9ff78fb2010-01-19 12:59:15 -0800402}
403
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700404// nat disable intface extface
405// 0 1 2 3 4 5
406// nat enable intface extface addrcnt nated-ipaddr/prelength
407int NatController::disableNat(const int argc, char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700408 int addrCount = atoi(argv[4]);
409 const char *intIface = argv[2];
410 const char *extIface = argv[3];
Robert Greenwalt1caafe62010-03-24 15:43:00 -0700411
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700412 if (!checkInterface(intIface) || !checkInterface(extIface)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000413 ALOGE("Invalid interface specified");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700414 errno = ENODEV;
415 return -1;
416 }
417
418 if (argc < 5 + addrCount) {
Steve Block5ea0c052012-01-06 19:18:11 +0000419 ALOGE("Missing Argument");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700420 errno = EINVAL;
421 return -1;
422 }
423
424 setForwardRules(false, intIface, extIface);
JP Abgrall4ae80de2013-03-14 20:06:20 -0700425 routesOp(false, intIface, extIface, argv, addrCount);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700426 if (--natCount <= 0) {
Kazuhiro Ondo4ab46852012-01-12 16:15:06 -0600427 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
428 setDefaults();
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700429 }
430 return 0;
San Mehat9ff78fb2010-01-19 12:59:15 -0800431}