Add netd support for marked packet forwarding
Add binds in netd for setting up fwmark rules to be used with the per
uid marking to do per uid routing.
Change-Id: Id4f315dd1aec73f074e233c2e3f70eb24b4c537a
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 7ffb725..8346945 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -104,6 +104,7 @@
static const char* NAT_POSTROUTING[] = {
NatController::LOCAL_NAT_POSTROUTING,
+ SecondaryTableController::LOCAL_NAT_POSTROUTING,
NULL,
};
@@ -262,9 +263,36 @@
// 0 1 2 3 4 5 6 7
// interface route add/remove iface default/secondary dest prefix gateway
+ // interface route fwmark add/remove iface
// interface route uid add/remove iface uid
if (!strcmp(argv[1], "route")) {
int prefix_length = 0;
+ if (!strcmp(argv[2], "fwmark")) {
+ if (argc < 5) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+ return 0;
+ }
+ if (!strcmp(argv[3], "add")) {
+ if (!sSecondaryTableCtrl->addFwmarkRule(argv[4])) {
+ cli->sendMsg(ResponseCode::CommandOkay, "Fwmark rule successfully added",
+ false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to add fwmark rule",
+ true);
+ }
+ } else if (!strcmp(argv[3], "remove")) {
+ if (!sSecondaryTableCtrl->removeFwmarkRule(argv[4])) {
+ cli->sendMsg(ResponseCode::CommandOkay, "Fwmark rule successfully removed",
+ false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove fwmark rule",
+ true);
+ }
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark cmd", false);
+ }
+ return 0;
+ }
if (!strcmp(argv[2], "uid")) {
if (argc < 6) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
diff --git a/SecondaryTableController.cpp b/SecondaryTableController.cpp
index 4b10f62..3841083 100644
--- a/SecondaryTableController.cpp
+++ b/SecondaryTableController.cpp
@@ -37,6 +37,7 @@
#include "SecondaryTableController.h"
const char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT";
+const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
SecondaryTableController::SecondaryTableController() {
int i;
@@ -234,6 +235,60 @@
return runCmd(ARRAY_SIZE(cmd), cmd);
}
+int SecondaryTableController::addFwmarkRule(const char *iface) {
+ return setFwmarkRule(iface, true);
+}
+
+int SecondaryTableController::removeFwmarkRule(const char *iface) {
+ return setFwmarkRule(iface, false);
+}
+
+int SecondaryTableController::setFwmarkRule(const char *iface, bool add) {
+ char tableIndex_str[11];
+ int tableIndex = findTableNumber(iface);
+ if (tableIndex == -1) {
+ tableIndex = findTableNumber(""); // look for an empty slot
+ if (tableIndex == -1) {
+ ALOGE("Max number of NATed interfaces reached");
+ errno = ENODEV;
+ return -1;
+ }
+ strncpy(mInterfaceTable[tableIndex], iface, IFNAMSIZ);
+ // Ensure null termination even if truncation happened
+ mInterfaceTable[tableIndex][IFNAMSIZ] = 0;
+ }
+ snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
+ BASE_TABLE_NUMBER);
+ const char *cmd[] = {
+ IP_PATH,
+ "rule",
+ add ? "add" : "del",
+ "fwmark",
+ tableIndex_str,
+ "table",
+ tableIndex_str
+ };
+ int ret = runCmd(ARRAY_SIZE(cmd), cmd);
+ if (ret) return ret;
+
+ //set up the needed source IP rewriting
+ //NOTE: Without ipv6 NAT in the kernel <3.7 only support V4 NAT
+ return execIptables(V4,
+ "-t",
+ "nat",
+ add ? "-A" : "-D",
+ LOCAL_NAT_POSTROUTING,
+ "-o",
+ iface,
+ "-m",
+ "mark",
+ "--mark",
+ tableIndex_str,
+ "-j",
+ "MASQUERADE",
+ NULL);
+
+}
int SecondaryTableController::addUidRule(const char *iface, const char *uid) {
return setUidRule(iface, uid, true);
diff --git a/SecondaryTableController.h b/SecondaryTableController.h
index 27344e4..d29198d 100644
--- a/SecondaryTableController.h
+++ b/SecondaryTableController.h
@@ -42,12 +42,16 @@
int modifyLocalRoute(int tableIndex, const char *action, const char *iface, const char *addr);
int addUidRule(const char *iface, const char *uid);
int removeUidRule(const char *iface, const char *uid);
+ int addFwmarkRule(const char *iface);
+ int removeFwmarkRule(const char *iface);
static const char* LOCAL_MANGLE_OUTPUT;
+ static const char* LOCAL_NAT_POSTROUTING;
private:
int setUidRule(const char* iface, const char *uid, bool add);
+ int setFwmarkRule(const char *iface, bool add);
int modifyRoute(SocketClient *cli, const char *action, char *iface, char *dest, int prefix,
char *gateway, int tableIndex);