Commit c6c67349 authored by JP Abgrall's avatar JP Abgrall
Browse files

netd: bandwidth: tethering global alert support

Now, when nat is enabled/disabled it will let the bandwidthcontroller
know that it might need to add/remove the matching global alert into
the tethering rules in the FORWARD chain of iptables.

Bug: 5336638
Change-Id: I1843f3f6601f371537f754a31db792e054b36a1d
parent c1b38701
......@@ -48,6 +48,7 @@ extern "C" int logwrap(int argc, const char **argv, int background);
/* Alphabetical */
const char BandwidthController::ALERT_IPT_TEMPLATE[] = "%s %s %s -m quota2 ! --quota %lld --name %s";
const int BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4;
const char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert";
const char BandwidthController::IP6TABLES_PATH[] = "/system/bin/ip6tables";
const char BandwidthController::IPTABLES_PATH[] = "/system/bin/iptables";
const int BandwidthController::MAX_CMD_ARGS = 32;
......@@ -217,6 +218,7 @@ int BandwidthController::enableBandwidthControl(void) {
quotaIfaces.clear();
naughtyAppUids.clear();
globalAlertBytes = 0;
globalAlertTetherCount = 0;
sharedQuotaBytes = sharedAlertBytes = 0;
......@@ -698,9 +700,35 @@ int BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, in
return res;
}
int BandwidthController::setGlobalAlert(int64_t bytes) {
int BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) {
int res = 0;
const char *opFlag;
const char *ifaceLimiting;
char *alertQuotaCmd;
const char *alertName = "globalAlert";
switch (op) {
case IptOpInsert:
opFlag = "-I";
break;
case IptOpReplace:
opFlag = "-R";
break;
default:
case IptOpDelete:
opFlag = "-D";
break;
}
ifaceLimiting = "! -i lo+";
asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "FORWARD",
bytes, alertName, alertName);
res = runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
free(alertQuotaCmd);
return res;
}
int BandwidthController::setGlobalAlert(int64_t bytes) {
const char *alertName = ALERT_GLOBAL_NAME;
int res = 0;
if (!bytes) {
......@@ -711,15 +739,39 @@ int BandwidthController::setGlobalAlert(int64_t bytes) {
res = updateQuota(alertName, bytes);
} else {
res = runIptablesAlertCmd(IptOpInsert, alertName, bytes);
if (globalAlertTetherCount) {
LOGV("setGlobalAlert for %d tether", globalAlertTetherCount);
res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes);
}
}
globalAlertBytes = bytes;
return res;
}
int BandwidthController::setGlobalAlertInForwardChain(void) {
const char *alertName = ALERT_GLOBAL_NAME;
int res = 0;
globalAlertTetherCount++;
LOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount);
/*
* 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 (!globalAlertBytes || globalAlertTetherCount != 1) {
return 0;
}
/* We only add the rule if this was the 1st tether added. */
res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes);
return res;
}
int BandwidthController::removeGlobalAlert(void) {
char *alertQuotaCmd;
const char *alertName = "globalAlert";
const char *alertName = ALERT_GLOBAL_NAME;
int res = 0;
if (!globalAlertBytes) {
......@@ -727,10 +779,37 @@ int BandwidthController::removeGlobalAlert(void) {
return -1;
}
res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes);
if (globalAlertTetherCount) {
res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
}
globalAlertBytes = 0;
return res;
}
int BandwidthController::removeGlobalAlertInForwardChain(void) {
int res = 0;
const char *alertName = ALERT_GLOBAL_NAME;
if (!globalAlertTetherCount) {
LOGE("No prior alert set");
return -1;
}
globalAlertTetherCount--;
/*
* 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 (!globalAlertBytes || globalAlertTetherCount >= 1) {
return 0;
}
/* We only detete the rule if this was the last tether removed. */
res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
return res;
}
int BandwidthController::setSharedAlert(int64_t bytes) {
if (!sharedQuotaBytes) {
LOGE("Need to have a prior shared quota set to set an alert");
......
......@@ -62,6 +62,8 @@ public:
int setGlobalAlert(int64_t bytes);
int removeGlobalAlert(void);
int setGlobalAlertInForwardChain(void);
int removeGlobalAlertInForwardChain(void);
int setSharedAlert(int64_t bytes);
int removeSharedAlert(void);
......@@ -101,6 +103,7 @@ protected:
std::string makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota);
int runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes);
int runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes);
/* Runs for both ipv4 and ipv6 iptables */
int runCommands(int numCommands, const char *commands[], RunCmdErrHandling cmdErrHandling);
......@@ -128,6 +131,16 @@ protected:
int64_t sharedQuotaBytes;
int64_t sharedAlertBytes;
int64_t globalAlertBytes;
/*
* 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 globalAlertTetherCount;
std::list<QuotaInfo> quotaIfaces;
std::list<int /*appUid*/> naughtyAppUids;
......@@ -139,6 +152,7 @@ private:
/* Alphabetical */
static const char ALERT_IPT_TEMPLATE[];
static const int ALERT_RULE_POS_IN_COSTLY_CHAIN;
static const char ALERT_GLOBAL_NAME[];
static const char IP6TABLES_PATH[];
static const char IPTABLES_PATH[];
static const int MAX_CMD_ARGS;
......
......@@ -582,8 +582,16 @@ int CommandListener::NatCmd::runCommand(SocketClient *cli,
if (!strcmp(argv[1], "enable")) {
rc = sNatCtrl->enableNat(argv[2], argv[3]);
if(!rc) {
/* Ignore ifaces for now. */
rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
}
} else if (!strcmp(argv[1], "disable")) {
rc = sNatCtrl->disableNat(argv[2], argv[3]);
if(!rc) {
/* Ignore ifaces for now. */
rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
}
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
return 0;
......@@ -1046,6 +1054,17 @@ int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc
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 = sBandwidthCtrl->setGlobalAlertInForwardChain();
sendGenericOkFail(cli, rc);
return 0;
}
if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
if (argc != 2) {
......@@ -1056,6 +1075,17 @@ int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc
sendGenericOkFail(cli, rc);
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 = sBandwidthCtrl->removeGlobalAlertInForwardChain();
sendGenericOkFail(cli, rc);
return 0;
}
if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
if (argc != 3) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment