Merge "Changed format of interface class acitivity message."
diff --git a/Android.mk b/Android.mk
index cdaa184..4e6c6f3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -6,8 +6,9 @@
BandwidthController.cpp \
CommandListener.cpp \
DnsProxyListener.cpp \
- MDnsSdListener.cpp \
+ FirewallController.cpp \
IdletimerController.cpp \
+ MDnsSdListener.cpp \
NatController.cpp \
NetdCommand.cpp \
NetdConstants.cpp \
diff --git a/BandwidthController.cpp b/BandwidthController.cpp
index 31cdcab..e5d3054 100644
--- a/BandwidthController.cpp
+++ b/BandwidthController.cpp
@@ -51,6 +51,11 @@
#define 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::LOCAL_INPUT = "bw_INPUT";
+const char* BandwidthController::LOCAL_FORWARD = "bw_FORWARD";
+const char* BandwidthController::LOCAL_OUTPUT = "bw_OUTPUT";
+const char* BandwidthController::LOCAL_RAW_PREROUTING = "bw_raw_PREROUTING";
+const char* BandwidthController::LOCAL_MANGLE_POSTROUTING = "bw_mangle_POSTROUTING";
const int BandwidthController::MAX_CMD_ARGS = 32;
const int BandwidthController::MAX_CMD_LEN = 1024;
const int BandwidthController::MAX_IFACENAME_LEN = 64;
@@ -113,42 +118,13 @@
/* The cleanup commands assume flushing has been done. */
const char *BandwidthController::IPT_CLEANUP_COMMANDS[] = {
- /* Delete hooks to custom chains. */
- "-D INPUT -j bw_INPUT",
- "-D OUTPUT -j bw_OUTPUT",
- "-D FORWARD -j bw_FORWARD",
-
- "-t raw -D bw_raw_PREROUTING",
- "-t mangle -D bw_mangle_POSTROUTING",
-
- "-X bw_INPUT",
- "-X bw_OUTPUT",
- "-X bw_FORWARD",
"-X penalty_box",
"-X costly_shared",
-
- "-t raw -X bw_raw_PREROUTING",
- "-t mangle -X bw_mangle_POSTROUTING",
};
const char *BandwidthController::IPT_SETUP_COMMANDS[] = {
- /* Created needed chains. */
- "-N bw_INPUT",
- "-A INPUT -j bw_INPUT",
-
- "-N bw_OUTPUT",
- "-A OUTPUT -j bw_OUTPUT",
-
- "-N bw_FORWARD",
- "-I FORWARD -j bw_FORWARD",
-
"-N costly_shared",
"-N penalty_box",
-
- "-t raw -N bw_raw_PREROUTING",
- "-t raw -A PREROUTING -j bw_raw_PREROUTING",
- "-t mangle -N bw_mangle_POSTROUTING",
- "-t mangle -A POSTROUTING -j bw_mangle_POSTROUTING",
};
const char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = {
@@ -253,7 +229,6 @@
IPT_SETUP_COMMANDS, RunCmdFailureBad);
return 0;
-
}
int BandwidthController::enableBandwidthControl(bool force) {
diff --git a/BandwidthController.h b/BandwidthController.h
index 10e6ca2..17017d2 100644
--- a/BandwidthController.h
+++ b/BandwidthController.h
@@ -80,6 +80,12 @@
*/
int getTetherStats(TetherStats &stats, std::string &extraProcessingInfo);
+ static const char* LOCAL_INPUT;
+ static const char* LOCAL_FORWARD;
+ static const char* LOCAL_OUTPUT;
+ static const char* LOCAL_RAW_PREROUTING;
+ static const char* LOCAL_MANGLE_POSTROUTING;
+
protected:
class QuotaInfo {
public:
diff --git a/CommandListener.cpp b/CommandListener.cpp
index f562df3..a6d2048 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -40,7 +40,8 @@
#include "IdletimerController.h"
#include "SecondaryTableController.h"
#include "oem_iptables_hook.h"
-
+#include "NetdConstants.h"
+#include "FirewallController.h"
TetherController *CommandListener::sTetherCtrl = NULL;
NatController *CommandListener::sNatCtrl = NULL;
@@ -51,6 +52,76 @@
IdletimerController * CommandListener::sIdletimerCtrl = NULL;
ResolverController *CommandListener::sResolverCtrl = NULL;
SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
+FirewallController *CommandListener::sFirewallCtrl = NULL;
+
+/**
+ * List of module chains to be created, along with explicit ordering. ORDERING
+ * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
+ */
+static const char* FILTER_INPUT[] = {
+ // Bandwidth should always be early in input chain, to make sure we
+ // correctly count incoming traffic against data plan.
+ BandwidthController::LOCAL_INPUT,
+ FirewallController::LOCAL_INPUT,
+ NULL,
+};
+
+static const char* FILTER_FORWARD[] = {
+ OEM_IPTABLES_FILTER_FORWARD,
+ FirewallController::LOCAL_FORWARD,
+ BandwidthController::LOCAL_FORWARD,
+ NatController::LOCAL_FORWARD,
+ NULL,
+};
+
+static const char* FILTER_OUTPUT[] = {
+ OEM_IPTABLES_FILTER_OUTPUT,
+ FirewallController::LOCAL_OUTPUT,
+ BandwidthController::LOCAL_OUTPUT,
+ NULL,
+};
+
+static const char* RAW_PREROUTING[] = {
+ BandwidthController::LOCAL_RAW_PREROUTING,
+ NULL,
+};
+
+static const char* MANGLE_POSTROUTING[] = {
+ BandwidthController::LOCAL_MANGLE_POSTROUTING,
+ NULL,
+};
+
+static const char* NAT_PREROUTING[] = {
+ OEM_IPTABLES_NAT_PREROUTING,
+ IdletimerController::LOCAL_NAT_PREROUTING,
+ NULL,
+};
+
+static const char* NAT_POSTROUTING[] = {
+ IdletimerController::LOCAL_NAT_POSTROUTING,
+ NatController::LOCAL_NAT_POSTROUTING,
+ NULL,
+};
+
+static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
+ const char** childChains) {
+ const char** childChain = childChains;
+ do {
+ // Order is important:
+ // -D to delete any pre-existing jump rule (removes references
+ // that would prevent -X from working)
+ // -F to flush any existing chain
+ // -X to delete any existing chain
+ // -N to create the chain
+ // -A to append the chain to parent
+
+ execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
+ execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
+ execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
+ execIptables(target, "-t", table, "-N", *childChain, NULL);
+ execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
+ } while (*(++childChain) != NULL);
+}
CommandListener::CommandListener() :
FrameworkListener("netd", true) {
@@ -65,6 +136,7 @@
registerCmd(new BandwidthControlCmd());
registerCmd(new IdletimerControlCmd());
registerCmd(new ResolverCmd());
+ registerCmd(new FirewallCmd());
if (!sSecondaryTableCtrl)
sSecondaryTableCtrl = new SecondaryTableController();
@@ -84,16 +156,34 @@
sIdletimerCtrl = new IdletimerController();
if (!sResolverCtrl)
sResolverCtrl = new ResolverController();
+ if (!sFirewallCtrl)
+ sFirewallCtrl = new FirewallController();
/*
- * This is the only time controllers are allowed to touch
- * top-level chains in iptables.
- * Each controller should setup custom chains and hook them into
- * the top-level ones.
- * THE ORDER IS IMPORTANT. TRIPPLE CHECK EACH setup function.
+ * This is the only time we touch top-level chains in iptables; controllers
+ * should only mutate rules inside of their children chains, as created by
+ * the constants above.
+ *
+ * Modules should never ACCEPT packets (except in well-justified cases);
+ * they should instead defer to any remaining modules using RETURN, or
+ * otherwise DROP/REJECT.
*/
- /* Does DROP in nat: PREROUTING, FORWARD, OUTPUT */
+
+ // Create chains for children modules
+ createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
+ createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
+ createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
+ createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
+ createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
+ createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
+ createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
+
+ // Let each module setup their child chains
setupOemIptablesHook();
+
+ /* When enabled, DROPs all packets except those matching rules. */
+ sFirewallCtrl->setupIptablesHooks();
+
/* Does DROPs in FORWARD by default */
sNatCtrl->setupIptablesHooks();
/*
@@ -534,6 +624,12 @@
if (!strcmp(argv[1], "stop")) {
rc = sTetherCtrl->stopTethering();
+ } else if(!strcmp(argv[1], "start-reverse")) {
+ ALOGD("CommandListener::TetherCmd::run, call startReverseTethering, iface:%s", argv[2]);
+ sTetherCtrl->startReverseTethering(argv[2]);
+ } else if (!strcmp(argv[1], "stop-reverse")) {
+ ALOGD("CommandListener::TetherCmd::run, call stopReverseTethering");
+ rc = sTetherCtrl->stopReverseTethering();
} else if (!strcmp(argv[1], "status")) {
char *tmp = NULL;
@@ -1260,3 +1356,110 @@
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
return 0;
}
+
+CommandListener::FirewallCmd::FirewallCmd() :
+ NetdCommand("firewall") {
+}
+
+int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
+ if (!cond) {
+ cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
+ }
+ return 0;
+}
+
+FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
+ if (!strcmp(arg, "allow")) {
+ return ALLOW;
+ } else {
+ return DENY;
+ }
+}
+
+int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
+ char **argv) {
+ if (argc < 2) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "enable")) {
+ int res = sFirewallCtrl->enableFirewall();
+ return sendGenericOkFail(cli, res);
+ }
+ if (!strcmp(argv[1], "disable")) {
+ int res = sFirewallCtrl->disableFirewall();
+ return sendGenericOkFail(cli, res);
+ }
+ if (!strcmp(argv[1], "is_enabled")) {
+ int res = sFirewallCtrl->isFirewallEnabled();
+ return sendGenericOkFail(cli, res);
+ }
+
+ if (!strcmp(argv[1], "set_interface_rule")) {
+ if (argc != 4) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
+ return 0;
+ }
+
+ const char* iface = argv[2];
+ FirewallRule rule = parseRule(argv[3]);
+
+ int res = sFirewallCtrl->setInterfaceRule(iface, rule);
+ return sendGenericOkFail(cli, res);
+ }
+
+ if (!strcmp(argv[1], "set_egress_source_rule")) {
+ if (argc != 4) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
+ false);
+ return 0;
+ }
+
+ const char* addr = argv[2];
+ FirewallRule rule = parseRule(argv[3]);
+
+ int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
+ return sendGenericOkFail(cli, res);
+ }
+
+ if (!strcmp(argv[1], "set_egress_dest_rule")) {
+ if (argc != 5) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
+ false);
+ return 0;
+ }
+
+ const char* addr = argv[2];
+ int port = atoi(argv[3]);
+ FirewallRule rule = parseRule(argv[4]);
+
+ int res = 0;
+ res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
+ res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
+ return sendGenericOkFail(cli, res);
+ }
+
+ if (!strcmp(argv[1], "set_uid_rule")) {
+ if (argc != 4) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Usage: firewall set_uid_rule <1000> <allow|deny>",
+ false);
+ return 0;
+ }
+
+ int uid = atoi(argv[2]);
+ FirewallRule rule = parseRule(argv[3]);
+
+ int res = sFirewallCtrl->setUidRule(uid, rule);
+ return sendGenericOkFail(cli, res);
+ }
+
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
+ return 0;
+}
diff --git a/CommandListener.h b/CommandListener.h
index a9da6d7..e52b440 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -29,6 +29,7 @@
#include "IdletimerController.h"
#include "ResolverController.h"
#include "SecondaryTableController.h"
+#include "FirewallController.h"
class CommandListener : public FrameworkListener {
static TetherController *sTetherCtrl;
@@ -40,6 +41,7 @@
static IdletimerController *sIdletimerCtrl;
static ResolverController *sResolverCtrl;
static SecondaryTableController *sSecondaryTableCtrl;
+ static FirewallController *sFirewallCtrl;
public:
CommandListener();
@@ -131,6 +133,16 @@
virtual ~ResolverCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
+
+ class FirewallCmd: public NetdCommand {
+ public:
+ FirewallCmd();
+ virtual ~FirewallCmd() {}
+ int runCommand(SocketClient *c, int argc, char ** argv);
+ protected:
+ int sendGenericOkFail(SocketClient *cli, int cond);
+ static FirewallRule parseRule(const char* arg);
+ };
};
#endif
diff --git a/FirewallController.cpp b/FirewallController.cpp
new file mode 100644
index 0000000..0746316
--- /dev/null
+++ b/FirewallController.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define LOG_TAG "FirewallController"
+#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+
+#include "NetdConstants.h"
+#include "FirewallController.h"
+
+const char* FirewallController::LOCAL_INPUT = "fw_INPUT";
+const char* FirewallController::LOCAL_OUTPUT = "fw_OUTPUT";
+const char* FirewallController::LOCAL_FORWARD = "fw_FORWARD";
+
+FirewallController::FirewallController(void) {
+}
+
+int FirewallController::setupIptablesHooks(void) {
+ return 0;
+}
+
+int FirewallController::enableFirewall(void) {
+ int res = 0;
+
+ // flush any existing rules
+ disableFirewall();
+
+ // create default rule to drop all traffic
+ res |= execIptables(V4V6, "-A", LOCAL_INPUT, "-j", "DROP", NULL);
+ res |= execIptables(V4V6, "-A", LOCAL_OUTPUT, "-j", "REJECT", NULL);
+ res |= execIptables(V4V6, "-A", LOCAL_FORWARD, "-j", "REJECT", NULL);
+
+ return res;
+}
+
+int FirewallController::disableFirewall(void) {
+ int res = 0;
+
+ // flush any existing rules
+ res |= execIptables(V4V6, "-F", LOCAL_INPUT, NULL);
+ res |= execIptables(V4V6, "-F", LOCAL_OUTPUT, NULL);
+ res |= execIptables(V4V6, "-F", LOCAL_FORWARD, NULL);
+
+ return res;
+}
+
+int FirewallController::isFirewallEnabled(void) {
+ // TODO: verify that rules are still in place near top
+ return -1;
+}
+
+int FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) {
+ const char* op;
+ if (rule == ALLOW) {
+ op = "-I";
+ } else {
+ op = "-D";
+ }
+
+ int res = 0;
+ res |= execIptables(V4V6, op, LOCAL_INPUT, "-i", iface, "-j", "RETURN", NULL);
+ res |= execIptables(V4V6, op, LOCAL_OUTPUT, "-o", iface, "-j", "RETURN", NULL);
+ return res;
+}
+
+int FirewallController::setEgressSourceRule(const char* addr, FirewallRule rule) {
+ IptablesTarget target = V4;
+ if (strchr(addr, ':')) {
+ target = V6;
+ }
+
+ const char* op;
+ if (rule == ALLOW) {
+ op = "-I";
+ } else {
+ op = "-D";
+ }
+
+ int res = 0;
+ res |= execIptables(target, op, LOCAL_INPUT, "-d", addr, "-j", "RETURN", NULL);
+ res |= execIptables(target, op, LOCAL_OUTPUT, "-s", addr, "-j", "RETURN", NULL);
+ return res;
+}
+
+int FirewallController::setEgressDestRule(const char* addr, int protocol, int port,
+ FirewallRule rule) {
+ IptablesTarget target = V4;
+ if (strchr(addr, ':')) {
+ target = V6;
+ }
+
+ char protocolStr[16];
+ sprintf(protocolStr, "%d", protocol);
+
+ char portStr[16];
+ sprintf(portStr, "%d", port);
+
+ const char* op;
+ if (rule == ALLOW) {
+ op = "-I";
+ } else {
+ op = "-D";
+ }
+
+ int res = 0;
+ res |= execIptables(target, op, LOCAL_INPUT, "-s", addr, "-p", protocolStr,
+ "--sport", portStr, "-j", "RETURN", NULL);
+ res |= execIptables(target, op, LOCAL_OUTPUT, "-d", addr, "-p", protocolStr,
+ "--dport", portStr, "-j", "RETURN", NULL);
+ return res;
+}
+
+int FirewallController::setUidRule(int uid, FirewallRule rule) {
+ char uidStr[16];
+ sprintf(uidStr, "%d", uid);
+
+ const char* op;
+ if (rule == ALLOW) {
+ op = "-I";
+ } else {
+ op = "-D";
+ }
+
+ int res = 0;
+ res |= execIptables(V4V6, op, LOCAL_INPUT, "-m", "owner", "--uid-owner", uidStr,
+ "-j", "RETURN", NULL);
+ res |= execIptables(V4V6, op, LOCAL_OUTPUT, "-m", "owner", "--uid-owner", uidStr,
+ "-j", "RETURN", NULL);
+ return res;
+}
diff --git a/FirewallController.h b/FirewallController.h
new file mode 100644
index 0000000..158e0fa
--- /dev/null
+++ b/FirewallController.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#ifndef _FIREWALL_CONTROLLER_H
+#define _FIREWALL_CONTROLLER_H
+
+#include <string>
+
+enum FirewallRule { ALLOW, DENY };
+
+#define PROTOCOL_TCP 6
+#define PROTOCOL_UDP 17
+
+/*
+ * Simple firewall that drops all packets except those matching explicitly
+ * defined ALLOW rules.
+ */
+class FirewallController {
+public:
+ FirewallController();
+
+ int setupIptablesHooks(void);
+
+ int enableFirewall(void);
+ int disableFirewall(void);
+ int isFirewallEnabled(void);
+
+ /* Match traffic going in/out over the given iface. */
+ int setInterfaceRule(const char*, FirewallRule);
+ /* Match traffic coming-in-to or going-out-from given address. */
+ int setEgressSourceRule(const char*, FirewallRule);
+ /* Match traffic coming-in-from or going-out-to given address, port, and protocol. */
+ int setEgressDestRule(const char*, int, int, FirewallRule);
+ /* Match traffic owned by given UID. */
+ int setUidRule(int, FirewallRule);
+
+ static const char* LOCAL_INPUT;
+ static const char* LOCAL_OUTPUT;
+ static const char* LOCAL_FORWARD;
+
+};
+
+#endif
diff --git a/IdletimerController.cpp b/IdletimerController.cpp
index 2bcb9b7..8e6a67f 100644
--- a/IdletimerController.cpp
+++ b/IdletimerController.cpp
@@ -90,6 +90,9 @@
extern "C" int system_nosh(const char *command);
+const char* IdletimerController::LOCAL_NAT_PREROUTING = "idletimer_nat_PREROUTING";
+const char* IdletimerController::LOCAL_NAT_POSTROUTING = "idletimer_nat_POSTROUTING";
+
IdletimerController::IdletimerController() {
}
@@ -115,18 +118,6 @@
}
bool IdletimerController::setupIptablesHooks() {
- runIpxtablesCmd("-t nat -D PREROUTING -j idletimer_nat_PREROUTING");
- runIpxtablesCmd("-t nat -F idletimer_nat_PREROUTING");
- runIpxtablesCmd("-t nat -N idletimer_nat_PREROUTING");
-
- runIpxtablesCmd("-t nat -D POSTROUTING -j idletimer_nat_POSTROUTING");
- runIpxtablesCmd("-t nat -F idletimer_nat_POSTROUTING");
- runIpxtablesCmd("-t nat -N idletimer_nat_POSTROUTING");
-
- if (runIpxtablesCmd("-t nat -I PREROUTING -j idletimer_nat_PREROUTING")
- || runIpxtablesCmd("-t nat -I POSTROUTING -j idletimer_nat_POSTROUTING")) {
- return false;
- }
return true;
}
diff --git a/IdletimerController.h b/IdletimerController.h
index 6167b48..2af0d9b 100644
--- a/IdletimerController.h
+++ b/IdletimerController.h
@@ -30,6 +30,9 @@
const char *classLabel);
bool setupIptablesHooks();
+ static const char* LOCAL_NAT_PREROUTING;
+ static const char* LOCAL_NAT_POSTROUTING;
+
private:
enum IptOp { IptOpAdd, IptOpDelete };
int setDefaults();
diff --git a/NatController.cpp b/NatController.cpp
index 77c4874..e44a29b 100644
--- a/NatController.cpp
+++ b/NatController.cpp
@@ -35,6 +35,9 @@
extern "C" int system_nosh(const char *command);
+const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
+const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
+
NatController::NatController(SecondaryTableController *ctrl) {
secondaryTableCtrl = ctrl;
}
@@ -61,30 +64,6 @@
}
int NatController::setupIptablesHooks() {
- if (runCmd(IPTABLES_PATH, "-P INPUT ACCEPT"))
- return -1;
- if (runCmd(IPTABLES_PATH, "-P OUTPUT ACCEPT"))
- return -1;
- if (runCmd(IPTABLES_PATH, "-P FORWARD ACCEPT"))
- return -1;
-
- // Order is important!
- // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist)
- // -F to flush the chain (no-op if doesn't exist).
- // -N to create the chain (no-op if already exist).
-
- runCmd(IPTABLES_PATH, "-D FORWARD -j natctrl_FORWARD");
- runCmd(IPTABLES_PATH, "-F natctrl_FORWARD");
- runCmd(IPTABLES_PATH, "-N natctrl_FORWARD");
- if (runCmd(IPTABLES_PATH, "-A FORWARD -j natctrl_FORWARD"))
- return -1;
-
- runCmd(IPTABLES_PATH, "-t nat -D POSTROUTING -j natctrl_nat_POSTROUTING");
- runCmd(IPTABLES_PATH, "-t nat -F natctrl_nat_POSTROUTING");
- runCmd(IPTABLES_PATH, "-t nat -N natctrl_nat_POSTROUTING");
- if (runCmd(IPTABLES_PATH, "-t nat -A POSTROUTING -j natctrl_nat_POSTROUTING"))
- return -1;
-
setDefaults();
return 0;
}
diff --git a/NatController.h b/NatController.h
index 1d328e5..c1979bb 100644
--- a/NatController.h
+++ b/NatController.h
@@ -31,6 +31,9 @@
int disableNat(const int argc, char **argv);
int setupIptablesHooks();
+ static const char* LOCAL_FORWARD;
+ static const char* LOCAL_NAT_POSTROUTING;
+
private:
int natCount;
SecondaryTableController *secondaryTableCtrl;
diff --git a/NetdConstants.cpp b/NetdConstants.cpp
index e57b483..ca869a3 100644
--- a/NetdConstants.cpp
+++ b/NetdConstants.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#include <string.h>
+
+#include <cutils/log.h>
+
#include "NetdConstants.h"
const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh";
@@ -23,3 +27,71 @@
const char * const IP_PATH = "/system/bin/ip";
const char * const ADD = "add";
const char * const DEL = "del";
+
+static void logExecError(const char* argv[], int res) {
+ const char** argp = argv;
+ std::string args = "";
+ while (*argp) {
+ args += *argp;
+ args += ' ';
+ argp++;
+ }
+ ALOGE("exec() res=%d for %s", res, args.c_str());
+}
+
+static int execIptables(IptablesTarget target, bool silent, va_list args) {
+ /* Read arguments from incoming va_list; we expect the list to be NULL terminated. */
+ std::list<const char*> argsList;
+ argsList.push_back(NULL);
+ const char* arg;
+ do {
+ arg = va_arg(args, const char *);
+ argsList.push_back(arg);
+ } while (arg);
+
+ int i = 0;
+ const char* argv[argsList.size()];
+ std::list<const char*>::iterator it;
+ for (it = argsList.begin(); it != argsList.end(); it++, i++) {
+ argv[i] = *it;
+ }
+
+ int res = 0;
+ if (target == V4 || target == V4V6) {
+ argv[0] = IPTABLES_PATH;
+ int localRes = fork_and_execve(argv[0], argv);
+ if (localRes) {
+ if (!silent) {
+ logExecError(argv, localRes);
+ }
+ res |= localRes;
+ }
+ }
+ if (target == V6 || target == V4V6) {
+ argv[0] = IP6TABLES_PATH;
+ int localRes = fork_and_execve(argv[0], argv);
+ if (localRes) {
+ if (!silent) {
+ logExecError(argv, localRes);
+ }
+ res |= localRes;
+ }
+ }
+ return res;
+}
+
+int execIptables(IptablesTarget target, ...) {
+ va_list args;
+ va_start(args, target);
+ int res = execIptables(target, false, args);
+ va_end(args);
+ return res;
+}
+
+int execIptablesSilently(IptablesTarget target, ...) {
+ va_list args;
+ va_start(args, target);
+ int res = execIptables(target, true, args);
+ va_end(args);
+ return res;
+}
diff --git a/NetdConstants.h b/NetdConstants.h
index 9943a05..8468f9b 100644
--- a/NetdConstants.h
+++ b/NetdConstants.h
@@ -17,6 +17,9 @@
#ifndef _NETD_CONSTANTS_H
#define _NETD_CONSTANTS_H
+#include <string>
+#include <list>
+#include <stdarg.h>
extern const char * const IPTABLES_PATH;
extern const char * const IP6TABLES_PATH;
@@ -26,4 +29,11 @@
extern const char * const ADD;
extern const char * const DEL;
+extern "C" int fork_and_execve(const char*, const char*[]);
+
+enum IptablesTarget { V4, V6, V4V6 };
+
+int execIptables(IptablesTarget target, ...);
+int execIptablesSilently(IptablesTarget target, ...);
+
#endif
diff --git a/TetherController.cpp b/TetherController.cpp
index 8d14a14..2c48074 100644
--- a/TetherController.cpp
+++ b/TetherController.cpp
@@ -38,6 +38,7 @@
mDnsForwarders = new NetAddressCollection();
mDaemonFd = -1;
mDaemonPid = 0;
+ mDhcpcdPid = 0;
}
TetherController::~TetherController() {
@@ -187,6 +188,75 @@
return 0;
}
+// TODO(BT) remove
+int TetherController::startReverseTethering(const char* iface) {
+ if (mDhcpcdPid != 0) {
+ ALOGE("Reverse tethering already started");
+ errno = EBUSY;
+ return -1;
+ }
+
+ ALOGD("TetherController::startReverseTethering, Starting reverse tethering");
+
+ /*
+ * TODO: Create a monitoring thread to handle and restart
+ * the daemon if it exits prematurely
+ */
+ //cleanup the dhcp result
+ char dhcp_result_name[64];
+ snprintf(dhcp_result_name, sizeof(dhcp_result_name) - 1, "dhcp.%s.result", iface);
+ property_set(dhcp_result_name, "");
+
+ pid_t pid;
+ if ((pid = fork()) < 0) {
+ ALOGE("fork failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ if (!pid) {
+
+ char *args[10];
+ int argc = 0;
+ args[argc++] = "/system/bin/dhcpcd";
+ char host_name[128];
+ if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
+ {
+ args[argc++] = "-h";
+ args[argc++] = host_name;
+ }
+ args[argc++] = (char*)iface;
+ args[argc] = NULL;
+ if (execv(args[0], args)) {
+ ALOGE("startReverseTethering, execv failed (%s)", strerror(errno));
+ }
+ ALOGE("startReverseTethering, Should never get here!");
+ // TODO(BT) inform parent of the failure.
+ // Parent process need wait for child to report error status
+ // before it set mDhcpcdPid and return 0.
+ exit(-1);
+ } else {
+ mDhcpcdPid = pid;
+ ALOGD("Reverse Tethering running, pid:%d", pid);
+ }
+ return 0;
+}
+
+// TODO(BT) remove
+int TetherController::stopReverseTethering() {
+
+ if (mDhcpcdPid == 0) {
+ ALOGE("Tethering already stopped");
+ return 0;
+ }
+
+ ALOGD("Stopping tethering services");
+
+ kill(mDhcpcdPid, SIGTERM);
+ waitpid(mDhcpcdPid, NULL, 0);
+ mDhcpcdPid = 0;
+ ALOGD("Tethering services stopped");
+ return 0;
+}
bool TetherController::isTetheringStarted() {
return (mDaemonPid == 0 ? false : true);
}
diff --git a/TetherController.h b/TetherController.h
index eef94fe..463774b 100644
--- a/TetherController.h
+++ b/TetherController.h
@@ -28,6 +28,7 @@
InterfaceCollection *mInterfaces;
NetAddressCollection *mDnsForwarders;
pid_t mDaemonPid;
+ pid_t mDhcpcdPid;
int mDaemonFd;
public:
@@ -42,6 +43,9 @@
int stopTethering();
bool isTetheringStarted();
+ int startReverseTethering(const char* iface);
+ int stopReverseTethering();
+
int setDnsForwarders(char **servers, int numServers);
NetAddressCollection *getDnsForwarders();
diff --git a/logwrapper.c b/logwrapper.c
index f5f4548..e84ae89 100644
--- a/logwrapper.c
+++ b/logwrapper.c
@@ -160,17 +160,14 @@
return 0;
}
+int fork_and_execve(const char*, char*[]);
+
/*
* The following is based off of bionic/libc/unistd/system.c with
* modifications to avoid calling /system/bin/sh -c
*/
-extern char **environ;
int system_nosh(const char *command)
{
- pid_t pid;
- sig_t intsave, quitsave;
- sigset_t mask, omask;
- int pstat;
char buffer[255];
char *argp[32];
char *next = buffer;
@@ -200,6 +197,15 @@
}
argp[i] = NULL;
+ return fork_and_execve(argp[0], argp);
+}
+
+extern char **environ;
+int fork_and_execve(const char* filename, char* argv[]) {
+ pid_t pid;
+ sig_t intsave, quitsave;
+ sigset_t mask, omask;
+ int pstat;
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
@@ -210,7 +216,7 @@
return(-1);
case 0: /* child */
sigprocmask(SIG_SETMASK, &omask, NULL);
- execve(argp[0], argp, environ);
+ execve(filename, argv, environ);
_exit(127);
}
diff --git a/oem_iptables_hook.cpp b/oem_iptables_hook.cpp
index d3026a9..fbf14f8 100644
--- a/oem_iptables_hook.cpp
+++ b/oem_iptables_hook.cpp
@@ -45,48 +45,10 @@
return res;
}
-static bool oemSetupHooks() {
- // Order is important!
- // -N to create the chain (no-op if already exist).
- // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist)
- // -I to insert our jump rule into the default chain
-
- runIptablesCmd("-N oem_out");
- runIptablesCmd("-D OUTPUT -j oem_out");
- if (runIptablesCmd("-I OUTPUT -j oem_out"))
- return false;
-
- runIptablesCmd("-N oem_fwd");
- runIptablesCmd("-D FORWARD -j oem_fwd");
- if (runIptablesCmd("-I FORWARD -j oem_fwd"))
- return false;
-
- runIptablesCmd("-t nat -N oem_nat_pre");
- runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre");
- if (runIptablesCmd("-t nat -I PREROUTING -j oem_nat_pre"))
- return false;
-
- return true;
-}
-
static bool oemCleanupHooks() {
- // Order is important!
- // -D to remove ref to the chain
- // -F to empty the chain
- // -X to delete the chain
-
- runIptablesCmd("-D OUTPUT -j oem_out");
runIptablesCmd("-F oem_out");
- runIptablesCmd("-X oem_out");
-
- runIptablesCmd("-D FORWARD -j oem_fwd");
runIptablesCmd("-F oem_fwd");
- runIptablesCmd("-X oem_fwd");
-
- runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre");
runIptablesCmd("-t nat -F oem_nat_pre");
- runIptablesCmd("-t nat -X oem_nat_pre");
-
return true;
}
@@ -106,7 +68,7 @@
// The call to oemCleanupHooks() is superfluous when done on bootup,
// but is needed for the case where netd has crashed/stopped and is
// restarted.
- if (oemCleanupHooks() && oemSetupHooks() && oemInitChains()) {
+ if (oemCleanupHooks() && oemInitChains()) {
ALOGI("OEM iptable hook installed.");
}
}
diff --git a/oem_iptables_hook.h b/oem_iptables_hook.h
index f5696ba..bc99638 100644
--- a/oem_iptables_hook.h
+++ b/oem_iptables_hook.h
@@ -17,6 +17,10 @@
#ifndef _OEM_IPTABLES_HOOK_H
#define _OEM_IPTABLES_HOOK_H
+#define OEM_IPTABLES_FILTER_OUTPUT "oem_out"
+#define OEM_IPTABLES_FILTER_FORWARD "oem_fwd"
+#define OEM_IPTABLES_NAT_PREROUTING "oem_nat_pre"
+
void setupOemIptablesHook();
#endif