summaryrefslogtreecommitdiffstats
path: root/server/IdletimerController.cpp
diff options
context:
space:
mode:
authorSreeram Ramachandran <sreeram@google.com>2014-05-21 08:54:07 -0700
committerSreeram Ramachandran <sreeram@google.com>2014-05-21 09:03:35 -0700
commitf4cfad361175a7f9ccf4d41e76a9b289c3c3da22 (patch)
treeadef9c2f736b8a566b0edd9ff83f92493c367f34 /server/IdletimerController.cpp
parent5ff58d494a5ddf7e544adc77590300f04daf8e31 (diff)
downloadplatform_system_netd-f4cfad361175a7f9ccf4d41e76a9b289c3c3da22.tar.gz
platform_system_netd-f4cfad361175a7f9ccf4d41e76a9b289c3c3da22.tar.bz2
platform_system_netd-f4cfad361175a7f9ccf4d41e76a9b289c3c3da22.zip
Move netd_client into netd.
Change-Id: Ie4b6b303225c93f2448a503d6ea9cebb552cbad5
Diffstat (limited to 'server/IdletimerController.cpp')
-rw-r--r--server/IdletimerController.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/server/IdletimerController.cpp b/server/IdletimerController.cpp
new file mode 100644
index 000000000..76b79a792
--- /dev/null
+++ b/server/IdletimerController.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * MODUS OPERANDI
+ * --------------
+ *
+ * IPTABLES command sequence:
+ *
+ * iptables -F
+ *
+ * iptables -t raw -F idletimer_PREROUTING
+ * iptables -t mangle -F idletimer_POSTROUTING
+ *
+ *
+ * iptables -t raw -N idletimer_PREROUTING
+ * iptables -t mangle -N idletimer_POSTROUTING
+ *
+ * iptables -t raw -D PREROUTING -j idletimer_PREROUTING
+ * iptables -t mangle -D POSTROUTING -j idletimer_POSTROUTING
+ *
+ *
+ * iptables -t raw -I PREROUTING -j idletimer_PREROUTING
+ * iptables -t mangle -I POSTROUTING -j idletimer_POSTROUTING
+ *
+ * # For notifications to work the lable name must match the name of a valid interface.
+ * # If the label name does match an interface, the rules will be a no-op.
+ *
+ * iptables -t raw -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER --timeout 5 --label test-chain --send_nl_msg 1
+ * iptables -t mangle -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER --timeout 5 --label test-chain --send_nl_msg 1
+ *
+ * iptables -nxvL -t raw
+ * iptables -nxvL -t mangle
+ *
+ * =================
+ *
+ * ndc command sequence
+ * ------------------
+ * ndc idletimer enable
+ * ndc idletimer add <iface> <timeout> <class label>
+ * ndc idletimer remove <iface> <timeout> <class label>
+ *
+ * Monitor effect on the iptables chains after each step using:
+ * iptables -nxvL -t raw
+ * iptables -nxvL -t mangle
+ *
+ * Remember that the timeout value has to be same at the time of the
+ * removal.
+ *
+ * =================
+ *
+ * Verifying the iptables rule
+ * ---------------------------
+ * We want to make sure the iptable rules capture every packet. It can be
+ * verified with tcpdump. First take a note of the pkts count for the two rules:
+ *
+ * adb shell iptables -t mangle -L idletimer_mangle_POSTROUTING -v && adb shell iptables -t raw -L idletimer_raw_PREROUTING -v
+ *
+ * And then, before any network traffics happen on the device, run tcpdump:
+ *
+ * adb shell tcpdump | tee tcpdump.log
+ *
+ * After a while run iptables commands again, you could then count the number
+ * of incoming and outgoing packets captured by tcpdump, and compare that with
+ * the numbers reported by iptables command. There shouldn't be too much
+ * difference on these numbers, i.e., with 2000 packets captured it should
+ * differ by less than 5.
+ *
+ * =================
+ *
+ * Note that currently if the name of the iface is incorrect, iptables
+ * will setup rules without checking if it is the name of a valid
+ * interface (although no notifications will ever be received). It is
+ * the responsibility of code in Java land to ensure that the interface name
+ * is correct. The benefit of this, is that idletimers can be setup on
+ * interfaces than come and go.
+ *
+ * A remove should be called for each add command issued during cleanup, as duplicate
+ * entries of the rule may exist and will all have to removed.
+ *
+ */
+
+#define LOG_NDEBUG 0
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <cutils/properties.h>
+
+#define LOG_TAG "IdletimerController"
+#include <cutils/log.h>
+#include <logwrap/logwrap.h>
+
+#include "IdletimerController.h"
+#include "NetdConstants.h"
+
+const char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
+const char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING";
+
+IdletimerController::IdletimerController() {
+}
+
+IdletimerController::~IdletimerController() {
+}
+/* return 0 or non-zero */
+int IdletimerController::runIpxtablesCmd(int argc, const char **argv) {
+ int resIpv4, resIpv6;
+
+ // 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() {
+ return true;
+}
+
+int IdletimerController::setDefaults() {
+ int res;
+ const char *cmd1[] = {
+ NULL, // To be filled inside runIpxtablesCmd
+ "-t",
+ "raw",
+ "-F",
+ LOCAL_RAW_PREROUTING
+ };
+ res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
+
+ if (res)
+ return res;
+
+ const char *cmd2[] = {
+ NULL, // To be filled inside runIpxtablesCmd
+ "-t",
+ "mangle",
+ "-F",
+ LOCAL_MANGLE_POSTROUTING
+ };
+ res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
+
+ return res;
+}
+
+int IdletimerController::enableIdletimerControl() {
+ int res = setDefaults();
+ return res;
+}
+
+int IdletimerController::disableIdletimerControl() {
+ int res = setDefaults();
+ return res;
+}
+
+int IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
+ uint32_t timeout,
+ const char *classLabel) {
+ int res;
+ char timeout_str[11]; //enough to store any 32-bit unsigned decimal
+
+ snprintf(timeout_str, sizeof(timeout_str), "%u", timeout);
+
+ const char *cmd1[] = {
+ NULL, // To be filled inside runIpxtablesCmd
+ "-t",
+ "raw",
+ (op == IptOpAdd) ? "-A" : "-D",
+ LOCAL_RAW_PREROUTING,
+ "-i",
+ iface,
+ "-j",
+ "IDLETIMER",
+ "--timeout",
+ timeout_str,
+ "--label",
+ classLabel,
+ "--send_nl_msg",
+ "1"
+ };
+ res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
+
+ if (res)
+ return res;
+
+ const char *cmd2[] = {
+ NULL, // To be filled inside runIpxtablesCmd
+ "-t",
+ "mangle",
+ (op == IptOpAdd) ? "-A" : "-D",
+ LOCAL_MANGLE_POSTROUTING,
+ "-o",
+ iface,
+ "-j",
+ "IDLETIMER",
+ "--timeout",
+ timeout_str,
+ "--label",
+ classLabel,
+ "--send_nl_msg",
+ "1"
+ };
+ res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
+
+ return res;
+}
+
+int IdletimerController::addInterfaceIdletimer(const char *iface,
+ uint32_t timeout,
+ const char *classLabel) {
+ return modifyInterfaceIdletimer(IptOpAdd, iface, timeout, classLabel);
+}
+
+int IdletimerController::removeInterfaceIdletimer(const char *iface,
+ uint32_t timeout,
+ const char *classLabel) {
+ return modifyInterfaceIdletimer(IptOpDelete, iface, timeout, classLabel);
+}