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

netd: BandwidthController: support reading out tethering stats

* Add
  ndc bandwidth gettetherstats <ifaceIn> <ifaceOut>
which returns
  221  ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
If the iface pair is not found it will fail.

221 is the new response code for TetheringStatsResult.
It gets the stats by looking at the iptables FORWARD chain's counters.

* Fixed return handling after some of the responses.
  - no need for errorno
  - after ResponseCode >= 200, don't return another.

* Correctly initialize the alert values on "bandwidth enable"

Bug: 5244846,5230066
Change-Id: I81c941441525fa4055ae270d5cad05e6c42b8f72
parent 65969062
......@@ -14,8 +14,17 @@
* limitations under the License.
*/
// #define LOG_NDEBUG 0
/*
* The CommandListener, FrameworkListener don't allow for
* multiple calls in parallel to reach the BandwidthController.
* If they ever were to allow it, then netd/ would need some tweaking.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -36,13 +45,16 @@ extern "C" int logwrap(int argc, const char **argv, int background);
#include "BandwidthController.h"
const int BandwidthController::MAX_CMD_LEN = 1024;
const int BandwidthController::MAX_IFACENAME_LEN = 64;
const int BandwidthController::MAX_CMD_ARGS = 32;
const char BandwidthController::IPTABLES_PATH[] = "/system/bin/iptables";
const char BandwidthController::IP6TABLES_PATH[] = "/system/bin/ip6tables";
/* 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 int BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4;
const char BandwidthController::IP6TABLES_PATH[] = "/system/bin/ip6tables";
const char BandwidthController::IPTABLES_PATH[] = "/system/bin/iptables";
const int BandwidthController::MAX_CMD_ARGS = 32;
const int BandwidthController::MAX_CMD_LEN = 1024;
const int BandwidthController::MAX_IFACENAME_LEN = 64;
const int BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256;
bool BandwidthController::useLogwrapCall = false;
/**
......@@ -83,7 +95,7 @@ bool BandwidthController::useLogwrapCall = false;
* iptables -A penalty_box -m owner --uid-owner app_3 \
* --jump REJECT --reject-with icmp-net-prohibited
*/
const char *BandwidthController::cleanupCommands[] = {
const char *BandwidthController::IPT_CLEANUP_COMMANDS[] = {
/* Cleanup rules. */
"-F",
"-t raw -F",
......@@ -93,13 +105,13 @@ const char *BandwidthController::cleanupCommands[] = {
"-X", /* Should normally only be costly_shared, penalty_box, and costly_<iface> */
};
const char *BandwidthController::setupCommands[] = {
const char *BandwidthController::IPT_SETUP_COMMANDS[] = {
/* Created needed chains. */
"-N costly_shared",
"-N penalty_box",
};
const char *BandwidthController::basicAccountingCommands[] = {
const char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = {
"-F INPUT",
"-A INPUT -i lo --jump ACCEPT",
"-A INPUT -m owner --socket-exists", /* This is a tracking rule. */
......@@ -132,7 +144,7 @@ BandwidthController::BandwidthController(void) {
int BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling) {
int res = 0;
LOGD("runIpxtablesCmd(cmd=%s)", cmd);
LOGV("runIpxtablesCmd(cmd=%s)", cmd);
res |= runIptablesCmd(cmd, rejectHandling, IptIpV4);
res |= runIptablesCmd(cmd, rejectHandling, IptIpV6);
return res;
......@@ -199,31 +211,38 @@ int BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandl
int BandwidthController::enableBandwidthControl(void) {
int res;
/* Some of the initialCommands are allowed to fail */
runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, RunCmdFailureOk);
runCommands(sizeof(setupCommands) / sizeof(char*), setupCommands, RunCmdFailureOk);
res = runCommands(sizeof(basicAccountingCommands) / sizeof(char*), basicAccountingCommands,
RunCmdFailureBad);
sharedQuotaBytes = sharedAlertBytes = 0;
/* Let's pretend we started from scratch ... */
sharedQuotaIfaces.clear();
quotaIfaces.clear();
naughtyAppUids.clear();
globalAlertBytes = 0;
sharedQuotaBytes = sharedAlertBytes = 0;
/* Some of the initialCommands are allowed to fail */
runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*),
IPT_CLEANUP_COMMANDS, RunCmdFailureOk);
runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*),
IPT_SETUP_COMMANDS, RunCmdFailureOk);
res = runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*),
IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad);
return res;
}
int BandwidthController::disableBandwidthControl(void) {
/* The cleanupCommands are allowed to fail. */
runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, RunCmdFailureOk);
/* The IPT_CLEANUP_COMMANDS are allowed to fail. */
runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*),
IPT_CLEANUP_COMMANDS, RunCmdFailureOk);
return 0;
}
int BandwidthController::runCommands(int numCommands, const char *commands[],
RunCmdErrHandling cmdErrHandling) {
int res = 0;
LOGD("runCommands(): %d commands", numCommands);
LOGV("runCommands(): %d commands", numCommands);
for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) {
res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd);
if (res && cmdErrHandling != RunCmdFailureBad)
......@@ -312,7 +331,7 @@ std::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *cost
char *buff;
const char *opFlag;
LOGD("makeIptablesQuotaCmd(%d, %lld)", op, quota);
LOGV("makeIptablesQuotaCmd(%d, %lld)", op, quota);
switch (op) {
case IptOpInsert:
......@@ -593,7 +612,7 @@ int BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes)
return -1;
}
scanRes = fscanf(fp, "%lld", bytes);
LOGD("Read quota res=%d bytes=%lld", scanRes, *bytes);
LOGV("Read quota res=%d bytes=%lld", scanRes, *bytes);
fclose(fp);
return scanRes == 1 ? 0 : -1;
}
......@@ -812,3 +831,86 @@ int BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertB
free(alertName);
return res;
}
/*
* Parse the ptks and bytes out of:
* Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
* 0 0 ACCEPT all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
* 0 0 DROP all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 state INVALID
* 0 0 ACCEPT all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0
*
*/
int BandwidthController::parseForwardChainStats(TetherStats &stats, FILE *fp) {
int res;
char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
char iface0[MAX_IPT_OUTPUT_LINE_LEN];
char iface1[MAX_IPT_OUTPUT_LINE_LEN];
char rest[MAX_IPT_OUTPUT_LINE_LEN];
char *buffPtr;
int64_t packets, bytes;
while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
/* Clean up, so a failed parse can still print info */
iface0[0] = iface1[0] = rest[0] = packets = bytes = 0;
res = sscanf(buffPtr, "%lld %lld ACCEPT all -- %s %s 0.%s",
&packets, &bytes, iface0, iface1, rest);
LOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%lld bytes=%lld rest=<%s> orig line=<%s>", res,
iface0, iface1, packets, bytes, rest, buffPtr);
if (res != 5) {
continue;
}
if ((stats.ifaceIn == iface0) && (stats.ifaceOut == iface1)) {
LOGV("iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets);
stats.rxPackets = packets;
stats.rxBytes = bytes;
} else if ((stats.ifaceOut == iface0) && (stats.ifaceIn == iface1)) {
LOGV("iface_in=%s iface_out=%s tx_bytes=%lld tx_packets=%lld ", iface1, iface0, bytes, packets);
stats.txPackets = packets;
stats.txBytes = bytes;
}
}
/* Failure if rx or tx was not found */
return (stats.rxBytes == -1 || stats.txBytes == -1) ? -1 : 0;
}
char *BandwidthController::TetherStats::getStatsLine(void) {
char *msg;
asprintf(&msg, "%s %s %lld %lld %lld %lld", ifaceIn.c_str(), ifaceOut.c_str(),
rxBytes, rxPackets, txBytes, txPackets);
return msg;
}
int BandwidthController::getTetherStats(TetherStats &stats) {
int res;
std::string fullCmd;
FILE *iptOutput;
const char *cmd;
if (stats.rxBytes != -1 || stats.txBytes != -1) {
LOGE("Unexpected input stats. Byte counts should be -1.");
return -1;
}
/*
* Why not use some kind of lib to talk to iptables?
* Because the only libs are libiptc and libip6tc in iptables, and they are
* not easy to use. They require the known iptables match modules to be
* preloaded/linked, and require apparently a lot of wrapper code to get
* the wanted info.
*/
fullCmd = IPTABLES_PATH;
fullCmd += " -nvx -L FORWARD";
iptOutput = popen(fullCmd.c_str(), "r");
if (!iptOutput) {
LOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
return -1;
}
res = parseForwardChainStats(stats, iptOutput);
pclose(iptOutput);
/* Currently NatController doesn't do ipv6 tethering, so we are done. */
return res;
}
......@@ -19,8 +19,32 @@
#include <list>
#include <string>
#include <utility> // for pair
class BandwidthController {
public:
class TetherStats {
public:
TetherStats(void)
: rxBytes(-1), rxPackets(-1),
txBytes(-1), txPackets(-1) {};
TetherStats(std::string ifnIn, std::string ifnOut,
int64_t rxB, int64_t rxP,
int64_t txB, int64_t txP)
: ifaceIn(ifnIn), ifaceOut(ifnOut),
rxBytes(rxB), rxPackets(rxP),
txBytes(txB), txPackets(txP) {};
std::string ifaceIn;
std::string ifaceOut;
int64_t rxBytes, rxPackets;
int64_t txBytes, txPackets;
/*
* Allocates a new string representing this:
* ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
* The caller is responsible for free()'ing the returned ptr.
*/
char *getStatsLine(void);
};
BandwidthController();
int enableBandwidthControl(void);
int disableBandwidthControl(void);
......@@ -45,6 +69,12 @@ public:
int setInterfaceAlert(const char *iface, int64_t bytes);
int removeInterfaceAlert(const char *iface);
/*
* stats should have ifaceIn and ifaceOut initialized.
* Byte counts should be left to the default (-1).
*/
int getTetherStats(TetherStats &stats);
protected:
class QuotaInfo {
public:
......@@ -54,6 +84,7 @@ protected:
int64_t quota;
int64_t alert;
};
enum IptIpVer { IptIpV4, IptIpV6 };
enum IptOp { IptOpInsert, IptOpReplace, IptOpDelete };
enum IptRejectOp { IptRejectAdd, IptRejectNoAdd };
......@@ -61,13 +92,6 @@ protected:
enum QuotaType { QuotaUnique, QuotaShared };
enum RunCmdErrHandling { RunCmdFailureBad, RunCmdFailureOk };
std::list<std::string> sharedQuotaIfaces;
int64_t sharedQuotaBytes;
int64_t sharedAlertBytes;
std::list<QuotaInfo> quotaIfaces;
std::list<int /*appUid*/> naughtyAppUids;
int maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp);
int prepCostlyIface(const char *ifn, QuotaType quotaType);
......@@ -89,26 +113,43 @@ protected:
int updateQuota(const char *alertName, int64_t bytes);
int64_t globalAlertBytes;
int setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes);
int removeCostlyAlert(const char *costName, int64_t *alertBytes);
/*
* When false, it will directly use system() instead of logwrap()
* stats should have ifaceIn and ifaceOut initialized.
* fp should be a file to the FORWARD rules of iptables.
*/
static bool useLogwrapCall;
static int parseForwardChainStats(TetherStats &stats, FILE *fp);
/*------------------*/
std::list<std::string> sharedQuotaIfaces;
int64_t sharedQuotaBytes;
int64_t sharedAlertBytes;
int64_t globalAlertBytes;
std::list<QuotaInfo> quotaIfaces;
std::list<int /*appUid*/> naughtyAppUids;
private:
static const char *cleanupCommands[];
static const char *setupCommands[];
static const char *basicAccountingCommands[];
static const int MAX_CMD_LEN;
static const int MAX_IFACENAME_LEN;
static const int MAX_CMD_ARGS;
static const char IPTABLES_PATH[];
static const char IP6TABLES_PATH[];
static const char *IPT_CLEANUP_COMMANDS[];
static const char *IPT_SETUP_COMMANDS[];
static const char *IPT_BASIC_ACCOUNTING_COMMANDS[];
/* Alphabetical */
static const char ALERT_IPT_TEMPLATE[];
static const int ALERT_RULE_POS_IN_COSTLY_CHAIN;
static const int ALERT_RULE_POS_IN_COSTLY_CHAIN;
static const char IP6TABLES_PATH[];
static const char IPTABLES_PATH[];
static const int MAX_CMD_ARGS;
static const int MAX_CMD_LEN;
static const int MAX_IFACENAME_LEN;
static const int MAX_IPT_OUTPUT_LINE_LEN;
/*
* When false, it will directly use system() instead of logwrap()
*/
static bool useLogwrapCall;
};
#endif
......@@ -14,6 +14,8 @@
* limitations under the License.
*/
// #define LOG_NDEBUG 0
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
......@@ -847,75 +849,109 @@ CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
NetdCommand("bandwidth") {
}
void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
char *msg;
asprintf(&msg, "Usage: bandwidth %s", usageMsg);
cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
free(msg);
}
void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
if (!cond) {
cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
}
}
void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
}
int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
int rc = 0;
LOGD("bwctrlcmd: argc=%d argv[0]=%s", argc, argv[0]);
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
sendGenericSyntaxError(cli, "<cmds> <args...>");
return 0;
}
LOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
if (!strcmp(argv[1], "enable")) {
rc = sBandwidthCtrl->enableBandwidthControl();
} else if (!strcmp(argv[1], "disable")) {
rc = sBandwidthCtrl->disableBandwidthControl();
int rc = sBandwidthCtrl->enableBandwidthControl();
sendGenericOkFail(cli, rc);
return 0;
}
if (!strcmp(argv[1], "disable")) {
int rc = sBandwidthCtrl->disableBandwidthControl();
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
}
if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removequota <interface>", false);
sendGenericSyntaxError(cli, "removequota <interface>");
return 0;
}
rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
}
if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
int64_t bytes;
if (argc != 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth getquota", false);
sendGenericSyntaxError(cli, "getquota");
return 0;
}
rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
if (rc) {
cli->sendMsg(ResponseCode::OperationFailed, "Failed to get quota", true);
sendGenericOpFailed(cli, "Failed to get quota");
return 0;
}
char *msg;
asprintf(&msg, "%lld", bytes);
cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
free(msg);
return 0;
} else if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
}
if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
int64_t bytes;
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth getiquota <iface>", false);
sendGenericSyntaxError(cli, "getiquota <iface>");
return 0;
}
rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
if (rc) {
cli->sendMsg(ResponseCode::OperationFailed, "Failed to get quota", true);
sendGenericOpFailed(cli, "Failed to get quota");
return 0;
}
char *msg;
asprintf(&msg, "%lld", bytes);
cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
free(msg);
return 0;
} else if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
}
if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth setquota <interface> <bytes>", false);
sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
return 0;
}
rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
} else if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
sendGenericOkFail(cli, rc);
return 0;
}
if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
int rc;
if (argc < 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth setquotas <bytes> <interface> ...", false);
sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
return 0;
}
for (int q = 3; argc >= 4; q++, argc--) {
rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
if (rc) {
......@@ -924,16 +960,20 @@ int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc
cli->sendMsg(ResponseCode::OperationFailed,
msg, false);
free(msg);
break;
return 0;
}
}
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
}
if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
int rc;
if (argc < 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removequotas <interface> ...", false);
sendGenericSyntaxError(cli, "removequotas <interface> ...");
return 0;
}
for (int q = 2; argc >= 3; q++, argc--) {
rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
if (rc) {
......@@ -942,99 +982,136 @@ int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc
cli->sendMsg(ResponseCode::OperationFailed,
msg, false);
free(msg);
break;
return 0;
}
}
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
}
if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removeiquota <interface>", false);
sendGenericSyntaxError(cli, "removeiquota <interface>");
return 0;
}
rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
}
if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth setiquota <interface> <bytes>", false);
sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
return 0;
}
rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
}
if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
if (argc < 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth addnaughtyapps <appUid> ...", false);
sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
return 0;
}
rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
}
if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
if (argc < 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removenaughtyapps <appUid> ...", false);
sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
return 0;
}
rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
}
if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth setglobalalert <bytes>", false);
sendGenericSyntaxError(cli, "setglobalalert <bytes>");
return 0;
}
rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
}
if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
if (argc != 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removeglobalalert", false);
sendGenericSyntaxError(cli, "removeglobalalert");
return 0;
}
rc = sBandwidthCtrl->removeGlobalAlert();
int rc = sBandwidthCtrl->removeGlobalAlert();
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
}
if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth setsharedalert <bytes>", false);
sendGenericSyntaxError(cli, "setsharedalert <bytes>");
return 0;
}
rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
}
if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
if (argc != 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removesharedalert", false);
sendGenericSyntaxError(cli, "removesharedalert");
return 0;
}
rc = sBandwidthCtrl->removeSharedAlert();
int rc = sBandwidthCtrl->removeSharedAlert();
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
}
if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth setinterfacealert <interface> <bytes>", false);
sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
return 0;
}
rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
sendGenericOkFail(cli, rc);
return 0;
} else if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
}
if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: bandwidth removeinterfacealert <interface>", false);
sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
return 0;
}
rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
sendGenericOkFail(cli, rc);
return 0;
}
if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
BandwidthController::TetherStats tetherStats;
if (argc != 4) {
sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>");
return 0;
}
tetherStats.ifaceIn = argv[2];
tetherStats.ifaceOut = argv[3];
int rc = sBandwidthCtrl->getTetherStats(tetherStats);
if (rc) {
sendGenericOpFailed(cli, "Failed to get tethering stats");
return 0;
}
char *msg = tetherStats.getStatsLine();
cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false);
free(msg);
return 0;
if (!rc) {
cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", true);
}
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
return 0;
}
......@@ -106,6 +106,10 @@ private:
BandwidthControlCmd();
virtual ~BandwidthControlCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
protected:
void sendGenericOkFail(SocketClient *cli, int cond);
void sendGenericOpFailed(SocketClient *cli, const char *errMsg);
void sendGenericSyntaxError(SocketClient *cli, const char *usageMsg);
};
class ResolverCmd : public NetdCommand {
......
......@@ -43,6 +43,7 @@ public:
static const int InterfaceRxThrottleResult = 218;
static const int InterfaceTxThrottleResult = 219;
static const int QuotaCounterResult = 220;
static const int TetheringStatsResult = 221;
// 400 series - The command was accepted but the requested action
// did not take place.
......
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