am 551e5b47: am 553dc723: BandwidthController: validate interface / chain names
* commit '551e5b47a21294cf775f8effbb6f2bf34c664164':
BandwidthController: validate interface / chain names
diff --git a/BandwidthController.cpp b/BandwidthController.cpp
index 6fad1e2..a7c2c2c 100644
--- a/BandwidthController.cpp
+++ b/BandwidthController.cpp
@@ -1147,10 +1147,12 @@
* Parse the ptks and bytes out of:
* Chain natctrl_tether_counters (4 references)
* pkts bytes target prot opt in out source destination
- * 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 counter wlan0_rmnet0: 0 bytes
- * 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0 counter rmnet0_wlan0: 0 bytes
- * 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0 counter bt-pan_rmnet0: 0 bytes
- * 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0 counter rmnet0_bt-pan: 0 bytes
+ * 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0
+ * 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0
+ * 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0
+ * 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0
+ * It results in an error if invoked and no tethering counter rules exist. The constraint
+ * helps detect complete parsing failure.
*/
int BandwidthController::parseForwardChainStats(SocketClient *cli, const TetherStats filter,
FILE *fp, std::string &extraProcessingInfo) {
@@ -1163,6 +1165,7 @@
TetherStats stats;
char *buffPtr;
int64_t packets, bytes;
+ int statsFound = 0;
bool filterPair = filter.intIface[0] && filter.extIface[0];
@@ -1238,14 +1241,18 @@
stats = filter;
}
free(msg);
+ statsFound++;
}
}
- /* Successful if the last stats entry wasn't partial. */
- if ((stats.rxBytes == -1) == (stats.txBytes == -1)) {
- cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
- return 0;
+
+ /* It is always an error to find only one side of the stats. */
+ /* It is an error to find nothing when not filtering. */
+ if (((stats.rxBytes == -1) != (stats.txBytes == -1)) ||
+ (!statsFound && !filterPair)) {
+ return -1;
}
- return -1;
+ cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
+ return 0;
}
char *BandwidthController::TetherStats::getStatsLine(void) const {
diff --git a/BandwidthController.h b/BandwidthController.h
index 8164e18..6b7b5d3 100644
--- a/BandwidthController.h
+++ b/BandwidthController.h
@@ -87,7 +87,8 @@
* For all pairs, stats should have ifaceIn=ifaceOut="".
* Sends out to the cli the single stat (TetheringStatsReluts) or a list of stats
* (TetheringStatsListResult+CommandOkay).
- * Error is to be handled on the outside
+ * Error is to be handled on the outside.
+ * It results in an error if invoked and no tethering counter rules exist.
*/
int getTetherStats(SocketClient *cli, TetherStats &stats, std::string &extraProcessingInfo);
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 84e9d5d..6ec2afc 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -1359,6 +1359,11 @@
}
tetherStats.intIface = argc > 2 ? argv[2] : "";
tetherStats.extIface = argc > 3 ? argv[3] : "";
+ // No filtering requested and there are no interface pairs to lookup.
+ if (argc <= 2 && sNatCtrl->ifacePairList.empty()) {
+ cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
+ return 0;
+ }
int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
if (rc) {
extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
diff --git a/IdletimerController.cpp b/IdletimerController.cpp
index 54b4edd..76b79a7 100644
--- a/IdletimerController.cpp
+++ b/IdletimerController.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-// #define LOG_NDEBUG 0
-
/*
* MODUS OPERANDI
* --------------
@@ -95,6 +93,8 @@
*
*/
+#define LOG_NDEBUG 0
+
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
@@ -123,11 +123,27 @@
}
/* return 0 or non-zero */
int IdletimerController::runIpxtablesCmd(int argc, const char **argv) {
- int res;
+ int resIpv4, resIpv6;
- res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
- ALOGV("runCmd() res=%d", res);
- return res;
+ // Running for IPv4
+ argv[0] = IPTABLES_PATH;
+ resIpv4 = android_fork_execvp(argc, (char **)argv, NULL, false, false);
+
+ // Running for IPv6
+ argv[0] = IP6TABLES_PATH;
+ resIpv6 = android_fork_execvp(argc, (char **)argv, NULL, false, false);
+
+#if !LOG_NDEBUG
+ std::string full_cmd = argv[0];
+ argc--; argv++;
+ for (; argc; argc--, argv++) {
+ full_cmd += " ";
+ full_cmd += argv[0];
+ }
+ ALOGV("runCmd(%s) res_ipv4=%d, res_ipv6=%d", full_cmd.c_str(), resIpv4, resIpv6);
+#endif
+
+ return (resIpv4 == 0 && resIpv6 == 0) ? 0 : -1;
}
bool IdletimerController::setupIptablesHooks() {
@@ -137,7 +153,7 @@
int IdletimerController::setDefaults() {
int res;
const char *cmd1[] = {
- IPTABLES_PATH,
+ NULL, // To be filled inside runIpxtablesCmd
"-t",
"raw",
"-F",
@@ -149,7 +165,7 @@
return res;
const char *cmd2[] = {
- IPTABLES_PATH,
+ NULL, // To be filled inside runIpxtablesCmd
"-t",
"mangle",
"-F",
@@ -179,7 +195,7 @@
snprintf(timeout_str, sizeof(timeout_str), "%u", timeout);
const char *cmd1[] = {
- IPTABLES_PATH,
+ NULL, // To be filled inside runIpxtablesCmd
"-t",
"raw",
(op == IptOpAdd) ? "-A" : "-D",
@@ -201,7 +217,7 @@
return res;
const char *cmd2[] = {
- IPTABLES_PATH,
+ NULL, // To be filled inside runIpxtablesCmd
"-t",
"mangle",
(op == IptOpAdd) ? "-A" : "-D",
diff --git a/NatController.cpp b/NatController.cpp
index dd5316a..fbf5f8a 100644
--- a/NatController.cpp
+++ b/NatController.cpp
@@ -98,6 +98,7 @@
return -1;
}
}
+ ifacePairList.clear();
return 0;
}
@@ -252,27 +253,32 @@
return 0;
}
+bool NatController::checkTetherCountingRuleExist(const char *pair_name) {
+ std::list<std::string>::iterator it;
+
+ for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
+ if (*it == pair_name) {
+ /* We already have this counter */
+ return true;
+ }
+ }
+ return false;
+}
+
int NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
/* We only ever add tethering quota rules so that they stick. */
if (!add) {
return 0;
}
- char *quota_name, *proc_path;
+ char *pair_name, *proc_path;
int quota_fd;
- asprintf("a_name, "%s_%s", intIface, extIface);
+ asprintf(&pair_name, "%s_%s", intIface, extIface);
- asprintf(&proc_path, "/proc/net/xt_quota/%s", quota_name);
- quota_fd = open(proc_path, O_RDONLY);
- if (quota_fd >= 0) {
- /* quota for iface pair already exists */
- free(proc_path);
- free(quota_name);
+ if (checkTetherCountingRuleExist(pair_name)) {
+ free(pair_name);
return 0;
}
- close(quota_fd);
- free(proc_path);
-
const char *cmd2b[] = {
IPTABLES_PATH,
"-A",
@@ -281,32 +287,22 @@
intIface,
"-o",
extIface,
- "-m",
- "quota2",
- "--name",
- quota_name,
- "--grow",
"-j",
"RETURN"
};
if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) && add) {
- free(quota_name);
+ free(pair_name);
return -1;
}
- free(quota_name);
+ ifacePairList.push_front(pair_name);
+ free(pair_name);
- asprintf("a_name, "%s_%s", extIface, intIface);
- asprintf(&proc_path, "/proc/net/xt_quota/%s", quota_name);
- quota_fd = open(proc_path, O_RDONLY);
- if (quota_fd >= 0) {
- /* quota for iface pair already exists */
- free(proc_path);
- free(quota_name);
+ asprintf(&pair_name, "%s_%s", extIface, intIface);
+ if (checkTetherCountingRuleExist(pair_name)) {
+ free(pair_name);
return 0;
}
- close(quota_fd);
- free(proc_path);
const char *cmd3b[] = {
IPTABLES_PATH,
@@ -316,21 +312,17 @@
extIface,
"-o",
intIface,
- "-m",
- "quota2",
- "--name",
- quota_name,
- "--grow",
"-j",
"RETURN"
};
if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) && add) {
// unwind what's been done, but don't care about success - what more could we do?
- free(quota_name);
+ free(pair_name);
return -1;
}
- free(quota_name);
+ ifacePairList.push_front(pair_name);
+ free(pair_name);
return 0;
}
diff --git a/NatController.h b/NatController.h
index 5f45376..2912e4b 100644
--- a/NatController.h
+++ b/NatController.h
@@ -18,6 +18,8 @@
#define _NAT_CONTROLLER_H
#include <linux/in.h>
+#include <list>
+#include <string>
class NetworkController;
class SecondaryTableController;
@@ -36,11 +38,16 @@
static const char* LOCAL_NAT_POSTROUTING;
static const char* LOCAL_TETHER_COUNTERS_CHAIN;
+ // List of strings of interface pairs.
+ std::list<std::string> ifacePairList;
+
private:
int natCount;
SecondaryTableController *mSecondaryTableCtrl;
NetworkController *mNetCtrl;
+ bool checkTetherCountingRuleExist(const char *pair_name);
+
int setDefaults();
int runCmd(int argc, const char **argv);
bool checkInterface(const char *iface);
diff --git a/NetlinkHandler.cpp b/NetlinkHandler.cpp
index 534f386..9c2984f 100644
--- a/NetlinkHandler.cpp
+++ b/NetlinkHandler.cpp
@@ -91,14 +91,11 @@
} else if (!strcmp(subsys, "xt_idletimer")) {
int action = evt->getAction();
- const char *label = evt->findParam("LABEL");
+ const char *label = evt->findParam("INTERFACE");
const char *state = evt->findParam("STATE");
- // if no LABEL, use INTERFACE instead
- if (label == NULL) {
- label = evt->findParam("INTERFACE");
- }
+ const char *timestamp = evt->findParam("TIME_NS");
if (state)
- notifyInterfaceClassActivity(label, !strcmp("active", state));
+ notifyInterfaceClassActivity(label, !strcmp("active", state), timestamp);
#if !LOG_NDEBUG
} else if (strcmp(subsys, "platform") && strcmp(subsys, "backlight")) {
@@ -144,9 +141,13 @@
}
void NetlinkHandler::notifyInterfaceClassActivity(const char *name,
- bool isActive) {
- notify(ResponseCode::InterfaceClassActivity,
+ bool isActive, const char *timestamp) {
+ if (timestamp == NULL)
+ notify(ResponseCode::InterfaceClassActivity,
"IfaceClass %s %s", isActive ? "active" : "idle", name);
+ else
+ notify(ResponseCode::InterfaceClassActivity,
+ "IfaceClass %s %s %s", isActive ? "active" : "idle", name, timestamp);
}
void NetlinkHandler::notifyAddressChanged(int action, const char *addr,
diff --git a/NetlinkHandler.h b/NetlinkHandler.h
index 94b7282..a5c5b6b 100644
--- a/NetlinkHandler.h
+++ b/NetlinkHandler.h
@@ -39,7 +39,8 @@
void notifyInterfaceChanged(const char *name, bool isUp);
void notifyInterfaceLinkChanged(const char *name, bool isUp);
void notifyQuotaLimitReached(const char *name, const char *iface);
- void notifyInterfaceClassActivity(const char *name, bool isActive);
+ void notifyInterfaceClassActivity(const char *name, bool isActive,
+ const char *timestamp);
void notifyAddressChanged(int action, const char *addr, const char *iface,
const char *flags, const char *scope);
void notifyInterfaceDnsServers(const char *iface, const char *lifetime,
diff --git a/SoftapController.cpp b/SoftapController.cpp
index 825a376..7d5da95 100644
--- a/SoftapController.cpp
+++ b/SoftapController.cpp
@@ -144,7 +144,7 @@
if (argc > 7) {
if (!strcmp(argv[6], "wpa-psk")) {
generatePsk(argv[3], argv[7], psk_str);
- asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);
+ asprintf(&fbuf, "%swpa=3\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);
} else if (!strcmp(argv[6], "wpa2-psk")) {
generatePsk(argv[3], argv[7], psk_str);
asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);