Use iptables pipes in BandwidthController startup.
Most of BandwidthController startup is already using
iptables-restore, but some commands (notably listing the costly
chains so they can be flushed by flushCleanTables) still
use iptables. Move these to use execIptablesRestoreWithOutput.
Test: netd_unit_test passes
Bug: 34873832
Change-Id: Ib0741a99a2605cd6934186fd4e5364331a4eab5a
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index 09dc483..3df2309 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -66,7 +66,7 @@
auto BandwidthController::execFunction = android_fork_execvp;
auto BandwidthController::popenFunction = popen;
-auto BandwidthController::iptablesRestoreFunction = execIptablesRestore;
+auto BandwidthController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
namespace {
@@ -75,6 +75,7 @@
const int MAX_CMD_LEN = 1024;
const int MAX_IFACENAME_LEN = 64;
const int MAX_IPT_OUTPUT_LINE_LEN = 256;
+const std::string NEW_CHAIN_COMMAND = "-N ";
/**
* Some comments about the rules:
@@ -138,7 +139,7 @@
* iptables -R 1 bw_data_saver --jump RETURN
*/
-const std::string COMMIT_AND_CLOSE = "COMMIT\n\x04";
+const std::string COMMIT_AND_CLOSE = "COMMIT\n";
const std::string DATA_SAVER_ENABLE_COMMAND = "-R bw_data_saver 1";
const std::string HAPPY_BOX_WHITELIST_COMMAND = android::base::StringPrintf(
"-I bw_happy_box -m owner --uid-owner %d-%d --jump RETURN", 0, MAX_SYSTEM_UID);
@@ -270,7 +271,7 @@
flushExistingCostlyTables(doClean);
std::string commands = android::base::Join(IPT_FLUSH_COMMANDS, '\n');
- iptablesRestoreFunction(V4V6, commands);
+ iptablesRestoreFunction(V4V6, commands, nullptr);
}
int BandwidthController::setupIptablesHooks(void) {
@@ -297,7 +298,7 @@
flushCleanTables(false);
std::string commands = android::base::Join(IPT_BASIC_ACCOUNTING_COMMANDS, '\n');
- return iptablesRestoreFunction(V4V6, commands);
+ return iptablesRestoreFunction(V4V6, commands, nullptr);
}
int BandwidthController::disableBandwidthControl(void) {
@@ -1273,47 +1274,45 @@
}
void BandwidthController::flushExistingCostlyTables(bool doClean) {
- std::string fullCmd;
- FILE *iptOutput;
+ std::string fullCmd = "*filter\n-S\nCOMMIT\n";
+ std::string ruleList;
/* Only lookup ip4 table names as ip6 will have the same tables ... */
- fullCmd = IPTABLES_PATH;
- fullCmd += " -w -S";
- iptOutput = popenFunction(fullCmd.c_str(), "r");
- if (!iptOutput) {
- ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
+ if (int ret = iptablesRestoreFunction(V4, fullCmd, &ruleList)) {
+ ALOGE("Failed to list existing costly tables ret=%d", ret);
return;
}
/* ... then flush/clean both ip4 and ip6 iptables. */
- parseAndFlushCostlyTables(iptOutput, doClean);
- pclose(iptOutput);
+ parseAndFlushCostlyTables(ruleList, doClean);
}
-void BandwidthController::parseAndFlushCostlyTables(FILE *fp, bool doRemove) {
- int res;
- char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
- char costlyIfaceName[MAX_IPT_OUTPUT_LINE_LEN];
- char cmd[MAX_CMD_LEN];
- char *buffPtr;
+void BandwidthController::parseAndFlushCostlyTables(const std::string& ruleList, bool doRemove) {
+ std::stringstream stream(ruleList);
+ std::string rule;
+ std::vector<std::string> clearCommands = { "*filter" };
+ std::string chainName;
- while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
- costlyIfaceName[0] = '\0'; /* So that debugging output always works */
- res = sscanf(buffPtr, "-N bw_costly_%s", costlyIfaceName);
- ALOGV("parse res=%d costly=<%s> orig line=<%s>", res,
- costlyIfaceName, buffPtr);
- if (res != 1) {
- continue;
- }
- /* Exclusions: "shared" is not an ifacename */
- if (!strcmp(costlyIfaceName, "shared")) {
+ // Find and flush all rules starting with "-N bw_costly_<iface>" except "-N bw_costly_shared".
+ while (std::getline(stream, rule, '\n')) {
+ if (rule.find(NEW_CHAIN_COMMAND) != 0) continue;
+ chainName = rule.substr(NEW_CHAIN_COMMAND.size());
+ ALOGV("parse chainName=<%s> orig line=<%s>", chainName.c_str(), rule.c_str());
+
+ if (chainName.find("bw_costly_") != 0 || chainName == std::string("bw_costly_shared")) {
continue;
}
- snprintf(cmd, sizeof(cmd), "-F bw_costly_%s", costlyIfaceName);
- runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
+ clearCommands.push_back(android::base::StringPrintf(":%s -", chainName.c_str()));
if (doRemove) {
- snprintf(cmd, sizeof(cmd), "-X bw_costly_%s", costlyIfaceName);
- runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
+ clearCommands.push_back(android::base::StringPrintf("-X %s", chainName.c_str()));
}
}
+
+ if (clearCommands.size() == 1) {
+ // No rules found.
+ return;
+ }
+
+ clearCommands.push_back("COMMIT\n");
+ iptablesRestoreFunction(V4V6, android::base::Join(clearCommands, '\n'), nullptr);
}