Start using IP tool for advanced routing.
bug:5495862
bug:5396842
Change-Id: I51f21060947f57e63b18c4d35e9d49fac488d48a
diff --git a/NatController.cpp b/NatController.cpp
index 49984f8..ce5b3f1 100644
--- a/NatController.cpp
+++ b/NatController.cpp
@@ -28,30 +28,33 @@
#include <cutils/log.h>
#include "NatController.h"
+#include "SecondaryTableController.h"
extern "C" int logwrap(int argc, const char **argv, int background);
static char IPTABLES_PATH[] = "/system/bin/iptables";
+static char IP_PATH[] = "/system/bin/ip";
-NatController::NatController() {
- natCount = 0;
+NatController::NatController(SecondaryTableController *ctrl) {
+ secondaryTableCtrl = ctrl;
+ setDefaults();
}
NatController::~NatController() {
}
-int NatController::runIptablesCmd(const char *cmd) {
+int NatController::runCmd(const char *path, const char *cmd) {
char *buffer;
size_t len = strnlen(cmd, 255);
int res;
if (len == 255) {
- LOGE("iptables command too long");
+ LOGE("command too long");
errno = E2BIG;
return -1;
}
- asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
+ asprintf(&buffer, "%s %s", path, cmd);
res = system(buffer);
free(buffer);
return res;
@@ -59,57 +62,113 @@
int NatController::setDefaults() {
- if (runIptablesCmd("-P INPUT ACCEPT"))
+ if (runCmd(IPTABLES_PATH, "-P INPUT ACCEPT"))
return -1;
- if (runIptablesCmd("-P OUTPUT ACCEPT"))
+ if (runCmd(IPTABLES_PATH, "-P OUTPUT ACCEPT"))
return -1;
- if (runIptablesCmd("-P FORWARD DROP"))
+ if (runCmd(IPTABLES_PATH, "-P FORWARD DROP"))
return -1;
- if (runIptablesCmd("-F FORWARD"))
+ if (runCmd(IPTABLES_PATH, "-F FORWARD"))
return -1;
- if (runIptablesCmd("-t nat -F"))
+ if (runCmd(IPTABLES_PATH, "-t nat -F"))
return -1;
+
+ runCmd(IP_PATH, "rule flush");
+ runCmd(IP_PATH, "rule add from all lookup default prio 32767");
+ runCmd(IP_PATH, "rule add from all lookup main prio 32766");
+
+ natCount = 0;
return 0;
}
-bool NatController::interfaceExists(const char *iface) {
- // XXX: Implement this
+bool NatController::checkInterface(const char *iface) {
+ if (strlen(iface) > MAX_IFACE_LENGTH) return false;
return true;
}
-// when un-doing NAT, we should report errors, but also try to do as much cleanup
-// as we can - don't short circuit on error.
-int NatController::doNatCommands(const char *intIface, const char *extIface, bool add) {
+// 0 1 2 3 4 5
+// nat enable intface extface addrcnt nated-ipaddr/prelength
+int NatController::enableNat(const int argc, char **argv) {
char cmd[255];
+ int i;
+ int addrCount = atoi(argv[4]);
+ int ret = 0;
+ const char *intIface = argv[2];
+ const char *extIface = argv[3];
+ int tableNumber;
- char bootmode[PROPERTY_VALUE_MAX] = {0};
- property_get("ro.bootmode", bootmode, "unknown");
- if (0 != strcmp("bp-tools", bootmode)) {
- // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
- if (add == false) {
- if (natCount <= 1) {
- int ret = setDefaults();
- if (ret == 0) {
- natCount=0;
- }
- LOGE("setDefaults returned %d", ret);
- return ret;
- }
- }
- }
-
- if (!interfaceExists(intIface) || !interfaceExists (extIface)) {
+ if (!checkInterface(intIface) || !checkInterface(extIface)) {
LOGE("Invalid interface specified");
errno = ENODEV;
return -1;
}
+ if (argc < 5 + addrCount) {
+ LOGE("Missing Argument");
+ errno = EINVAL;
+ return -1;
+ }
+
+ tableNumber = secondaryTableCtrl->findTableNumber(extIface);
+ if (tableNumber != -1) {
+ for(i = 0; i < addrCount && ret == 0; i++) {
+ snprintf(cmd, sizeof(cmd), "rule add from %s table %d", argv[5+i],
+ tableNumber + BASE_TABLE_NUMBER);
+ ret |= runCmd(IP_PATH, cmd);
+ if (ret) LOGE("IP rule %s got %d", cmd, ret);
+
+ snprintf(cmd, sizeof(cmd), "route add %s dev %s table %d", argv[5+i], intIface,
+ tableNumber + BASE_TABLE_NUMBER);
+ ret |= runCmd(IP_PATH, cmd);
+ if (ret) LOGE("IP route %s got %d", cmd, ret);
+ }
+ }
+
+ if (ret != 0 || setForwardRules(true, intIface, extIface) != 0) {
+ if (tableNumber != -1) {
+ for (i = 0; i < addrCount; i++) {
+ snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
+ tableNumber + BASE_TABLE_NUMBER);
+ runCmd(IP_PATH, cmd);
+
+ snprintf(cmd, sizeof(cmd), "rule del from %s table %d", argv[5+i],
+ tableNumber + BASE_TABLE_NUMBER);
+ runCmd(IP_PATH, cmd);
+ }
+ }
+ LOGE("Error setting forward rules");
+ errno = ENODEV;
+ return -1;
+ }
+
+ natCount++;
+ // add this if we are the first added nat
+ if (natCount == 1) {
+ snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
+ if (runCmd(IPTABLES_PATH, cmd)) {
+ LOGE("Error seting postroute rule: %s", cmd);
+ // unwind what's been done, but don't care about success - what more could we do?
+ for (i = 0; i < addrCount; i++) {
+ snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
+ tableNumber + BASE_TABLE_NUMBER);
+ runCmd(IP_PATH, cmd);
+ }
+ setDefaults();
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int NatController::setForwardRules(bool add, const char *intIface, const char * extIface) {
+ char cmd[255];
+
snprintf(cmd, sizeof(cmd),
"-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
(add ? "A" : "D"),
extIface, intIface);
- if (runIptablesCmd(cmd) && add) {
- // only bail out if we are adding, not removing nat rules
+ if (runCmd(IPTABLES_PATH, cmd) && add) {
return -1;
}
@@ -117,58 +176,80 @@
"-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
(add ? "A" : "D"),
intIface, extIface);
- if (runIptablesCmd(cmd) && add) {
+ if (runCmd(IPTABLES_PATH, cmd) && add) {
// bail on error, but only if adding
snprintf(cmd, sizeof(cmd),
"-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
(!add ? "A" : "D"),
extIface, intIface);
- runIptablesCmd(cmd);
+ runCmd(IPTABLES_PATH, cmd);
return -1;
}
snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"),
intIface, extIface);
- if (runIptablesCmd(cmd) && add) {
+ if (runCmd(IPTABLES_PATH, cmd) && add) {
// unwind what's been done, but don't care about success - what more could we do?
snprintf(cmd, sizeof(cmd),
"-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
(!add ? "A" : "D"),
intIface, extIface);
- runIptablesCmd(cmd);
+ runCmd(IPTABLES_PATH, cmd);
snprintf(cmd, sizeof(cmd),
"-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
(!add ? "A" : "D"),
extIface, intIface);
- runIptablesCmd(cmd);
+ runCmd(IPTABLES_PATH, cmd);
return -1;
}
-
- // add this if we are the first added nat
- if (add && natCount == 0) {
- snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
- if (runIptablesCmd(cmd)) {
- if (0 != strcmp("bp-tools", bootmode)) {
- // unwind what's been done, but don't care about success - what more could we do?
- setDefaults();;
- }
- return -1;
- }
- }
-
- if (add) {
- natCount++;
- } else {
- natCount--;
- }
return 0;
}
-int NatController::enableNat(const char *intIface, const char *extIface) {
- return doNatCommands(intIface, extIface, true);
-}
+// nat disable intface extface
+// 0 1 2 3 4 5
+// nat enable intface extface addrcnt nated-ipaddr/prelength
+int NatController::disableNat(const int argc, char **argv) {
+ char cmd[255];
+ int i;
+ int addrCount = atoi(argv[4]);
+ const char *intIface = argv[2];
+ const char *extIface = argv[3];
+ int tableNumber;
-int NatController::disableNat(const char *intIface, const char *extIface) {
- return doNatCommands(intIface, extIface, false);
+ if (!checkInterface(intIface) || !checkInterface(extIface)) {
+ LOGE("Invalid interface specified");
+ errno = ENODEV;
+ return -1;
+ }
+
+ if (argc < 5 + addrCount) {
+ LOGE("Missing Argument");
+ errno = EINVAL;
+ return -1;
+ }
+
+ setForwardRules(false, intIface, extIface);
+
+ tableNumber = secondaryTableCtrl->findTableNumber(extIface);
+ if (tableNumber != -1) {
+ for (i = 0; i < addrCount; i++) {
+ snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
+ tableNumber + BASE_TABLE_NUMBER);
+ // if the interface has gone down these will be gone already and give errors
+ // ignore them.
+ runCmd(IP_PATH, cmd);
+ }
+ }
+
+ if (--natCount <= 0) {
+ char bootmode[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.bootmode", bootmode, "unknown");
+ if (0 != strcmp("bp-tools", bootmode)) {
+ // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
+ setDefaults();
+ }
+ natCount = 0;
+ }
+ return 0;
}