Nat-related commands refine
We need this to ensure that the tethering IPCs don't need to grab the
lock in two different controllers
The idea is that always having a global_alert rule in bw_global_alert
chain.
TetherController will enable/disable the reference of bw_global_alert
chain.
[childchain order of filter FORWARD chain]
Chain FORWARD
nm_mdmprxy_iface_pkt_fwder
oem_fwd
fw_FORWARD
bw_FORWARD
tetherctrl_FORWARD
--Simple rule comparison--
[Before]
Chain bw_FORWARD
Alert rule
... other rules
Chain tetherctrl_FORWARD
... other rules
[After]
Chain bw_FORWARD
No Alert rule
... other rules
Chain tetherctrl_FORWARD
Jump to bw_global_alert
... other rules
Chain bw_global_alert
Alert rule
The exact rule comparison is shown in the bug.
Bug:119735985
Test: built, flashed, booted
system/netd/tests/runtests.sh passes
Change-Id: Ibf752d0c8de9170689fc74c89c0424d2642853ec
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index e0dc25e..7e9bff7 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -66,6 +66,7 @@
const char BandwidthController::LOCAL_OUTPUT[] = "bw_OUTPUT";
const char BandwidthController::LOCAL_RAW_PREROUTING[] = "bw_raw_PREROUTING";
const char BandwidthController::LOCAL_MANGLE_POSTROUTING[] = "bw_mangle_POSTROUTING";
+const char BandwidthController::LOCAL_GLOBAL_ALERT[] = "bw_global_alert";
auto BandwidthController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
@@ -157,27 +158,27 @@
"-I bw_penalty_box -m bpf --object-pinned %s -j REJECT", XT_BPF_BLACKLIST_PROG_PATH);
static const std::vector<std::string> IPT_FLUSH_COMMANDS = {
- /*
- * Cleanup rules.
- * Should normally include bw_costly_<iface>, but we rely on the way they are setup
- * to allow coexistance.
- */
- "*filter",
- ":bw_INPUT -",
- ":bw_OUTPUT -",
- ":bw_FORWARD -",
- ":bw_happy_box -",
- ":bw_penalty_box -",
- ":bw_data_saver -",
- ":bw_costly_shared -",
- "COMMIT",
- "*raw",
- ":bw_raw_PREROUTING -",
- "COMMIT",
- "*mangle",
- ":bw_mangle_POSTROUTING -",
- COMMIT_AND_CLOSE
-};
+ /*
+ * Cleanup rules.
+ * Should normally include bw_costly_<iface>, but we rely on the way they are setup
+ * to allow coexistance.
+ */
+ "*filter",
+ ":bw_INPUT -",
+ ":bw_OUTPUT -",
+ ":bw_FORWARD -",
+ ":bw_happy_box -",
+ ":bw_penalty_box -",
+ ":bw_data_saver -",
+ ":bw_costly_shared -",
+ ":bw_global_alert -",
+ "COMMIT",
+ "*raw",
+ ":bw_raw_PREROUTING -",
+ "COMMIT",
+ "*mangle",
+ ":bw_mangle_POSTROUTING -",
+ COMMIT_AND_CLOSE};
static const uint32_t uidBillingMask = Fwmark::getUidBillingMask();
@@ -215,6 +216,8 @@
const std::vector<std::string> getBasicAccountingCommands(const bool useBpf) {
const std::vector<std::string> ipt_basic_accounting_commands = {
"*filter",
+
+ "-A bw_INPUT -j bw_global_alert",
// Prevents IPSec double counting (ESP and UDP-encap-ESP respectively)
"-A bw_INPUT -p esp -j RETURN",
StringPrintf("-A bw_INPUT -m mark --mark 0x%x/0x%x -j RETURN", uidBillingMask,
@@ -222,6 +225,7 @@
useBpf ? "" : "-A bw_INPUT -m owner --socket-exists",
StringPrintf("-A bw_INPUT -j MARK --or-mark 0x%x", uidBillingMask),
+ "-A bw_OUTPUT -j bw_global_alert",
// Prevents IPSec double counting (Tunnel mode and Transport mode,
// respectively)
"-A bw_OUTPUT -o " IPSEC_IFACE_PREFIX "+ -j RETURN",
@@ -293,7 +297,6 @@
mSharedQuotaIfaces.clear();
mQuotaIfaces.clear();
mGlobalAlertBytes = 0;
- mGlobalAlertTetherCount = 0;
mSharedQuotaBytes = mSharedAlertBytes = 0;
flushCleanTables(false);
@@ -630,20 +633,13 @@
// TODO: consider using an alternate template for the delete that does not include the --quota
// value. This code works because the --quota value is ignored by deletes
- StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_INPUT", bytes,
- alertName.c_str());
- StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_OUTPUT", bytes,
- alertName.c_str());
- StringAppendF(&alertQuotaCmd, "COMMIT\n");
- return iptablesRestoreFunction(V4V6, alertQuotaCmd, nullptr);
-}
-
-int BandwidthController::runIptablesAlertFwdCmd(IptOp op, const std::string& alertName,
- int64_t bytes) {
- const char *opFlag = opToString(op);
- std::string alertQuotaCmd = "*filter\n";
- StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_FORWARD", bytes,
+ /*
+ * Add alert rule in bw_global_alert chain, 3 chains might reference bw_global_alert.
+ * bw_INPUT, bw_OUTPUT (added by BandwidthController in enableBandwidthControl)
+ * bw_FORWARD (added by TetherController in setTetherGlobalAlertRule if nat enable/disable)
+ */
+ StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, LOCAL_GLOBAL_ALERT, bytes,
alertName.c_str());
StringAppendF(&alertQuotaCmd, "COMMIT\n");
@@ -663,10 +659,6 @@
res = updateQuota(alertName, bytes);
} else {
res = runIptablesAlertCmd(IptOpInsert, alertName, bytes);
- if (mGlobalAlertTetherCount) {
- ALOGV("setGlobalAlert for %d tether", mGlobalAlertTetherCount);
- res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes);
- }
if (res) {
res = -EREMOTEIO;
}
@@ -675,26 +667,6 @@
return res;
}
-int BandwidthController::setGlobalAlertInForwardChain() {
- const char *alertName = ALERT_GLOBAL_NAME;
-
- mGlobalAlertTetherCount++;
- ALOGV("setGlobalAlertInForwardChain(): %d tether", mGlobalAlertTetherCount);
-
- /*
- * If there is no globalAlert active we are done.
- * If there is an active globalAlert but this is not the 1st
- * tether, we are also done.
- */
- if (!mGlobalAlertBytes || mGlobalAlertTetherCount != 1) {
- return 0;
- }
-
- /* We only add the rule if this was the 1st tether added. */
- return (runIptablesAlertFwdCmd(IptOpInsert, alertName, mGlobalAlertBytes) == 0) ? 0
- : -EREMOTEIO;
-}
-
int BandwidthController::removeGlobalAlert() {
const char *alertName = ALERT_GLOBAL_NAME;
@@ -706,36 +678,10 @@
int res = 0;
res = runIptablesAlertCmd(IptOpDelete, alertName, mGlobalAlertBytes);
- if (mGlobalAlertTetherCount) {
- res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes);
- }
mGlobalAlertBytes = 0;
return res;
}
-int BandwidthController::removeGlobalAlertInForwardChain() {
- const char *alertName = ALERT_GLOBAL_NAME;
-
- if (!mGlobalAlertTetherCount) {
- ALOGE("No prior alert set");
- return -ENOENT;
- }
-
- mGlobalAlertTetherCount--;
- /*
- * If there is no globalAlert active we are done.
- * If there is an active globalAlert but there are more
- * tethers, we are also done.
- */
- if (!mGlobalAlertBytes || mGlobalAlertTetherCount >= 1) {
- return 0;
- }
-
- /* We only detete the rule if this was the last tether removed. */
- return (runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes) == 0) ? 0
- : -EREMOTEIO;
-}
-
int BandwidthController::setSharedAlert(int64_t bytes) {
if (!mSharedQuotaBytes) {
ALOGE("Need to have a prior shared quota set to set an alert");
diff --git a/server/BandwidthController.h b/server/BandwidthController.h
index 31575b8..b8691dc 100644
--- a/server/BandwidthController.h
+++ b/server/BandwidthController.h
@@ -73,6 +73,7 @@
static const char LOCAL_OUTPUT[];
static const char LOCAL_RAW_PREROUTING[];
static const char LOCAL_MANGLE_POSTROUTING[];
+ static const char LOCAL_GLOBAL_ALERT[];
enum IptJumpOp { IptJumpReject, IptJumpReturn, IptJumpNoAdd };
enum IptOp { IptOpInsert, IptOpDelete };
@@ -136,15 +137,6 @@
int64_t mSharedQuotaBytes = 0;
int64_t mSharedAlertBytes = 0;
int64_t mGlobalAlertBytes = 0;
- /*
- * This tracks the number of tethers setup.
- * The FORWARD chain is updated in the following cases:
- * - The 1st time a globalAlert is setup and there are tethers setup.
- * - Anytime a globalAlert is removed and there are tethers setup.
- * - The 1st tether is setup and there is a globalAlert active.
- * - The last tether is removed and there is a globalAlert active.
- */
- int mGlobalAlertTetherCount = 0;
std::map<std::string, QuotaInfo> mQuotaIfaces;
std::set<std::string> mSharedQuotaIfaces;
diff --git a/server/BandwidthControllerTest.cpp b/server/BandwidthControllerTest.cpp
index dc67f6c..febbe62 100644
--- a/server/BandwidthControllerTest.cpp
+++ b/server/BandwidthControllerTest.cpp
@@ -53,10 +53,12 @@
const std::string ACCOUNT_RULES_WITHOUT_BPF =
"*filter\n"
+ "-A bw_INPUT -j bw_global_alert\n"
"-A bw_INPUT -p esp -j RETURN\n"
"-A bw_INPUT -m mark --mark 0x100000/0x100000 -j RETURN\n"
"-A bw_INPUT -m owner --socket-exists\n"
"-A bw_INPUT -j MARK --or-mark 0x100000\n"
+ "-A bw_OUTPUT -j bw_global_alert\n"
"-A bw_OUTPUT -o ipsec+ -j RETURN\n"
"-A bw_OUTPUT -m policy --pol ipsec --dir out -j RETURN\n"
"-A bw_OUTPUT -m owner --socket-exists\n"
@@ -82,10 +84,12 @@
const std::string ACCOUNT_RULES_WITH_BPF =
"*filter\n"
+ "-A bw_INPUT -j bw_global_alert\n"
"-A bw_INPUT -p esp -j RETURN\n"
"-A bw_INPUT -m mark --mark 0x100000/0x100000 -j RETURN\n"
"\n"
"-A bw_INPUT -j MARK --or-mark 0x100000\n"
+ "-A bw_OUTPUT -j bw_global_alert\n"
"-A bw_OUTPUT -o ipsec+ -j RETURN\n"
"-A bw_OUTPUT -m policy --pol ipsec --dir out -j RETURN\n"
"\n"
@@ -128,28 +132,30 @@
mTun.destroy();
}
- void expectSetupCommands(const std::string& expectedClean, std::string expectedAccounting) {
+ void expectSetupCommands(const std::string& expectedClean,
+ const std::string& expectedAccounting) {
std::string expectedList =
"*filter\n"
"-S\n"
"COMMIT\n";
std::string expectedFlush =
- "*filter\n"
- ":bw_INPUT -\n"
- ":bw_OUTPUT -\n"
- ":bw_FORWARD -\n"
- ":bw_happy_box -\n"
- ":bw_penalty_box -\n"
- ":bw_data_saver -\n"
- ":bw_costly_shared -\n"
- "COMMIT\n"
- "*raw\n"
- ":bw_raw_PREROUTING -\n"
- "COMMIT\n"
- "*mangle\n"
- ":bw_mangle_POSTROUTING -\n"
- "COMMIT\n";
+ "*filter\n"
+ ":bw_INPUT -\n"
+ ":bw_OUTPUT -\n"
+ ":bw_FORWARD -\n"
+ ":bw_happy_box -\n"
+ ":bw_penalty_box -\n"
+ ":bw_data_saver -\n"
+ ":bw_costly_shared -\n"
+ ":bw_global_alert -\n"
+ "COMMIT\n"
+ "*raw\n"
+ ":bw_raw_PREROUTING -\n"
+ "COMMIT\n"
+ "*mangle\n"
+ ":bw_mangle_POSTROUTING -\n"
+ "COMMIT\n";
ExpectedIptablesCommands expected = {{ V4, expectedList }};
if (expectedClean.size()) {
@@ -165,14 +171,10 @@
using IptOp = BandwidthController::IptOp;
- int runIptablesAlertCmd(IptOp a, const char *b, int64_t c) {
+ int runIptablesAlertCmd(IptOp a, const char* b, int64_t c) {
return mBw.runIptablesAlertCmd(a, b, c);
}
- int runIptablesAlertFwdCmd(IptOp a, const char *b, int64_t c) {
- return mBw.runIptablesAlertFwdCmd(a, b, c);
- }
-
int setCostlyAlert(const std::string& a, int64_t b, int64_t* c) {
return mBw.setCostlyAlert(a, b, c);
}
@@ -467,42 +469,20 @@
TEST_F(BandwidthControllerTest, IptablesAlertCmd) {
std::vector<std::string> expected = {
- "*filter\n"
- "-I bw_INPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
- "-I bw_OUTPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
- "COMMIT\n"
- };
+ "*filter\n"
+ "-I bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
+ "COMMIT\n"};
EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
expectIptablesRestoreCommands(expected);
expected = {
- "*filter\n"
- "-D bw_INPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
- "-D bw_OUTPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
- "COMMIT\n"
- };
+ "*filter\n"
+ "-D bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
+ "COMMIT\n"};
EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
expectIptablesRestoreCommands(expected);
}
-TEST_F(BandwidthControllerTest, IptablesAlertFwdCmd) {
- std::vector<std::string> expected = {
- "*filter\n"
- "-I bw_FORWARD -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
- "COMMIT\n"
- };
- EXPECT_EQ(0, runIptablesAlertFwdCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
- expectIptablesRestoreCommands(expected);
-
- expected = {
- "*filter\n"
- "-D bw_FORWARD -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
- "COMMIT\n"
- };
- EXPECT_EQ(0, runIptablesAlertFwdCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
- expectIptablesRestoreCommands(expected);
-}
-
TEST_F(BandwidthControllerTest, CostlyAlert) {
const int64_t kQuota = 123456;
int64_t alertBytes = 0;
diff --git a/server/CommandListener.cpp b/server/CommandListener.cpp
index 7629c9a..6156221 100644
--- a/server/CommandListener.cpp
+++ b/server/CommandListener.cpp
@@ -531,14 +531,8 @@
// nat disable intiface extiface
if (!strcmp(argv[1], "enable") && argc >= 4) {
rc = gCtls->tetherCtrl.enableNat(argv[2], argv[3]);
- if(!rc) {
- /* Ignore ifaces for now. */
- rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
- }
} else if (!strcmp(argv[1], "disable") && argc >= 4) {
- /* Ignore ifaces for now. */
- rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
- rc |= gCtls->tetherCtrl.disableNat(argv[2], argv[3]);
+ rc = gCtls->tetherCtrl.disableNat(argv[2], argv[3]);
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
return 0;
@@ -871,17 +865,6 @@
sendGenericOkFail(cli, rc);
return 0;
}
- if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
- if (argc != 4) {
- sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
- return 0;
- }
- /* We ignore the interfaces for now. */
- int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
- sendGenericOkFail(cli, rc);
- return 0;
-
- }
if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
if (argc != 2) {
sendGenericSyntaxError(cli, "removeglobalalert");
@@ -892,17 +875,6 @@
return 0;
}
- if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
- if (argc != 4) {
- sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
- return 0;
- }
- /* We ignore the interfaces for now. */
- int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
- sendGenericOkFail(cli, rc);
- return 0;
-
- }
if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
if (argc != 3) {
sendGenericSyntaxError(cli, "setsharedalert <bytes>");
diff --git a/server/ControllersTest.cpp b/server/ControllersTest.cpp
index 0c56594..cc8b1aa 100644
--- a/server/ControllersTest.cpp
+++ b/server/ControllersTest.cpp
@@ -70,121 +70,125 @@
TEST_F(ControllersTest, TestInitIptablesRules) {
// Test what happens when we boot and there are no rules.
ExpectedIptablesCommands expected = {
- { V4V6, "*filter\n"
- ":INPUT -\n"
- "-F INPUT\n"
- ":bw_INPUT -\n"
- "-A INPUT -j bw_INPUT\n"
- ":fw_INPUT -\n"
- "-A INPUT -j fw_INPUT\n"
- "COMMIT\n"
- },
- { V4V6, "*filter\n"
- ":FORWARD -\n"
- "-F FORWARD\n"
- ":oem_fwd -\n"
- "-A FORWARD -j oem_fwd\n"
- ":fw_FORWARD -\n"
- "-A FORWARD -j fw_FORWARD\n"
- ":bw_FORWARD -\n"
- "-A FORWARD -j bw_FORWARD\n"
- ":tetherctrl_FORWARD -\n"
- "-A FORWARD -j tetherctrl_FORWARD\n"
- "COMMIT\n"
- },
- { V4V6, "*raw\n"
- ":PREROUTING -\n"
- "-F PREROUTING\n"
- ":bw_raw_PREROUTING -\n"
- "-A PREROUTING -j bw_raw_PREROUTING\n"
- ":idletimer_raw_PREROUTING -\n"
- "-A PREROUTING -j idletimer_raw_PREROUTING\n"
- ":tetherctrl_raw_PREROUTING -\n"
- "-A PREROUTING -j tetherctrl_raw_PREROUTING\n"
- "COMMIT\n"
- },
- { V4V6, "*mangle\n"
- ":FORWARD -\n"
- "-F FORWARD\n"
- ":tetherctrl_mangle_FORWARD -\n"
- "-A FORWARD -j tetherctrl_mangle_FORWARD\n"
- "COMMIT\n"
- },
- { V4V6, "*mangle\n"
- ":INPUT -\n"
- "-F INPUT\n"
- ":wakeupctrl_mangle_INPUT -\n"
- "-A INPUT -j wakeupctrl_mangle_INPUT\n"
- ":routectrl_mangle_INPUT -\n"
- "-A INPUT -j routectrl_mangle_INPUT\n"
- "COMMIT\n"
- },
- { V4, "*nat\n"
- ":PREROUTING -\n"
- "-F PREROUTING\n"
- ":oem_nat_pre -\n"
- "-A PREROUTING -j oem_nat_pre\n"
- "COMMIT\n"
- },
- { V4, "*nat\n"
- ":POSTROUTING -\n"
- "-F POSTROUTING\n"
- ":tetherctrl_nat_POSTROUTING -\n"
- "-A POSTROUTING -j tetherctrl_nat_POSTROUTING\n"
- "COMMIT\n"
- },
- { V4, "*filter\n"
- "-S OUTPUT\n"
- "COMMIT\n" },
- { V4, "*filter\n"
- ":oem_out -\n"
- "-A OUTPUT -j oem_out\n"
- ":fw_OUTPUT -\n"
- "-A OUTPUT -j fw_OUTPUT\n"
- ":st_OUTPUT -\n"
- "-A OUTPUT -j st_OUTPUT\n"
- ":bw_OUTPUT -\n"
- "-A OUTPUT -j bw_OUTPUT\n"
- "COMMIT\n"
- },
- { V6, "*filter\n"
- "-S OUTPUT\n"
- "COMMIT\n" },
- { V6, "*filter\n"
- ":oem_out -\n"
- "-A OUTPUT -j oem_out\n"
- ":fw_OUTPUT -\n"
- "-A OUTPUT -j fw_OUTPUT\n"
- ":st_OUTPUT -\n"
- "-A OUTPUT -j st_OUTPUT\n"
- ":bw_OUTPUT -\n"
- "-A OUTPUT -j bw_OUTPUT\n"
- "COMMIT\n"
- },
- { V4, "*mangle\n"
- "-S POSTROUTING\n"
- "COMMIT\n" },
- { V4, "*mangle\n"
- ":oem_mangle_post -\n"
- "-A POSTROUTING -j oem_mangle_post\n"
- ":bw_mangle_POSTROUTING -\n"
- "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
- ":idletimer_mangle_POSTROUTING -\n"
- "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
- "COMMIT\n"
- },
- { V6, "*mangle\n"
- "-S POSTROUTING\n"
- "COMMIT\n" },
- { V6, "*mangle\n"
- ":oem_mangle_post -\n"
- "-A POSTROUTING -j oem_mangle_post\n"
- ":bw_mangle_POSTROUTING -\n"
- "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
- ":idletimer_mangle_POSTROUTING -\n"
- "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
- "COMMIT\n"
- },
+ {V4V6,
+ "*filter\n"
+ ":INPUT -\n"
+ "-F INPUT\n"
+ ":bw_INPUT -\n"
+ "-A INPUT -j bw_INPUT\n"
+ ":fw_INPUT -\n"
+ "-A INPUT -j fw_INPUT\n"
+ "COMMIT\n"},
+ {V4V6,
+ "*filter\n"
+ ":FORWARD -\n"
+ "-F FORWARD\n"
+ ":oem_fwd -\n"
+ "-A FORWARD -j oem_fwd\n"
+ ":fw_FORWARD -\n"
+ "-A FORWARD -j fw_FORWARD\n"
+ ":bw_FORWARD -\n"
+ "-A FORWARD -j bw_FORWARD\n"
+ ":tetherctrl_FORWARD -\n"
+ "-A FORWARD -j tetherctrl_FORWARD\n"
+ "COMMIT\n"},
+ {V4V6,
+ "*raw\n"
+ ":PREROUTING -\n"
+ "-F PREROUTING\n"
+ ":bw_raw_PREROUTING -\n"
+ "-A PREROUTING -j bw_raw_PREROUTING\n"
+ ":idletimer_raw_PREROUTING -\n"
+ "-A PREROUTING -j idletimer_raw_PREROUTING\n"
+ ":tetherctrl_raw_PREROUTING -\n"
+ "-A PREROUTING -j tetherctrl_raw_PREROUTING\n"
+ "COMMIT\n"},
+ {V4V6,
+ "*mangle\n"
+ ":FORWARD -\n"
+ "-F FORWARD\n"
+ ":tetherctrl_mangle_FORWARD -\n"
+ "-A FORWARD -j tetherctrl_mangle_FORWARD\n"
+ "COMMIT\n"},
+ {V4V6,
+ "*mangle\n"
+ ":INPUT -\n"
+ "-F INPUT\n"
+ ":wakeupctrl_mangle_INPUT -\n"
+ "-A INPUT -j wakeupctrl_mangle_INPUT\n"
+ ":routectrl_mangle_INPUT -\n"
+ "-A INPUT -j routectrl_mangle_INPUT\n"
+ "COMMIT\n"},
+ {V4,
+ "*nat\n"
+ ":PREROUTING -\n"
+ "-F PREROUTING\n"
+ ":oem_nat_pre -\n"
+ "-A PREROUTING -j oem_nat_pre\n"
+ "COMMIT\n"},
+ {V4,
+ "*nat\n"
+ ":POSTROUTING -\n"
+ "-F POSTROUTING\n"
+ ":tetherctrl_nat_POSTROUTING -\n"
+ "-A POSTROUTING -j tetherctrl_nat_POSTROUTING\n"
+ "COMMIT\n"},
+ {V4,
+ "*filter\n"
+ "-S OUTPUT\n"
+ "COMMIT\n"},
+ {V4,
+ "*filter\n"
+ ":oem_out -\n"
+ "-A OUTPUT -j oem_out\n"
+ ":fw_OUTPUT -\n"
+ "-A OUTPUT -j fw_OUTPUT\n"
+ ":st_OUTPUT -\n"
+ "-A OUTPUT -j st_OUTPUT\n"
+ ":bw_OUTPUT -\n"
+ "-A OUTPUT -j bw_OUTPUT\n"
+ "COMMIT\n"},
+ {V6,
+ "*filter\n"
+ "-S OUTPUT\n"
+ "COMMIT\n"},
+ {V6,
+ "*filter\n"
+ ":oem_out -\n"
+ "-A OUTPUT -j oem_out\n"
+ ":fw_OUTPUT -\n"
+ "-A OUTPUT -j fw_OUTPUT\n"
+ ":st_OUTPUT -\n"
+ "-A OUTPUT -j st_OUTPUT\n"
+ ":bw_OUTPUT -\n"
+ "-A OUTPUT -j bw_OUTPUT\n"
+ "COMMIT\n"},
+ {V4,
+ "*mangle\n"
+ "-S POSTROUTING\n"
+ "COMMIT\n"},
+ {V4,
+ "*mangle\n"
+ ":oem_mangle_post -\n"
+ "-A POSTROUTING -j oem_mangle_post\n"
+ ":bw_mangle_POSTROUTING -\n"
+ "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
+ ":idletimer_mangle_POSTROUTING -\n"
+ "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
+ "COMMIT\n"},
+ {V6,
+ "*mangle\n"
+ "-S POSTROUTING\n"
+ "COMMIT\n"},
+ {V6,
+ "*mangle\n"
+ ":oem_mangle_post -\n"
+ "-A POSTROUTING -j oem_mangle_post\n"
+ ":bw_mangle_POSTROUTING -\n"
+ "-A POSTROUTING -j bw_mangle_POSTROUTING\n"
+ ":idletimer_mangle_POSTROUTING -\n"
+ "-A POSTROUTING -j idletimer_mangle_POSTROUTING\n"
+ "COMMIT\n"},
};
// Check that we run these commands and these only.
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index 7647e20..ebf1788 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -1493,10 +1493,6 @@
auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(intIface, extIface);
int res = gCtls->tetherCtrl.enableNat(intIface.c_str(), extIface.c_str());
- if (!res) {
- std::lock_guard lock(gCtls->bandwidthCtrl.lock);
- res = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
- }
gLog.log(entry.returns(res).withAutomaticDuration());
return statusFromErrcode(res);
}
@@ -1504,11 +1500,9 @@
binder::Status NetdNativeService::tetherRemoveForward(const std::string& intIface,
const std::string& extIface) {
NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
- std::lock_guard lock(gCtls->bandwidthCtrl.lock);
auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(intIface, extIface);
- int res = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
- res |= gCtls->tetherCtrl.disableNat(intIface.c_str(), extIface.c_str());
+ int res = gCtls->tetherCtrl.disableNat(intIface.c_str(), extIface.c_str());
gLog.log(entry.returns(res).withAutomaticDuration());
return statusFromErrcode(res);
}
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index 49c1b7e..62dcbbf 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -507,12 +507,13 @@
"COMMIT\n", LOCAL_FORWARD, LOCAL_FORWARD, LOCAL_NAT_POSTROUTING);
std::string v6Cmd = StringPrintf(
- "*filter\n"
- ":%s -\n"
- "COMMIT\n"
- "*raw\n"
- ":%s -\n"
- "COMMIT\n", LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
+ "*filter\n"
+ ":%s -\n"
+ "COMMIT\n"
+ "*raw\n"
+ ":%s -\n"
+ "COMMIT\n",
+ LOCAL_FORWARD, LOCAL_RAW_PREROUTING);
int res = iptablesRestoreFunction(V4, v4Cmd, nullptr);
if (res < 0) {
@@ -552,8 +553,8 @@
"COMMIT\n"
};
- if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) ||
- setupIPv6CountersChain()) {
+ if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) || setupIPv6CountersChain() ||
+ setTetherGlobalAlertRule()) {
ALOGE("Error setting postroute rule: iface=%s", extIface);
if (!isAnyForwardingPairEnabled()) {
// unwind what's been done, but don't care about success - what more could we do?
@@ -574,6 +575,19 @@
return 0;
}
+int TetherController::setTetherGlobalAlertRule() {
+ // Only add this if we are the first enabled nat
+ if (isAnyForwardingPairEnabled()) {
+ return 0;
+ }
+ const std::string cmds =
+ "*filter\n" +
+ StringPrintf("-I %s -j %s\n", LOCAL_FORWARD, BandwidthController::LOCAL_GLOBAL_ALERT) +
+ "COMMIT\n";
+
+ return iptablesRestoreFunction(V4V6, cmds, nullptr);
+}
+
int TetherController::setupIPv6CountersChain() {
// Only add this if we are the first enabled nat
if (isAnyForwardingPairEnabled()) {
@@ -584,13 +598,11 @@
* IPv6 tethering doesn't need the state-based conntrack rules, so
* it unconditionally jumps to the tether counters chain all the time.
*/
- std::vector<std::string> v6Cmds = {
- "*filter",
- StringPrintf("-A %s -g %s", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN),
- "COMMIT\n"
- };
+ const std::string v6Cmds =
+ "*filter\n" +
+ StringPrintf("-A %s -g %s\n", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN) + "COMMIT\n";
- return iptablesRestoreFunction(V6, Join(v6Cmds, '\n'), nullptr);
+ return iptablesRestoreFunction(V6, v6Cmds, nullptr);
}
// Gets a pointer to the ForwardingDownstream for an interface pair in the map, or nullptr
@@ -738,7 +750,8 @@
int TetherController::disableNat(const char* intIface, const char* extIface) {
if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
- return -ENODEV;
+ errno = ENODEV;
+ return -errno;
}
setForwardRules(false, intIface, extIface);
diff --git a/server/TetherController.h b/server/TetherController.h
index 54fa6da..18d0dc3 100644
--- a/server/TetherController.h
+++ b/server/TetherController.h
@@ -158,6 +158,7 @@
bool tetherCountingRuleExists(const std::string& iface1, const std::string& iface2);
int setDefaults();
+ int setTetherGlobalAlertRule();
int setForwardRules(bool set, const char *intIface, const char *extIface);
int setTetherCountingRules(bool add, const char *intIface, const char *extIface);
diff --git a/server/TetherControllerTest.cpp b/server/TetherControllerTest.cpp
index 7ccdc0c..969cbcd 100644
--- a/server/TetherControllerTest.cpp
+++ b/server/TetherControllerTest.cpp
@@ -56,42 +56,55 @@
}
const ExpectedIptablesCommands FLUSH_COMMANDS = {
- { V4, "*filter\n"
- ":tetherctrl_FORWARD -\n"
- "-A tetherctrl_FORWARD -j DROP\n"
- "COMMIT\n"
- "*nat\n"
- ":tetherctrl_nat_POSTROUTING -\n"
- "COMMIT\n" },
- { V6, "*filter\n"
- ":tetherctrl_FORWARD -\n"
- "COMMIT\n"
- "*raw\n"
- ":tetherctrl_raw_PREROUTING -\n"
- "COMMIT\n" },
+ {V4,
+ "*filter\n"
+ ":tetherctrl_FORWARD -\n"
+ "-A tetherctrl_FORWARD -j DROP\n"
+ "COMMIT\n"
+ "*nat\n"
+ ":tetherctrl_nat_POSTROUTING -\n"
+ "COMMIT\n"},
+ {V6,
+ "*filter\n"
+ ":tetherctrl_FORWARD -\n"
+ "COMMIT\n"
+ "*raw\n"
+ ":tetherctrl_raw_PREROUTING -\n"
+ "COMMIT\n"},
};
const ExpectedIptablesCommands SETUP_COMMANDS = {
- { V4, "*filter\n"
- ":tetherctrl_FORWARD -\n"
- "-A tetherctrl_FORWARD -j DROP\n"
- "COMMIT\n"
- "*nat\n"
- ":tetherctrl_nat_POSTROUTING -\n"
- "COMMIT\n" },
- { V6, "*filter\n"
- ":tetherctrl_FORWARD -\n"
- "COMMIT\n"
- "*raw\n"
- ":tetherctrl_raw_PREROUTING -\n"
- "COMMIT\n" },
- { V4, "*mangle\n"
- "-A tetherctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
- "-j TCPMSS --clamp-mss-to-pmtu\n"
- "COMMIT\n" },
- { V4V6, "*filter\n"
- ":tetherctrl_counters -\n"
- "COMMIT\n" },
+ {V4,
+ "*filter\n"
+ ":tetherctrl_FORWARD -\n"
+ "-A tetherctrl_FORWARD -j DROP\n"
+ "COMMIT\n"
+ "*nat\n"
+ ":tetherctrl_nat_POSTROUTING -\n"
+ "COMMIT\n"},
+ {V6,
+ "*filter\n"
+ ":tetherctrl_FORWARD -\n"
+ "COMMIT\n"
+ "*raw\n"
+ ":tetherctrl_raw_PREROUTING -\n"
+ "COMMIT\n"},
+ {V4,
+ "*mangle\n"
+ "-A tetherctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
+ "-j TCPMSS --clamp-mss-to-pmtu\n"
+ "COMMIT\n"},
+ {V4V6,
+ "*filter\n"
+ ":tetherctrl_counters -\n"
+ "COMMIT\n"},
+ };
+
+ const ExpectedIptablesCommands ALERT_ADD_COMMAND = {
+ {V4V6,
+ "*filter\n"
+ "-I tetherctrl_FORWARD -j bw_global_alert\n"
+ "COMMIT\n"},
};
ExpectedIptablesCommands firstIPv4UpstreamCommands(const char *extIf) {
@@ -106,9 +119,9 @@
ExpectedIptablesCommands firstIPv6UpstreamCommands() {
std::string v6Cmd =
- "*filter\n"
- "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
- "COMMIT\n";
+ "*filter\n"
+ "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
+ "COMMIT\n";
return {
{ V6, v6Cmd },
};
@@ -178,10 +191,9 @@
constexpr static const bool NO_COUNTERS = false;
constexpr static const bool WITH_IPV6 = true;
constexpr static const bool NO_IPV6 = false;
- ExpectedIptablesCommands allNewNatCommands(
- const char *intIf, const char *extIf, bool withCounterChainRules,
- bool withIPv6Upstream) {
-
+ ExpectedIptablesCommands allNewNatCommands(const char* intIf, const char* extIf,
+ bool withCounterChainRules, bool withIPv6Upstream,
+ bool firstEnableNat) {
ExpectedIptablesCommands commands;
ExpectedIptablesCommands setupFirstIPv4Commands = firstIPv4UpstreamCommands(extIf);
ExpectedIptablesCommands startFirstNatCommands = startNatCommands(intIf, extIf,
@@ -192,6 +204,9 @@
ExpectedIptablesCommands setupFirstIPv6Commands = firstIPv6UpstreamCommands();
appendAll(commands, setupFirstIPv6Commands);
}
+ if (firstEnableNat) {
+ appendAll(commands, ALERT_ADD_COMMAND);
+ }
appendAll(commands, startFirstNatCommands);
return commands;
@@ -243,8 +258,8 @@
TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
// Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
- ExpectedIptablesCommands firstNat = allNewNatCommands(
- "wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6);
+ ExpectedIptablesCommands firstNat =
+ allNewNatCommands("wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6, true);
mTetherCtrl.enableNat("wlan0", "rmnet0");
expectIptablesRestoreCommands(firstNat);
@@ -267,7 +282,7 @@
expectIptablesRestoreCommands(stopLastNat);
// Re-add a NAT removed previously: tetherctrl_counters chain rules are not re-added
- firstNat = allNewNatCommands("wlan0", "rmnet0", NO_COUNTERS, WITH_IPV6);
+ firstNat = allNewNatCommands("wlan0", "rmnet0", NO_COUNTERS, WITH_IPV6, true);
mTetherCtrl.enableNat("wlan0", "rmnet0");
expectIptablesRestoreCommands(firstNat);
@@ -280,15 +295,15 @@
TEST_F(TetherControllerTest, TestMultipleUpstreams) {
// Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
- ExpectedIptablesCommands firstNat = allNewNatCommands(
- "wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6);
+ ExpectedIptablesCommands firstNat =
+ allNewNatCommands("wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6, true);
mTetherCtrl.enableNat("wlan0", "rmnet0");
expectIptablesRestoreCommands(firstNat);
// Start second NAT, on new upstream. Expect the upstream and NAT rules to be created for IPv4,
// but no counter rules for IPv6.
- ExpectedIptablesCommands secondNat = allNewNatCommands(
- "wlan0", "v4-rmnet0", WITH_COUNTERS, NO_IPV6);
+ ExpectedIptablesCommands secondNat =
+ allNewNatCommands("wlan0", "v4-rmnet0", WITH_COUNTERS, NO_IPV6, false);
mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
expectIptablesRestoreCommands(secondNat);
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
index a6905b1..495b672 100644
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -1133,6 +1133,7 @@
* cause of the the failure.
*/
void interfaceSetMtu(in @utf8InCpp String ifName, int mtu);
+
/**
* Add forwarding rule/stats on given interface.
*