am 484bdcab: am 63790dce: am 42b4c508: (-s ours) am 11ff695d: (-s ours) Reconcile with jb-mr1-release - do not merge
* commit '484bdcab1e7e64c2ad6ee36b9d216dbc94e82608':
diff --git a/Android.mk b/Android.mk
index e4b6ad6..3a3651d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,9 +21,7 @@
SecondaryTableController.cpp \
SoftapController.cpp \
TetherController.cpp \
- ThrottleController.cpp \
oem_iptables_hook.cpp \
- logwrapper.c \
main.cpp \
@@ -40,7 +38,8 @@
LOCAL_CFLAGS := -Werror=format
LOCAL_SHARED_LIBRARIES := libstlport libsysutils libcutils libnetutils \
- libcrypto libhardware_legacy libmdnssd libdl
+ libcrypto libhardware_legacy libmdnssd libdl \
+ liblogwrap
include $(BUILD_EXECUTABLE)
diff --git a/BandwidthController.cpp b/BandwidthController.cpp
index e5d3054..d51ea25 100644
--- a/BandwidthController.cpp
+++ b/BandwidthController.cpp
@@ -40,16 +40,13 @@
#define LOG_TAG "BandwidthController"
#include <cutils/log.h>
#include <cutils/properties.h>
-
-extern "C" int logwrap(int argc, const char **argv);
-extern "C" int system_nosh(const char *command);
+#include <logwrap/logwrap.h>
#include "NetdConstants.h"
#include "BandwidthController.h"
/* Alphabetical */
-#define ALERT_IPT_TEMPLATE "%s %s %s -m quota2 ! --quota %lld --name %s"
-const int BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4;
+#define ALERT_IPT_TEMPLATE "%s %s -m quota2 ! --quota %lld --name %s"
const char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert";
const char* BandwidthController::LOCAL_INPUT = "bw_INPUT";
const char* BandwidthController::LOCAL_FORWARD = "bw_FORWARD";
@@ -61,8 +58,6 @@
const int BandwidthController::MAX_IFACENAME_LEN = 64;
const int BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256;
-bool BandwidthController::useLogwrapCall = false;
-
/**
* Some comments about the rules:
* * Ordering
@@ -128,23 +123,17 @@
};
const char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = {
- "-A bw_INPUT -i lo --jump RETURN",
"-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */
- "-A bw_OUTPUT -o lo --jump RETURN",
"-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */
"-A costly_shared --jump penalty_box",
- "-t raw -A bw_raw_PREROUTING ! -i lo+ -m owner --socket-exists", /* This is a tracking rule. */
- "-t mangle -A bw_mangle_POSTROUTING ! -o lo+ -m owner --socket-exists", /* This is a tracking rule. */
+ "-t raw -A bw_raw_PREROUTING -m owner --socket-exists", /* This is a tracking rule. */
+ "-t mangle -A bw_mangle_POSTROUTING -m owner --socket-exists", /* This is a tracking rule. */
};
BandwidthController::BandwidthController(void) {
- char value[PROPERTY_VALUE_MAX];
-
- property_get("persist.bandwidth.uselogwrap", value, "0");
- useLogwrapCall = !strcmp(value, "1");
}
int BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling,
@@ -172,6 +161,7 @@
char *next = buffer;
char *tmp;
int res;
+ int status = 0;
std::string fullCmd = cmd;
@@ -190,28 +180,27 @@
fullCmd.insert(0, " ");
fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH);
- if (!useLogwrapCall) {
- res = system_nosh(fullCmd.c_str());
- } else {
- if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
- ALOGE("iptables command too long");
+ if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
+ ALOGE("iptables command too long");
+ return -1;
+ }
+
+ argc = 0;
+ while ((tmp = strsep(&next, " "))) {
+ argv[argc++] = tmp;
+ if (argc >= MAX_CMD_ARGS) {
+ ALOGE("iptables argument overflow");
return -1;
}
-
- argc = 0;
- while ((tmp = strsep(&next, " "))) {
- argv[argc++] = tmp;
- if (argc >= MAX_CMD_ARGS) {
- ALOGE("iptables argument overflow");
- return -1;
- }
- }
-
- argv[argc] = NULL;
- res = logwrap(argc, argv);
}
+
+ argv[argc] = NULL;
+ res = android_fork_execvp(argc, (char **)argv, &status, false,
+ failureHandling == IptFailShow);
+ res = res || !WIFEXITED(status) || WEXITSTATUS(status);
if (res && failureHandling == IptFailShow) {
- ALOGE("runIptablesCmd(): failed %s res=%d", fullCmd.c_str(), res);
+ ALOGE("runIptablesCmd(): res=%d status=%d failed %s", res, status,
+ fullCmd.c_str());
}
return res;
}
@@ -290,6 +279,9 @@
case IptOpInsert:
opFlag = "-I";
break;
+ case IptOpAppend:
+ opFlag = "-A";
+ break;
case IptOpReplace:
opFlag = "-R";
break;
@@ -392,6 +384,9 @@
case IptOpInsert:
opFlag = "-I";
break;
+ case IptOpAppend:
+ opFlag = "-A";
+ break;
case IptOpReplace:
opFlag = "-R";
break;
@@ -635,8 +630,14 @@
}
if (it == quotaIfaces.end()) {
+ /* Preparing the iface adds a penalty_box check */
res |= prepCostlyIface(ifn, QuotaUnique);
- quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
+ /*
+ * The rejecting quota limit should go after the penalty box checks
+ * or else a naughty app could just eat up the quota.
+ * So we append here.
+ */
+ quotaCmd = makeIptablesQuotaCmd(IptOpAppend, costName, maxBytes);
res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
if (res) {
ALOGE("Failed set quota rule");
@@ -740,13 +741,15 @@
int BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) {
int res = 0;
const char *opFlag;
- const char *ifaceLimiting;
char *alertQuotaCmd;
switch (op) {
case IptOpInsert:
opFlag = "-I";
break;
+ case IptOpAppend:
+ opFlag = "-A";
+ break;
case IptOpReplace:
opFlag = "-R";
break;
@@ -756,13 +759,11 @@
break;
}
- ifaceLimiting = "! -i lo+";
- asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_INPUT",
+ asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_INPUT",
bytes, alertName);
res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
free(alertQuotaCmd);
- ifaceLimiting = "! -o lo+";
- asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_OUTPUT",
+ asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_OUTPUT",
bytes, alertName);
res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
free(alertQuotaCmd);
@@ -772,13 +773,15 @@
int BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) {
int res = 0;
const char *opFlag;
- const char *ifaceLimiting;
char *alertQuotaCmd;
switch (op) {
case IptOpInsert:
opFlag = "-I";
break;
+ case IptOpAppend:
+ opFlag = "-A";
+ break;
case IptOpReplace:
opFlag = "-R";
break;
@@ -788,8 +791,7 @@
break;
}
- ifaceLimiting = "! -i lo+";
- asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_FORWARD",
+ asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_FORWARD",
bytes, alertName);
res = runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
free(alertQuotaCmd);
@@ -933,7 +935,7 @@
int BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) {
char *alertQuotaCmd;
- char *chainNameAndPos;
+ char *chainName;
int res = 0;
char *alertName;
@@ -945,11 +947,11 @@
if (*alertBytes) {
res = updateQuota(alertName, *alertBytes);
} else {
- asprintf(&chainNameAndPos, "costly_%s %d", costName, ALERT_RULE_POS_IN_COSTLY_CHAIN);
- asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-I", chainNameAndPos, bytes, alertName);
+ asprintf(&chainName, "costly_%s", costName);
+ asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-A", chainName, bytes, alertName);
res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
free(alertQuotaCmd);
- free(chainNameAndPos);
+ free(chainName);
}
*alertBytes = bytes;
free(alertName);
@@ -969,7 +971,7 @@
}
asprintf(&chainName, "costly_%s", costName);
- asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-D", chainName, *alertBytes, alertName);
+ asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-D", chainName, *alertBytes, alertName);
res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
free(alertQuotaCmd);
free(chainName);
diff --git a/BandwidthController.h b/BandwidthController.h
index 17017d2..b4a2c20 100644
--- a/BandwidthController.h
+++ b/BandwidthController.h
@@ -97,7 +97,7 @@
};
enum IptIpVer { IptIpV4, IptIpV6 };
- enum IptOp { IptOpInsert, IptOpReplace, IptOpDelete };
+ enum IptOp { IptOpInsert, IptOpReplace, IptOpDelete, IptOpAppend };
enum IptRejectOp { IptRejectAdd, IptRejectNoAdd };
enum NaughtyAppOp { NaughtyAppOpAdd, NaughtyAppOpRemove };
enum QuotaType { QuotaUnique, QuotaShared };
@@ -169,17 +169,11 @@
static const char *IPT_BASIC_ACCOUNTING_COMMANDS[];
/* Alphabetical */
- static const int ALERT_RULE_POS_IN_COSTLY_CHAIN;
static const char ALERT_GLOBAL_NAME[];
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
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 6f81524..31ae129 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -24,7 +24,6 @@
#include <dirent.h>
#include <errno.h>
#include <string.h>
-#include <fcntl.h>
#include <linux/if.h>
#define LOG_TAG "CommandListener"
@@ -35,7 +34,6 @@
#include "CommandListener.h"
#include "ResponseCode.h"
-#include "ThrottleController.h"
#include "BandwidthController.h"
#include "IdletimerController.h"
#include "SecondaryTableController.h"
@@ -207,22 +205,6 @@
NetdCommand("interface") {
}
-int CommandListener::writeFile(const char *path, const char *value, int size) {
- int fd = open(path, O_WRONLY);
- if (fd < 0) {
- ALOGE("Failed to open %s: %s", path, strerror(errno));
- return -1;
- }
-
- if (write(fd, value, size) != size) {
- ALOGE("Failed to write %s: %s", path, strerror(errno));
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
-}
-
int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
if (argc < 2) {
@@ -247,79 +229,6 @@
closedir(d);
cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
return 0;
- } else if (!strcmp(argv[1], "readrxcounter")) {
- if (argc != 3) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface readrxcounter <interface>", false);
- return 0;
- }
- unsigned long rx = 0, tx = 0;
- if (readInterfaceCounters(argv[2], &rx, &tx)) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
- return 0;
- }
-
- char *msg;
- asprintf(&msg, "%lu", rx);
- cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
- free(msg);
-
- return 0;
- } else if (!strcmp(argv[1], "readtxcounter")) {
- if (argc != 3) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface readtxcounter <interface>", false);
- return 0;
- }
- unsigned long rx = 0, tx = 0;
- if (readInterfaceCounters(argv[2], &rx, &tx)) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
- return 0;
- }
-
- char *msg = NULL;
- asprintf(&msg, "%lu", tx);
- cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
- free(msg);
- return 0;
- } else if (!strcmp(argv[1], "getthrottle")) {
- if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface getthrottle <interface> <rx|tx>", false);
- return 0;
- }
- int val = 0;
- int rc = 0;
- int voldRc = ResponseCode::InterfaceRxThrottleResult;
-
- if (!strcmp(argv[3], "rx")) {
- rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
- } else {
- rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
- voldRc = ResponseCode::InterfaceTxThrottleResult;
- }
- if (rc) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
- } else {
- char *msg = NULL;
- asprintf(&msg, "%u", val);
- cli->sendMsg(voldRc, msg, false);
- free(msg);
- return 0;
- }
- return 0;
- } else if (!strcmp(argv[1], "setthrottle")) {
- if (argc != 5) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
- return 0;
- }
- if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
- } else {
- cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
- }
- return 0;
} else if (!strcmp(argv[1], "driver")) {
int rc;
char *rbuf;
@@ -529,19 +438,13 @@
false);
return 0;
}
-
- char *tmp;
- asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]);
-
- if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) {
- free(tmp);
+ int enable = !strncmp(argv[3], "enable", 7);
+ if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
+ cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
+ } else {
cli->sendMsg(ResponseCode::OperationFailed,
"Failed to set ipv6 privacy extensions", true);
- return 0;
}
-
- free(tmp);
- cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
return 0;
} else if (!strcmp(argv[1], "ipv6")) {
if (argc != 4) {
@@ -551,18 +454,13 @@
return 0;
}
- char *tmp;
- asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]);
-
- if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) {
- free(tmp);
+ int enable = !strncmp(argv[3], "enable", 7);
+ if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
+ cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
+ } else {
cli->sendMsg(ResponseCode::OperationFailed,
"Failed to change IPv6 state", true);
- return 0;
}
-
- free(tmp);
- cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
return 0;
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
@@ -827,11 +725,17 @@
int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
- int rc = 0, flag = 0;
+ int rc = ResponseCode::SoftapStatusResult;
+ int flag = 0;
char *retbuf = NULL;
+ if (sSoftapCtrl == NULL) {
+ cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
+ return -1;
+ }
if (argc < 2) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Missing argument in a SoftAP command", false);
return 0;
}
@@ -841,31 +745,23 @@
rc = sSoftapCtrl->stopSoftap();
} else if (!strcmp(argv[1], "fwreload")) {
rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
- } else if (!strcmp(argv[1], "clients")) {
- rc = sSoftapCtrl->clientsSoftap(&retbuf);
- if (!rc) {
- cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
- free(retbuf);
- return 0;
- }
} else if (!strcmp(argv[1], "status")) {
- asprintf(&retbuf, "Softap service %s",
- (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
- cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
+ asprintf(&retbuf, "Softap service %s running",
+ (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
+ cli->sendMsg(rc, retbuf, false);
free(retbuf);
return 0;
} else if (!strcmp(argv[1], "set")) {
rc = sSoftapCtrl->setSoftap(argc, argv);
} else {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
return 0;
}
- if (!rc) {
- cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
- } else {
- cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
- }
+ if (rc >= 400 && rc < 600)
+ cli->sendMsg(rc, "SoftAP command has failed", false);
+ else
+ cli->sendMsg(rc, "Ok", false);
return 0;
}
@@ -891,9 +787,10 @@
"Wrong number of arguments to resolver setdefaultif", false);
return 0;
}
- } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..."
- if (argc >= 4) {
- rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3);
+ } else if (!strcmp(argv[1], "setifdns")) {
+ // "resolver setifdns <iface> <domains> <dns1> <dns2> ..."
+ if (argc >= 5) {
+ rc = sResolverCtrl->setInterfaceDnsServers(argv[2], argv[3], &argv[4], argc - 4);
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Wrong number of arguments to resolver setifdns", false);
@@ -925,6 +822,22 @@
"Wrong number of arguments to resolver setdefaultif", false);
return 0;
}
+ } else if (!strcmp(argv[1], "setifaceforpid")) { // resolver setifaceforpid <iface> <pid>
+ if (argc == 4) {
+ rc = sResolverCtrl->setDnsInterfaceForPid(argv[2], atoi(argv[3]));
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Wrong number of arguments to resolver setifaceforpid", false);
+ return 0;
+ }
+ } else if (!strcmp(argv[1], "clearifaceforpid")) { // resolver clearifaceforpid <pid>
+ if (argc == 3) {
+ rc = sResolverCtrl->clearDnsInterfaceForPid(atoi(argv[2]));
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Wrong number of arguments to resolver clearifaceforpid", false);
+ return 0;
+ }
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
return 0;
@@ -939,47 +852,6 @@
return 0;
}
-int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
- FILE *fp = fopen("/proc/net/dev", "r");
- if (!fp) {
- ALOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
- return -1;
- }
-
- char buffer[512];
-
- fgets(buffer, sizeof(buffer), fp); // Header 1
- fgets(buffer, sizeof(buffer), fp); // Header 2
- while(fgets(buffer, sizeof(buffer), fp)) {
- buffer[strlen(buffer)-1] = '\0';
-
- char name[31];
- unsigned long d;
- sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu",
- name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
- char *rxString = strchr(name, ':');
- *rxString = '\0';
- rxString++;
- // when the rx count gets too big it changes from "name: 999" to "name:1000"
- // and the sscanf munge the two together. Detect that and fix
- // note that all the %lu will be off by one and the real tx value will be in d
- if (*rxString != '\0') {
- *tx = d;
- sscanf(rxString, "%20lu", rx);
- }
- if (strcmp(name, iface)) {
- continue;
- }
- fclose(fp);
- return 0;
- }
-
- fclose(fp);
- *rx = 0;
- *tx = 0;
- return 0;
-}
-
CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
NetdCommand("bandwidth") {
}
diff --git a/CommandListener.h b/CommandListener.h
index e8d92a8..1db81f8 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -51,10 +51,6 @@
private:
- static int writeFile(const char *path, const char *value, int size);
-
- static int readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx);
-
class SoftapCmd : public NetdCommand {
public:
SoftapCmd();
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index 7da6b43..cee8d10 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -25,9 +25,12 @@
#include <sys/types.h>
#include <string.h>
#include <pthread.h>
+#include <resolv_iface.h>
+#include <net/if.h>
#define LOG_TAG "DnsProxyListener"
#define DBG 0
+#define VDBG 0
#include <cutils/log.h>
#include <sysutils/SocketClient.h>
@@ -39,18 +42,35 @@
FrameworkListener("dnsproxyd") {
registerCmd(new GetAddrInfoCmd());
registerCmd(new GetHostByAddrCmd());
+ registerCmd(new GetHostByNameCmd());
+}
+
+DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient *c,
+ char* host,
+ char* service,
+ struct addrinfo* hints,
+ char* iface,
+ pid_t pid)
+ : mClient(c),
+ mHost(host),
+ mService(service),
+ mHints(hints),
+ mIface(iface),
+ mPid(pid) {
}
DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
free(mHost);
free(mService);
free(mHints);
+ free(mIface);
}
void DnsProxyListener::GetAddrInfoHandler::start() {
pthread_t thread;
pthread_create(&thread, NULL,
DnsProxyListener::GetAddrInfoHandler::threadStart, this);
+ pthread_detach(thread);
}
void* DnsProxyListener::GetAddrInfoHandler::threadStart(void* obj) {
@@ -69,13 +89,47 @@
(len == 0 || c->sendData(data, len) == 0);
}
+// Returns true on success
+static bool sendhostent(SocketClient *c, struct hostent *hp) {
+ bool success = true;
+ int i;
+ if (hp->h_name != NULL) {
+ success &= sendLenAndData(c, strlen(hp->h_name)+1, hp->h_name);
+ } else {
+ success &= sendLenAndData(c, 0, "") == 0;
+ }
+
+ for (i=0; hp->h_aliases[i] != NULL; i++) {
+ success &= sendLenAndData(c, strlen(hp->h_aliases[i])+1, hp->h_aliases[i]);
+ }
+ success &= sendLenAndData(c, 0, ""); // null to indicate we're done
+
+ uint32_t buf = htonl(hp->h_addrtype);
+ success &= c->sendData(&buf, sizeof(buf)) == 0;
+
+ buf = htonl(hp->h_length);
+ success &= c->sendData(&buf, sizeof(buf)) == 0;
+
+ for (i=0; hp->h_addr_list[i] != NULL; i++) {
+ success &= sendLenAndData(c, 16, hp->h_addr_list[i]);
+ }
+ success &= sendLenAndData(c, 0, ""); // null to indicate we're done
+ return success;
+}
+
void DnsProxyListener::GetAddrInfoHandler::run() {
if (DBG) {
- ALOGD("GetAddrInfoHandler, now for %s / %s", mHost, mService);
+ ALOGD("GetAddrInfoHandler, now for %s / %s / %s", mHost, mService, mIface);
+ }
+
+ char tmp[IF_NAMESIZE + 1];
+ if (mIface == NULL) {
+ _resolv_get_pids_associated_interface(mPid, tmp, sizeof(tmp));
}
struct addrinfo* result = NULL;
- uint32_t rv = getaddrinfo(mHost, mService, mHints, &result);
+ uint32_t rv = android_getaddrinfoforiface(mHost, mService, mHints, mIface ? mIface : tmp,
+ &result);
if (rv) {
// getaddrinfo failed
mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, &rv, sizeof(rv));
@@ -112,7 +166,7 @@
ALOGD("argv[%i]=%s", i, argv[i]);
}
}
- if (argc != 7) {
+ if (argc != 8) {
char* msg = NULL;
asprintf( &msg, "Invalid number of arguments to getaddrinfo: %i", argc);
ALOGW("%s", msg);
@@ -135,11 +189,20 @@
service = strdup(service);
}
+ char* iface = argv[7];
+ if (strcmp(iface, "^") == 0) {
+ iface = NULL;
+ } else {
+ iface = strdup(iface);
+ }
+
struct addrinfo* hints = NULL;
int ai_flags = atoi(argv[3]);
int ai_family = atoi(argv[4]);
int ai_socktype = atoi(argv[5]);
int ai_protocol = atoi(argv[6]);
+ pid_t pid = cli->getPid();
+
if (ai_flags != -1 || ai_family != -1 ||
ai_socktype != -1 || ai_protocol != -1) {
hints = (struct addrinfo*) calloc(1, sizeof(struct addrinfo));
@@ -150,21 +213,139 @@
}
if (DBG) {
- ALOGD("GetAddrInfoHandler for %s / %s",
+ ALOGD("GetAddrInfoHandler for %s / %s / %s / %d",
name ? name : "[nullhost]",
- service ? service : "[nullservice]");
+ service ? service : "[nullservice]",
+ iface ? iface : "[nulliface]",
+ pid);
}
cli->incRef();
DnsProxyListener::GetAddrInfoHandler* handler =
- new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints);
+ new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, iface, pid);
handler->start();
return 0;
}
/*******************************************************
- * GetHostByAddr *
+ * GetHostByName *
+ *******************************************************/
+DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd() :
+ NetdCommand("gethostbyname") {
+}
+
+int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli,
+ int argc, char **argv) {
+ if (DBG) {
+ for (int i = 0; i < argc; i++) {
+ ALOGD("argv[%i]=%s", i, argv[i]);
+ }
+ }
+ if (argc != 4) {
+ char* msg = NULL;
+ asprintf(&msg, "Invalid number of arguments to gethostbyname: %i", argc);
+ ALOGW("%s", msg);
+ cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
+ free(msg);
+ return -1;
+ }
+
+ pid_t pid = cli->getPid();
+ char* iface = argv[1];
+ char* name = argv[2];
+ int af = atoi(argv[3]);
+
+ if (strcmp(iface, "^") == 0) {
+ iface = NULL;
+ } else {
+ iface = strdup(iface);
+ }
+
+ if (strcmp(name, "^") == 0) {
+ name = NULL;
+ } else {
+ name = strdup(name);
+ }
+
+ cli->incRef();
+ DnsProxyListener::GetHostByNameHandler* handler =
+ new DnsProxyListener::GetHostByNameHandler(cli, pid, iface, name, af);
+ handler->start();
+
+ return 0;
+}
+
+DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c,
+ pid_t pid,
+ char* iface,
+ char* name,
+ int af)
+ : mClient(c),
+ mPid(pid),
+ mIface(iface),
+ mName(name),
+ mAf(af) {
+}
+
+DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
+ free(mIface);
+ free(mName);
+}
+
+void DnsProxyListener::GetHostByNameHandler::start() {
+ pthread_t thread;
+ pthread_create(&thread, NULL,
+ DnsProxyListener::GetHostByNameHandler::threadStart, this);
+ pthread_detach(thread);
+}
+
+void* DnsProxyListener::GetHostByNameHandler::threadStart(void* obj) {
+ GetHostByNameHandler* handler = reinterpret_cast<GetHostByNameHandler*>(obj);
+ handler->run();
+ delete handler;
+ pthread_exit(NULL);
+ return NULL;
+}
+
+void DnsProxyListener::GetHostByNameHandler::run() {
+ if (DBG) {
+ ALOGD("DnsProxyListener::GetHostByNameHandler::run\n");
+ }
+
+ char iface[IF_NAMESIZE + 1];
+ if (mIface == NULL) {
+ _resolv_get_pids_associated_interface(mPid, iface, sizeof(iface));
+ }
+
+ struct hostent* hp;
+
+ hp = android_gethostbynameforiface(mName, mAf, mIface ? mIface : iface);
+
+ if (DBG) {
+ ALOGD("GetHostByNameHandler::run gethostbyname errno: %s hp->h_name = %s, name_len = %d\n",
+ hp ? "success" : strerror(errno),
+ (hp && hp->h_name) ? hp->h_name: "null",
+ (hp && hp->h_name) ? strlen(hp->h_name)+ 1 : 0);
+ }
+
+ bool success = true;
+ if (hp) {
+ success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
+ success &= sendhostent(mClient, hp);
+ } else {
+ success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, NULL, 0) == 0;
+ }
+
+ if (!success) {
+ ALOGW("GetHostByNameHandler: Error writing DNS result to client\n");
+ }
+ mClient->decRef();
+}
+
+
+/*******************************************************
+ * GetHostByAddr *
*******************************************************/
DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd() :
NetdCommand("gethostbyaddr") {
@@ -177,8 +358,7 @@
ALOGD("argv[%i]=%s", i, argv[i]);
}
}
-
- if (argc != 4) {
+ if (argc != 5) {
char* msg = NULL;
asprintf(&msg, "Invalid number of arguments to gethostbyaddr: %i", argc);
ALOGW("%s", msg);
@@ -190,6 +370,14 @@
char* addrStr = argv[1];
int addrLen = atoi(argv[2]);
int addrFamily = atoi(argv[3]);
+ pid_t pid = cli->getPid();
+ char* iface = argv[4];
+
+ if (strcmp(iface, "^") == 0) {
+ iface = NULL;
+ } else {
+ iface = strdup(iface);
+ }
void* addr = malloc(sizeof(struct in6_addr));
errno = 0;
@@ -206,20 +394,36 @@
cli->incRef();
DnsProxyListener::GetHostByAddrHandler* handler =
- new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily);
+ new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, iface ,pid);
handler->start();
return 0;
}
+DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c,
+ void* address,
+ int addressLen,
+ int addressFamily,
+ char* iface,
+ pid_t pid)
+ : mClient(c),
+ mAddress(address),
+ mAddressLen(addressLen),
+ mAddressFamily(addressFamily),
+ mIface(iface),
+ mPid(pid) {
+}
+
DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
free(mAddress);
+ free(mIface);
}
void DnsProxyListener::GetHostByAddrHandler::start() {
pthread_t thread;
pthread_create(&thread, NULL,
DnsProxyListener::GetHostByAddrHandler::threadStart, this);
+ pthread_detach(thread);
}
void* DnsProxyListener::GetHostByAddrHandler::threadStart(void* obj) {
@@ -235,10 +439,16 @@
ALOGD("DnsProxyListener::GetHostByAddrHandler::run\n");
}
+ char tmp[IF_NAMESIZE + 1];
+ if (mIface == NULL) {
+ _resolv_get_pids_associated_interface(mPid, tmp, sizeof(tmp));
+ }
+
struct hostent* hp;
// NOTE gethostbyaddr should take a void* but bionic thinks it should be char*
- hp = gethostbyaddr((char*)mAddress, mAddressLen, mAddressFamily);
+ hp = android_gethostbyaddrforiface((char*)mAddress, mAddressLen, mAddressFamily,
+ mIface ? mIface : tmp);
if (DBG) {
ALOGD("GetHostByAddrHandler::run gethostbyaddr errno: %s hp->h_name = %s, name_len = %d\n",
@@ -247,18 +457,15 @@
(hp && hp->h_name) ? strlen(hp->h_name)+ 1 : 0);
}
- bool failed = true;
+ bool success = true;
if (hp) {
- failed = mClient->sendBinaryMsg(ResponseCode::DnsProxyQueryResult,
- hp->h_name ? hp->h_name : "",
- hp->h_name ? strlen(hp->h_name)+ 1 : 0);
+ success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
+ success &= sendhostent(mClient, hp);
} else {
- uint32_t error = h_errno;
- failed = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed,
- &error, sizeof(error));
+ success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, NULL, 0) == 0;
}
- if (failed) {
+ if (!success) {
ALOGW("GetHostByAddrHandler: Error writing DNS result to client\n");
}
mClient->decRef();
diff --git a/DnsProxyListener.h b/DnsProxyListener.h
index 24c3b6a..c950c02 100644
--- a/DnsProxyListener.h
+++ b/DnsProxyListener.h
@@ -40,11 +40,9 @@
GetAddrInfoHandler(SocketClient *c,
char* host,
char* service,
- struct addrinfo* hints)
- : mClient(c),
- mHost(host),
- mService(service),
- mHints(hints) {}
+ struct addrinfo* hints,
+ char* iface,
+ pid_t pid);
~GetAddrInfoHandler();
static void* threadStart(void* handler);
@@ -56,6 +54,35 @@
char* mHost; // owned
char* mService; // owned
struct addrinfo* mHints; // owned
+ char* mIface; // owned
+ pid_t mPid;
+ };
+
+ /* ------ gethostbyname ------*/
+ class GetHostByNameCmd : public NetdCommand {
+ public:
+ GetHostByNameCmd();
+ virtual ~GetHostByNameCmd() {}
+ int runCommand(SocketClient *c, int argc, char** argv);
+ };
+
+ class GetHostByNameHandler {
+ public:
+ GetHostByNameHandler(SocketClient *c,
+ pid_t pid,
+ char *iface,
+ char *name,
+ int af);
+ ~GetHostByNameHandler();
+ static void* threadStart(void* handler);
+ void start();
+ private:
+ void run();
+ SocketClient* mClient; //ref counted
+ pid_t mPid;
+ char* mIface; // owned
+ char* mName; // owned
+ int mAf;
};
/* ------ gethostbyaddr ------*/
@@ -71,11 +98,9 @@
GetHostByAddrHandler(SocketClient *c,
void* address,
int addressLen,
- int addressFamily)
- : mClient(c),
- mAddress(address),
- mAddressLen(addressLen),
- mAddressFamily(addressFamily) {}
+ int addressFamily,
+ char* iface,
+ pid_t pid);
~GetHostByAddrHandler();
static void* threadStart(void* handler);
@@ -87,6 +112,8 @@
void* mAddress; // address to lookup; owned
int mAddressLen; // length of address to look up
int mAddressFamily; // address family
+ char* mIface; // owned
+ pid_t mPid;
};
};
diff --git a/IdletimerController.cpp b/IdletimerController.cpp
index 7623f33..54b4edd 100644
--- a/IdletimerController.cpp
+++ b/IdletimerController.cpp
@@ -99,6 +99,7 @@
#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>
@@ -107,12 +108,11 @@
#define LOG_TAG "IdletimerController"
#include <cutils/log.h>
+#include <logwrap/logwrap.h>
#include "IdletimerController.h"
#include "NetdConstants.h"
-extern "C" int system_nosh(const char *command);
-
const char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
const char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING";
@@ -122,21 +122,11 @@
IdletimerController::~IdletimerController() {
}
/* return 0 or non-zero */
-int IdletimerController::runIpxtablesCmd(const char *cmd) {
- char *buffer;
- size_t len = strnlen(cmd, 255);
+int IdletimerController::runIpxtablesCmd(int argc, const char **argv) {
int res;
- if (len == 255) {
- ALOGE("command too long");
- return -1;
- }
-
- asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
- res = system_nosh(buffer);
- ALOGV("%s #%d", buffer, res);
- free(buffer);
-
+ res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
+ ALOGV("runCmd() res=%d", res);
return res;
}
@@ -146,17 +136,27 @@
int IdletimerController::setDefaults() {
int res;
- char *buffer;
- asprintf(&buffer, "-t raw -F %s", LOCAL_RAW_PREROUTING);
- res = runIpxtablesCmd(buffer);
- free(buffer);
+ const char *cmd1[] = {
+ IPTABLES_PATH,
+ "-t",
+ "raw",
+ "-F",
+ LOCAL_RAW_PREROUTING
+ };
+ res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
if (res)
return res;
- asprintf(&buffer, "-t mangle -F %s", LOCAL_MANGLE_POSTROUTING);
- res = runIpxtablesCmd(buffer);
- free(buffer);
+ const char *cmd2[] = {
+ IPTABLES_PATH,
+ "-t",
+ "mangle",
+ "-F",
+ LOCAL_MANGLE_POSTROUTING
+ };
+ res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
+
return res;
}
@@ -174,21 +174,50 @@
uint32_t timeout,
const char *classLabel) {
int res;
- char *buffer;
- asprintf(&buffer, "-t raw -%c %s -i %s -j IDLETIMER"
- " --timeout %u --label %s --send_nl_msg 1",
- (op == IptOpAdd) ? 'A' : 'D', LOCAL_RAW_PREROUTING, iface, timeout, classLabel);
- res = runIpxtablesCmd(buffer);
- free(buffer);
+ char timeout_str[11]; //enough to store any 32-bit unsigned decimal
+
+ snprintf(timeout_str, sizeof(timeout_str), "%u", timeout);
+
+ const char *cmd1[] = {
+ IPTABLES_PATH,
+ "-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;
- asprintf(&buffer, "-t mangle -%c %s -o %s -j IDLETIMER"
- " --timeout %u --label %s --send_nl_msg 1",
- (op == IptOpAdd) ? 'A' : 'D', LOCAL_MANGLE_POSTROUTING, iface, timeout, classLabel);
- res = runIpxtablesCmd(buffer);
- free(buffer);
+ const char *cmd2[] = {
+ IPTABLES_PATH,
+ "-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;
}
diff --git a/IdletimerController.h b/IdletimerController.h
index eb2aa35..98a312e 100644
--- a/IdletimerController.h
+++ b/IdletimerController.h
@@ -36,7 +36,7 @@
private:
enum IptOp { IptOpAdd, IptOpDelete };
int setDefaults();
- int runIpxtablesCmd(const char *cmd);
+ int runIpxtablesCmd(int argc, const char **cmd);
int modifyInterfaceIdletimer(IptOp op, const char *iface, uint32_t timeout,
const char *classLabel);
};
diff --git a/InterfaceController.cpp b/InterfaceController.cpp
index e02b517..00ab6d1 100644
--- a/InterfaceController.cpp
+++ b/InterfaceController.cpp
@@ -34,6 +34,8 @@
#include <netutils/ifc.h>
#include <private/android_filesystem_config.h>
+#include "NetdConstants.h"
+
#include "InterfaceController.h"
char if_cmd_lib_file_name[] = "/system/lib/libnetcmdiface.so";
@@ -99,3 +101,32 @@
return ret;
}
+
+int InterfaceController::writeIPv6ProcPath(const char *interface, const char *setting, const char *value) {
+ char *path;
+ asprintf(&path, "/proc/sys/net/ipv6/conf/%s/%s", interface, setting);
+ int success = writeFile(path, value, strlen(value));
+ free(path);
+ return success;
+}
+
+int InterfaceController::setEnableIPv6(const char *interface, const int on) {
+ // When IPv6 is on, accept RAs regardless of forwarding state.
+ // When IPv6 is off, accept RAs only if forwarding is off (the default).
+ const char *accept_ra = on ? "2" : "1";
+ if (writeIPv6ProcPath(interface, "accept_ra", accept_ra)) {
+ return -1;
+ }
+
+ // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
+ // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
+ // addresses and routes and disables IPv6 on the interface.
+ const char *disable_ipv6 = on ? "0" : "1";
+ return writeIPv6ProcPath(interface, "disable_ipv6", disable_ipv6);
+}
+
+int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
+ // 0: disable IPv6 privacy addresses
+ // 0: enable IPv6 privacy addresses and prefer them over non-privacy ones.
+ return writeIPv6ProcPath(interface, "use_tempaddr", on ? "2" : "0");
+}
diff --git a/InterfaceController.h b/InterfaceController.h
index e31cc11..b11ab4f 100644
--- a/InterfaceController.h
+++ b/InterfaceController.h
@@ -33,12 +33,16 @@
InterfaceController();
virtual ~InterfaceController();
int interfaceCommand(int argc, char *argv[], char **rbuf);
+ int setEnableIPv6(const char *interface, const int on);
+ int setIPv6PrivacyExtensions(const char *interface, const int on);
private:
void *libh_;
int (*sendCommand_)(int argc, char *argv[], char **rbuf);
int (*sendCommandInit_)(void);
int (*sendCommandFini_)(void);
+ int writeIPv6ProcPath(const char *interface, const char *setting,
+ const char *value);
};
#endif
diff --git a/MDnsSdListener.cpp b/MDnsSdListener.cpp
index 52703df..9a3f4f7 100644
--- a/MDnsSdListener.cpp
+++ b/MDnsSdListener.cpp
@@ -497,6 +497,7 @@
pthread_mutex_init(&mHeadMutex, NULL);
socketpair(AF_LOCAL, SOCK_STREAM, 0, mCtrlSocketPair);
pthread_create(&mThread, NULL, MDnsSdListener::Monitor::threadStart, this);
+ pthread_detach(mThread);
}
void *MDnsSdListener::Monitor::threadStart(void *obj) {
diff --git a/NatController.cpp b/NatController.cpp
index e44a29b..ff35d89 100644
--- a/NatController.cpp
+++ b/NatController.cpp
@@ -20,6 +20,7 @@
#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>
@@ -28,13 +29,12 @@
#define LOG_TAG "NatController"
#include <cutils/log.h>
+#include <logwrap/logwrap.h>
#include "NatController.h"
#include "SecondaryTableController.h"
#include "NetdConstants.h"
-extern "C" int system_nosh(const char *command);
-
const char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
const char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
@@ -45,21 +45,11 @@
NatController::~NatController() {
}
-int NatController::runCmd(const char *path, const char *cmd) {
- char *buffer;
- size_t len = strnlen(cmd, 255);
+int NatController::runCmd(int argc, const char **argv) {
int res;
- if (len == 255) {
- ALOGE("command too long");
- errno = E2BIG;
- return -1;
- }
-
- asprintf(&buffer, "%s %s", path, cmd);
- res = system_nosh(buffer);
- ALOGV("runCmd() buffer='%s' res=%d", buffer, res);
- free(buffer);
+ res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
+ ALOGV("runCmd() res=%d", res);
return res;
}
@@ -69,18 +59,100 @@
}
int NatController::setDefaults() {
- if (runCmd(IPTABLES_PATH, "-F natctrl_FORWARD"))
- return -1;
- if (runCmd(IPTABLES_PATH, "-t nat -F natctrl_nat_POSTROUTING"))
+ const char *cmd1[] = {
+ IPTABLES_PATH,
+ "-F",
+ "natctrl_FORWARD"
+ };
+ if (runCmd(ARRAY_SIZE(cmd1), cmd1))
return -1;
- runCmd(IP_PATH, "rule flush");
- runCmd(IP_PATH, "-6 rule flush");
- runCmd(IP_PATH, "rule add from all lookup default prio 32767");
- runCmd(IP_PATH, "rule add from all lookup main prio 32766");
- runCmd(IP_PATH, "-6 rule add from all lookup default prio 32767");
- runCmd(IP_PATH, "-6 rule add from all lookup main prio 32766");
- runCmd(IP_PATH, "route flush cache");
+ const char *cmd2[] = {
+ IPTABLES_PATH,
+ "-t",
+ "nat",
+ "-F",
+ "natctrl_nat_POSTROUTING"
+ };
+ if (runCmd(ARRAY_SIZE(cmd2), cmd2))
+ return -1;
+
+ const char *cmd3[] = {
+ IP_PATH,
+ "rule",
+ "flush"
+ };
+ runCmd(ARRAY_SIZE(cmd3), cmd3);
+
+ const char *cmd4[] = {
+ IP_PATH,
+ "-6",
+ "rule",
+ "flush"
+ };
+ runCmd(ARRAY_SIZE(cmd4), cmd4);
+
+ const char *cmd5[] = {
+ IP_PATH,
+ "rule",
+ "add",
+ "from",
+ "all",
+ "lookup",
+ "default",
+ "prio",
+ "32767"
+ };
+ runCmd(ARRAY_SIZE(cmd5), cmd5);
+
+ const char *cmd6[] = {
+ IP_PATH,
+ "rule",
+ "add",
+ "from",
+ "all",
+ "lookup",
+ "main",
+ "prio",
+ "32766"
+ };
+ runCmd(ARRAY_SIZE(cmd6), cmd6);
+
+ const char *cmd7[] = {
+ IP_PATH,
+ "-6",
+ "rule",
+ "add",
+ "from",
+ "all",
+ "lookup",
+ "default",
+ "prio",
+ "32767"
+ };
+ runCmd(ARRAY_SIZE(cmd7), cmd7);
+
+ const char *cmd8[] = {
+ IP_PATH,
+ "-6",
+ "rule",
+ "add",
+ "from",
+ "all",
+ "lookup",
+ "main",
+ "prio",
+ "32766"
+ };
+ runCmd(ARRAY_SIZE(cmd8), cmd8);
+
+ const char *cmd9[] = {
+ IP_PATH,
+ "route",
+ "flush",
+ "cache"
+ };
+ runCmd(ARRAY_SIZE(cmd9), cmd9);
natCount = 0;
@@ -95,7 +167,6 @@
// 0 1 2 3 4 5
// nat enable intface extface addrcnt nated-ipaddr/prelength
int NatController::enableNat(const int argc, char **argv) {
- char cmd[255];
int i;
int addrCount = atoi(argv[4]);
int ret = 0;
@@ -122,7 +193,13 @@
ret |= secondaryTableCtrl->modifyLocalRoute(tableNumber, ADD, intIface, argv[5+i]);
}
- runCmd(IP_PATH, "route flush cache");
+ const char *cmd[] = {
+ IP_PATH,
+ "route",
+ "flush",
+ "cache"
+ };
+ runCmd(ARRAY_SIZE(cmd), cmd);
}
if (ret != 0 || setForwardRules(true, intIface, extIface) != 0) {
@@ -132,7 +209,13 @@
secondaryTableCtrl->modifyFromRule(tableNumber, DEL, argv[5+i]);
}
- runCmd(IP_PATH, "route flush cache");
+ const char *cmd[] = {
+ IP_PATH,
+ "route",
+ "flush",
+ "cache"
+ };
+ runCmd(ARRAY_SIZE(cmd), cmd);
}
ALOGE("Error setting forward rules");
errno = ENODEV;
@@ -140,18 +223,40 @@
}
/* Always make sure the drop rule is at the end */
- snprintf(cmd, sizeof(cmd), "-D natctrl_FORWARD -j DROP");
- runCmd(IPTABLES_PATH, cmd);
- snprintf(cmd, sizeof(cmd), "-A natctrl_FORWARD -j DROP");
- runCmd(IPTABLES_PATH, cmd);
+ const char *cmd1[] = {
+ IPTABLES_PATH,
+ "-D",
+ "natctrl_FORWARD",
+ "-j",
+ "DROP"
+ };
+ runCmd(ARRAY_SIZE(cmd1), cmd1);
+ const char *cmd2[] = {
+ IPTABLES_PATH,
+ "-A",
+ "natctrl_FORWARD",
+ "-j",
+ "DROP"
+ };
+ runCmd(ARRAY_SIZE(cmd2), cmd2);
natCount++;
// add this if we are the first added nat
if (natCount == 1) {
- snprintf(cmd, sizeof(cmd), "-t nat -A natctrl_nat_POSTROUTING -o %s -j MASQUERADE", extIface);
- if (runCmd(IPTABLES_PATH, cmd)) {
- ALOGE("Error seting postroute rule: %s", cmd);
+ const char *cmd[] = {
+ IPTABLES_PATH,
+ "-t",
+ "nat",
+ "-A",
+ "natctrl_nat_POSTROUTING",
+ "-o",
+ extIface,
+ "-j",
+ "MASQUERADE"
+ };
+ if (runCmd(ARRAY_SIZE(cmd), cmd)) {
+ ALOGE("Error seting postroute rule: iface=%s", extIface);
// unwind what's been done, but don't care about success - what more could we do?
for (i = 0; i < addrCount; i++) {
secondaryTableCtrl->modifyLocalRoute(tableNumber, DEL, intIface, argv[5+i]);
@@ -167,56 +272,82 @@
}
int NatController::setForwardRules(bool add, const char *intIface, const char * extIface) {
- char cmd[255];
+ const char *cmd1[] = {
+ IPTABLES_PATH,
+ add ? "-A" : "-D",
+ "natctrl_FORWARD",
+ "-i",
+ extIface,
+ "-o",
+ intIface,
+ "-m",
+ "state",
+ "--state",
+ "ESTABLISHED,RELATED",
+ "-j",
+ "RETURN"
+ };
+ int rc = 0;
- snprintf(cmd, sizeof(cmd),
- "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
- (add ? "A" : "D"),
- extIface, intIface);
- if (runCmd(IPTABLES_PATH, cmd) && add) {
+ if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
return -1;
}
- snprintf(cmd, sizeof(cmd),
- "-%s natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
- (add ? "A" : "D"),
- intIface, extIface);
- if (runCmd(IPTABLES_PATH, cmd) && add) {
+ const char *cmd2[] = {
+ IPTABLES_PATH,
+ add ? "-A" : "-D",
+ "natctrl_FORWARD",
+ "-i",
+ intIface,
+ "-o",
+ extIface,
+ "-m",
+ "state",
+ "--state",
+ "INVALID",
+ "-j",
+ "DROP"
+ };
+
+ const char *cmd3[] = {
+ IPTABLES_PATH,
+ add ? "-A" : "-D",
+ "natctrl_FORWARD",
+ "-i",
+ intIface,
+ "-o",
+ extIface,
+ "-j",
+ "RETURN"
+ };
+
+ if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
// bail on error, but only if adding
- snprintf(cmd, sizeof(cmd),
- "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
- (!add ? "A" : "D"),
- extIface, intIface);
- runCmd(IPTABLES_PATH, cmd);
- return -1;
+ rc = -1;
+ goto err_invalid_drop;
}
- snprintf(cmd, sizeof(cmd), "-%s natctrl_FORWARD -i %s -o %s -j RETURN", (add ? "A" : "D"),
- intIface, extIface);
- if (runCmd(IPTABLES_PATH, cmd) && add) {
+ if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
// unwind what's been done, but don't care about success - what more could we do?
- snprintf(cmd, sizeof(cmd),
- "-%s natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
- (!add ? "A" : "D"),
- intIface, extIface);
- runCmd(IPTABLES_PATH, cmd);
-
- snprintf(cmd, sizeof(cmd),
- "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
- (!add ? "A" : "D"),
- extIface, intIface);
- runCmd(IPTABLES_PATH, cmd);
- return -1;
+ rc = -1;
+ goto err_return;
}
return 0;
+
+err_return:
+ cmd2[1] = "-D";
+ runCmd(ARRAY_SIZE(cmd2), cmd2);
+err_invalid_drop:
+ cmd1[1] = "-D";
+ runCmd(ARRAY_SIZE(cmd1), cmd1);
+ return rc;
}
// nat disable intface extface
// 0 1 2 3 4 5
// nat enable intface extface addrcnt nated-ipaddr/prelength
int NatController::disableNat(const int argc, char **argv) {
- char cmd[255];
int i;
int addrCount = atoi(argv[4]);
const char *intIface = argv[2];
@@ -245,7 +376,13 @@
secondaryTableCtrl->modifyFromRule(tableNumber, DEL, argv[5+i]);
}
- runCmd(IP_PATH, "route flush cache");
+ const char *cmd[] = {
+ IP_PATH,
+ "route",
+ "flush",
+ "cache"
+ };
+ runCmd(ARRAY_SIZE(cmd), cmd);
}
if (--natCount <= 0) {
diff --git a/NatController.h b/NatController.h
index c1979bb..4330567 100644
--- a/NatController.h
+++ b/NatController.h
@@ -39,7 +39,7 @@
SecondaryTableController *secondaryTableCtrl;
int setDefaults();
- int runCmd(const char *path, const char *cmd);
+ int runCmd(int argc, const char **argv);
bool checkInterface(const char *iface);
int setForwardRules(bool set, const char *intIface, const char *extIface);
};
diff --git a/NetdConstants.cpp b/NetdConstants.cpp
index db1d4cd..1ab09a5 100644
--- a/NetdConstants.cpp
+++ b/NetdConstants.cpp
@@ -14,11 +14,14 @@
* limitations under the License.
*/
+#include <fcntl.h>
#include <string.h>
+#include <sys/wait.h>
#define LOG_TAG "Netd"
#include <cutils/log.h>
+#include <logwrap/logwrap.h>
#include "NetdConstants.h"
@@ -30,7 +33,7 @@
const char * const ADD = "add";
const char * const DEL = "del";
-static void logExecError(const char* argv[], int res) {
+static void logExecError(const char* argv[], int res, int status) {
const char** argp = argv;
std::string args = "";
while (*argp) {
@@ -38,7 +41,25 @@
args += ' ';
argp++;
}
- ALOGE("exec() res=%d for %s", res, args.c_str());
+ ALOGE("exec() res=%d, status=%d for %s", res, status, args.c_str());
+}
+
+static int execIptablesCommand(int argc, const char *argv[], bool silent) {
+ int res;
+ int status;
+
+ res = android_fork_execvp(argc, (char **)argv, &status, false,
+ !silent);
+ if (res || !WIFEXITED(status) || WEXITSTATUS(status)) {
+ if (!silent) {
+ logExecError(argv, res, status);
+ }
+ if (res)
+ return res;
+ if (!WIFEXITED(status))
+ return ECHILD;
+ }
+ return WEXITSTATUS(status);
}
static int execIptables(IptablesTarget target, bool silent, va_list args) {
@@ -61,23 +82,11 @@
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;
- }
+ res |= execIptablesCommand(argsList.size(), argv, silent);
}
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;
- }
+ res |= execIptablesCommand(argsList.size(), argv, silent);
}
return res;
}
@@ -97,3 +106,19 @@
va_end(args);
return res;
}
+
+int writeFile(const char *path, const char *value, int size) {
+ int fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ ALOGE("Failed to open %s: %s", path, strerror(errno));
+ return -1;
+ }
+
+ if (write(fd, value, size) != size) {
+ ALOGE("Failed to write %s: %s", path, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
+}
diff --git a/NetdConstants.h b/NetdConstants.h
index 8468f9b..eb59af2 100644
--- a/NetdConstants.h
+++ b/NetdConstants.h
@@ -29,11 +29,12 @@
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, ...);
+int writeFile(const char *path, const char *value, int size);
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
#endif
diff --git a/ResolverController.cpp b/ResolverController.cpp
index 23554e8..13dd930 100644
--- a/ResolverController.cpp
+++ b/ResolverController.cpp
@@ -37,12 +37,12 @@
return 0;
}
-int ResolverController::setInterfaceDnsServers(const char* iface, char** servers, int numservers) {
+int ResolverController::setInterfaceDnsServers(const char* iface, const char* domains,
+ char** servers, int numservers) {
if (DBG) {
ALOGD("setInterfaceDnsServers iface = %s\n", iface);
}
-
- _resolv_set_nameservers_for_iface(iface, servers, numservers);
+ _resolv_set_nameservers_for_iface(iface, servers, numservers, domains);
return 0;
}
@@ -76,3 +76,23 @@
return 0;
}
+
+int ResolverController::setDnsInterfaceForPid(const char* iface, int pid) {
+ if (DBG) {
+ ALOGD("setDnsIfaceForPid iface = %s, pid = %d\n", iface, pid);
+ }
+
+ _resolv_set_iface_for_pid(iface, pid);
+
+ return 0;
+}
+
+int ResolverController::clearDnsInterfaceForPid(int pid) {
+ if (DBG) {
+ ALOGD("clearDnsIfaceForPid pid = %d\n", pid);
+ }
+
+ _resolv_clear_iface_for_pid(pid);
+
+ return 0;
+}
diff --git a/ResolverController.h b/ResolverController.h
index c6260da..a21e077 100644
--- a/ResolverController.h
+++ b/ResolverController.h
@@ -26,10 +26,13 @@
virtual ~ResolverController() {};
int setDefaultInterface(const char* iface);
- int setInterfaceDnsServers(const char* iface, char** servers, int numservers);
+ int setInterfaceDnsServers(const char* iface, const char * domains, char** servers,
+ int numservers);
int setInterfaceAddress(const char* iface, struct in_addr* addr);
int flushDefaultDnsCache();
int flushInterfaceDnsCache(const char* iface);
+ int setDnsInterfaceForPid(const char* iface, int pid);
+ int clearDnsInterfaceForPid(int pid);
};
#endif /* _RESOLVER_CONTROLLER_H_ */
diff --git a/SecondaryTableController.cpp b/SecondaryTableController.cpp
index 7d3de38..ce23d28 100644
--- a/SecondaryTableController.cpp
+++ b/SecondaryTableController.cpp
@@ -30,8 +30,7 @@
#define LOG_TAG "SecondaryTablController"
#include <cutils/log.h>
#include <cutils/properties.h>
-
-extern "C" int system_nosh(const char *command);
+#include <logwrap/logwrap.h>
#include "ResponseCode.h"
#include "NetdConstants.h"
@@ -81,18 +80,43 @@
int SecondaryTableController::modifyRoute(SocketClient *cli, const char *action, char *iface,
char *dest, int prefix, char *gateway, int tableIndex) {
- char *cmd;
+ char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
+ char tableIndex_str[11];
+ int ret;
+
+ // IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4
+ snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
+ snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex + BASE_TABLE_NUMBER);
if (strcmp("::", gateway) == 0) {
- // IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4
- asprintf(&cmd, "%s route %s %s/%d dev %s table %d",
- IP_PATH, action, dest, prefix, iface, tableIndex+BASE_TABLE_NUMBER);
+ const char *cmd[] = {
+ IP_PATH,
+ "route",
+ action,
+ dest_str,
+ "dev",
+ iface,
+ "table",
+ tableIndex_str
+ };
+ ret = runCmd(ARRAY_SIZE(cmd), cmd);
} else {
- asprintf(&cmd, "%s route %s %s/%d via %s dev %s table %d",
- IP_PATH, action, dest, prefix, gateway, iface, tableIndex+BASE_TABLE_NUMBER);
+ const char *cmd[] = {
+ IP_PATH,
+ "route",
+ action,
+ dest_str,
+ "via",
+ gateway,
+ "dev",
+ iface,
+ "table",
+ tableIndex_str
+ };
+ ret = runCmd(ARRAY_SIZE(cmd), cmd);
}
- if (runAndFree(cli, cmd)) {
+ if (ret) {
ALOGE("ip route %s failed: %s route %s %s/%d via %s dev %s table %d", action,
IP_PATH, action, dest, prefix, gateway, iface, tableIndex+BASE_TABLE_NUMBER);
errno = ENODEV;
@@ -157,14 +181,25 @@
int SecondaryTableController::modifyFromRule(int tableIndex, const char *action,
const char *addr) {
- char *cmd;
+ char tableIndex_str[11];
if (verifyTableIndex(tableIndex)) {
return -1;
}
- asprintf(&cmd, "%s %s rule %s from %s table %d", IP_PATH, getVersion(addr),
- action, addr, tableIndex + BASE_TABLE_NUMBER);
- if (runAndFree(NULL, cmd)) {
+
+ snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
+ BASE_TABLE_NUMBER);
+ const char *cmd[] = {
+ IP_PATH,
+ getVersion(addr),
+ "rule",
+ action,
+ "from",
+ addr,
+ "table",
+ tableIndex_str
+ };
+ if (runCmd(ARRAY_SIZE(cmd), cmd)) {
return -1;
}
@@ -174,7 +209,7 @@
int SecondaryTableController::modifyLocalRoute(int tableIndex, const char *action,
const char *iface, const char *addr) {
- char *cmd;
+ char tableIndex_str[11];
if (verifyTableIndex(tableIndex)) {
return -1;
@@ -182,23 +217,25 @@
modifyRuleCount(tableIndex, action); // some del's will fail as the iface is already gone.
- asprintf(&cmd, "%s route %s %s dev %s table %d", IP_PATH, action, addr, iface,
- tableIndex+BASE_TABLE_NUMBER);
- return runAndFree(NULL, cmd);
+ snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
+ BASE_TABLE_NUMBER);
+ const char *cmd[] = {
+ IP_PATH,
+ "route",
+ action,
+ addr,
+ "dev",
+ iface,
+ "table",
+ tableIndex_str
+ };
+
+ return runCmd(ARRAY_SIZE(cmd), cmd);
}
-int SecondaryTableController::runAndFree(SocketClient *cli, char *cmd) {
+int SecondaryTableController::runCmd(int argc, const char **argv) {
int ret = 0;
- if (strlen(cmd) >= 255) {
- if (cli != NULL) {
- ALOGE("ip command (%s) too long", cmd);
- errno = E2BIG;
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Too long", true);
- }
- free(cmd);
- return -1;
- }
- ret = system_nosh(cmd);
- free(cmd);
+
+ ret = android_fork_execvp(argc, (char **)argv, NULL, false, false);
return ret;
}
diff --git a/SecondaryTableController.h b/SecondaryTableController.h
index 79e0592..8531900 100644
--- a/SecondaryTableController.h
+++ b/SecondaryTableController.h
@@ -51,7 +51,7 @@
int verifyTableIndex(int tableIndex);
const char *getVersion(const char *addr);
- int runAndFree(SocketClient *cli, char *cmd);
+ int runCmd(int argc, const char **argv);
};
#endif
diff --git a/SoftapController.cpp b/SoftapController.cpp
index 7c7b2d0..21274f4 100644
--- a/SoftapController.cpp
+++ b/SoftapController.cpp
@@ -38,129 +38,101 @@
#include <netutils/ifc.h>
#include <private/android_filesystem_config.h>
#include "wifi.h"
+#include "ResponseCode.h"
#include "SoftapController.h"
static const char HOSTAPD_CONF_FILE[] = "/data/misc/wifi/hostapd.conf";
+static const char HOSTAPD_BIN_FILE[] = "/system/bin/hostapd";
-SoftapController::SoftapController() {
- mPid = 0;
- mSock = socket(AF_INET, SOCK_DGRAM, 0);
- if (mSock < 0)
- ALOGE("Failed to open socket");
-}
+SoftapController::SoftapController()
+ : mPid(0) {}
SoftapController::~SoftapController() {
- if (mSock >= 0)
- close(mSock);
}
int SoftapController::startSoftap() {
pid_t pid = 1;
- int ret = 0;
if (mPid) {
- ALOGE("Softap already started");
- return 0;
- }
- if (mSock < 0) {
- ALOGE("Softap startap - failed to open socket");
- return -1;
+ ALOGE("SoftAP is already running");
+ return ResponseCode::SoftapStatusResult;
}
if ((pid = fork()) < 0) {
ALOGE("fork failed (%s)", strerror(errno));
- return -1;
+ return ResponseCode::ServiceStartFailed;
}
if (!pid) {
ensure_entropy_file_exists();
- if (execl("/system/bin/hostapd", "/system/bin/hostapd",
+ if (execl(HOSTAPD_BIN_FILE, HOSTAPD_BIN_FILE,
"-e", WIFI_ENTROPY_FILE,
HOSTAPD_CONF_FILE, (char *) NULL)) {
ALOGE("execl failed (%s)", strerror(errno));
}
- ALOGE("Should never get here!");
- return -1;
+ ALOGE("SoftAP failed to start");
+ return ResponseCode::ServiceStartFailed;
} else {
mPid = pid;
- ALOGD("Softap startap - Ok");
+ ALOGD("SoftAP started successfully");
usleep(AP_BSS_START_DELAY);
}
- return ret;
-
+ return ResponseCode::SoftapStatusResult;
}
int SoftapController::stopSoftap() {
if (mPid == 0) {
- ALOGE("Softap already stopped");
- return 0;
+ ALOGE("SoftAP is not running");
+ return ResponseCode::SoftapStatusResult;
}
- ALOGD("Stopping Softap service");
+ ALOGD("Stopping the SoftAP service...");
kill(mPid, SIGTERM);
waitpid(mPid, NULL, 0);
- if (mSock < 0) {
- ALOGE("Softap stopap - failed to open socket");
- return -1;
- }
mPid = 0;
- ALOGD("Softap service stopped");
+ ALOGD("SoftAP stopped successfully");
usleep(AP_BSS_STOP_DELAY);
- return 0;
+ return ResponseCode::SoftapStatusResult;
}
bool SoftapController::isSoftapStarted() {
- return (mPid != 0 ? true : false);
+ return (mPid != 0);
}
/*
* Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Security
- * argv[5] - Key
- * argv[6] - Channel
- * argv[7] - Preamble
- * argv[8] - Max SCB
+ * argv[2] - wlan interface
+ * argv[3] - SSID
+ * argv[4] - Security
+ * argv[5] - Key
*/
int SoftapController::setSoftap(int argc, char *argv[]) {
char psk_str[2*SHA256_DIGEST_LENGTH+1];
- int ret = 0, i = 0, fd;
- char *ssid, *iface;
+ int ret = ResponseCode::SoftapStatusResult;
+ int i = 0;
+ int fd;
- if (mSock < 0) {
- ALOGE("Softap set - failed to open socket");
- return -1;
- }
if (argc < 4) {
- ALOGE("Softap set - missing arguments");
- return -1;
+ ALOGE("Softap set is missing arguments. Please use: softap <wlan iface> <SSID> <wpa2?-psk|open> <passphrase>");
+ return ResponseCode::CommandSyntaxError;
}
- iface = argv[2];
-
char *wbuf = NULL;
char *fbuf = NULL;
- if (argc > 3) {
- ssid = argv[3];
- } else {
- ssid = (char *)"AndroidAP";
- }
-
asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
"/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",
- iface, ssid);
+ argv[2], argv[3]);
if (argc > 4) {
if (!strcmp(argv[4], "wpa-psk")) {
- generatePsk(ssid, argv[5], psk_str);
+ generatePsk(argv[3], argv[5], psk_str);
asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);
} else if (!strcmp(argv[4], "wpa2-psk")) {
- generatePsk(ssid, argv[5], psk_str);
+ generatePsk(argv[3], argv[5], psk_str);
asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);
} else if (!strcmp(argv[4], "open")) {
asprintf(&fbuf, "%s", wbuf);
@@ -174,11 +146,11 @@
ALOGE("Cannot update \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
free(wbuf);
free(fbuf);
- return -1;
+ return ResponseCode::OperationFailed;
}
if (write(fd, fbuf, strlen(fbuf)) < 0) {
ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
- ret = -1;
+ ret = ResponseCode::OperationFailed;
}
free(wbuf);
free(fbuf);
@@ -189,7 +161,7 @@
HOSTAPD_CONF_FILE, strerror(errno));
close(fd);
unlink(HOSTAPD_CONF_FILE);
- return -1;
+ return ResponseCode::OperationFailed;
}
if (fchown(fd, AID_SYSTEM, AID_WIFI) < 0) {
@@ -197,13 +169,47 @@
HOSTAPD_CONF_FILE, AID_WIFI, strerror(errno));
close(fd);
unlink(HOSTAPD_CONF_FILE);
- return -1;
+ return ResponseCode::OperationFailed;
}
close(fd);
return ret;
}
+/*
+ * Arguments:
+ * argv[2] - interface name
+ * argv[3] - AP or P2P or STA
+ */
+int SoftapController::fwReloadSoftap(int argc, char *argv[])
+{
+ int i = 0;
+ char *fwpath = NULL;
+
+ if (argc < 4) {
+ ALOGE("SoftAP fwreload is missing arguments. Please use: softap <wlan iface> <AP|P2P|STA>");
+ return ResponseCode::CommandSyntaxError;
+ }
+
+ if (strcmp(argv[3], "AP") == 0) {
+ fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
+ } else if (strcmp(argv[3], "P2P") == 0) {
+ fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
+ } else if (strcmp(argv[3], "STA") == 0) {
+ fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
+ }
+ if (!fwpath)
+ return ResponseCode::CommandParameterError;
+ if (wifi_change_fw_path((const char *)fwpath)) {
+ ALOGE("Softap fwReload failed");
+ return ResponseCode::OperationFailed;
+ }
+ else {
+ ALOGD("Softap fwReload - Ok");
+ }
+ return ResponseCode::SoftapStatusResult;
+}
+
void SoftapController::generatePsk(char *ssid, char *passphrase, char *psk_str) {
unsigned char psk[SHA256_DIGEST_LENGTH];
int j;
@@ -212,55 +218,6 @@
reinterpret_cast<const unsigned char *>(ssid), strlen(ssid),
4096, SHA256_DIGEST_LENGTH, psk);
for (j=0; j < SHA256_DIGEST_LENGTH; j++) {
- sprintf(&psk_str[j<<1], "%02x", psk[j]);
+ sprintf(&psk_str[j*2], "%02x", psk[j]);
}
- psk_str[j<<1] = '\0';
-}
-
-
-/*
- * Arguments:
- * argv[2] - interface name
- * argv[3] - AP or STA
- */
-int SoftapController::fwReloadSoftap(int argc, char *argv[])
-{
- int ret, i = 0;
- char *iface;
- char *fwpath;
-
- if (mSock < 0) {
- ALOGE("Softap fwrealod - failed to open socket");
- return -1;
- }
- if (argc < 4) {
- ALOGE("Softap fwreload - missing arguments");
- return -1;
- }
-
- iface = argv[2];
-
- if (strcmp(argv[3], "AP") == 0) {
- fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
- } else if (strcmp(argv[3], "P2P") == 0) {
- fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
- } else {
- fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
- }
- if (!fwpath)
- return -1;
- ret = wifi_change_fw_path((const char *)fwpath);
- if (ret) {
- ALOGE("Softap fwReload - failed: %d", ret);
- }
- else {
- ALOGD("Softap fwReload - Ok");
- }
- return ret;
-}
-
-int SoftapController::clientsSoftap(char **retbuf)
-{
- /* TODO: implement over hostapd */
- return 0;
}
diff --git a/SoftapController.h b/SoftapController.h
index 57241b9..38ff8ff 100644
--- a/SoftapController.h
+++ b/SoftapController.h
@@ -27,11 +27,6 @@
#define AP_DRIVER_START_DELAY 800000
class SoftapController {
- pid_t mPid;
- int mSock;
-
- int addParam(int pos, const char *cmd, const char *arg);
- int setCommand(char *iface, const char *fname, unsigned buflen=0);
public:
SoftapController();
virtual ~SoftapController();
@@ -40,9 +35,10 @@
int stopSoftap();
bool isSoftapStarted();
int setSoftap(int argc, char *argv[]);
- void generatePsk(char *ssid, char *passphrase, char *psk);
int fwReloadSoftap(int argc, char *argv[]);
- int clientsSoftap(char **retbuf);
+private:
+ pid_t mPid;
+ void generatePsk(char *ssid, char *passphrase, char *psk);
};
#endif
diff --git a/TetherController.cpp b/TetherController.cpp
index 5f571a1..d067f11 100644
--- a/TetherController.cpp
+++ b/TetherController.cpp
@@ -158,12 +158,12 @@
ALOGE("execl failed (%s)", strerror(errno));
}
ALOGE("Should never get here!");
- free(args);
- return 0;
+ _exit(-1);
} else {
close(pipefd[0]);
mDaemonPid = pid;
mDaemonFd = pipefd[1];
+ applyDnsInterfaces();
ALOGD("Tethering services running");
}
@@ -217,11 +217,11 @@
char *args[10];
int argc = 0;
- args[argc++] = "/system/bin/dhcpcd";
+ args[argc++] = (char *)"/system/bin/dhcpcd";
char host_name[128];
if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
{
- args[argc++] = "-h";
+ args[argc++] = (char *)"-h";
args[argc++] = host_name;
}
args[argc++] = (char*)iface;
@@ -233,7 +233,7 @@
// 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);
+ _exit(-1);
} else {
mDhcpcdPid = pid;
ALOGD("Reverse Tethering running, pid:%d", pid);
@@ -308,19 +308,67 @@
return mDnsForwarders;
}
-int TetherController::tetherInterface(const char *interface) {
- mInterfaces->push_back(strdup(interface));
+int TetherController::applyDnsInterfaces() {
+ int i;
+ char daemonCmd[MAX_CMD_SIZE];
+
+ strcpy(daemonCmd, "update_ifaces");
+ int cmdLen = strlen(daemonCmd);
+ InterfaceCollection::iterator it;
+ bool haveInterfaces = false;
+
+ for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
+ cmdLen += (strlen(*it) + 1);
+ if (cmdLen + 1 >= MAX_CMD_SIZE) {
+ ALOGD("Too many DNS ifaces listed");
+ break;
+ }
+
+ strcat(daemonCmd, ":");
+ strcat(daemonCmd, *it);
+ haveInterfaces = true;
+ }
+
+ if ((mDaemonFd != -1) && haveInterfaces) {
+ ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
+ if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
+ ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
+ return -1;
+ }
+ }
return 0;
}
+int TetherController::tetherInterface(const char *interface) {
+ ALOGD("tetherInterface(%s)", interface);
+ mInterfaces->push_back(strdup(interface));
+
+ if (applyDnsInterfaces()) {
+ InterfaceCollection::iterator it;
+ for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
+ if (!strcmp(interface, *it)) {
+ free(*it);
+ mInterfaces->erase(it);
+ break;
+ }
+ }
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
int TetherController::untetherInterface(const char *interface) {
InterfaceCollection::iterator it;
+ ALOGD("untetherInterface(%s)", interface);
+
for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
if (!strcmp(interface, *it)) {
free(*it);
mInterfaces->erase(it);
- return 0;
+
+ return applyDnsInterfaces();
}
}
errno = ENOENT;
diff --git a/TetherController.h b/TetherController.h
index d3106eb..02cd412 100644
--- a/TetherController.h
+++ b/TetherController.h
@@ -52,6 +52,9 @@
int tetherInterface(const char *interface);
int untetherInterface(const char *interface);
InterfaceCollection *getTetheredInterfaceList();
+
+private:
+ int applyDnsInterfaces();
};
#endif
diff --git a/ThrottleController.cpp b/ThrottleController.cpp
deleted file mode 100644
index 5bd7ad5..0000000
--- a/ThrottleController.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2008 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 <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/pkt_sched.h>
-
-#define LOG_TAG "ThrottleController"
-#include <cutils/log.h>
-
-
-#include "ThrottleController.h"
-#include "NetdConstants.h"
-
-extern "C" int system_nosh(const char *command);
-extern "C" int ifc_init(void);
-extern "C" int ifc_up(const char *name);
-extern "C" int ifc_down(const char *name);
-
-int ThrottleController::runTcCmd(const char *cmd) {
- char *buffer;
- size_t len = strnlen(cmd, 255);
- int res;
-
- if (len == 255) {
- ALOGE("tc command too long");
- errno = E2BIG;
- return -1;
- }
-
- asprintf(&buffer, "%s %s", TC_PATH, cmd);
- res = system_nosh(buffer);
- free(buffer);
- return res;
-}
-
-int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) {
- char cmd[512];
- char ifn[65];
- int rc;
-
- memset(ifn, 0, sizeof(ifn));
- strncpy(ifn, iface, sizeof(ifn)-1);
-
- if (txKbps == -1) {
- reset(ifn);
- return 0;
- }
-
- /*
- *
- * Target interface configuration
- *
- */
-
- /*
- * Add root qdisc for the interface
- */
- sprintf(cmd, "qdisc add dev %s root handle 1: htb default 1 r2q 1000", ifn);
- if (runTcCmd(cmd)) {
- ALOGE("Failed to add root qdisc (%s)", strerror(errno));
- goto fail;
- }
-
- /*
- * Add our egress throttling class
- */
- sprintf(cmd, "class add dev %s parent 1: classid 1:1 htb rate %dkbit", ifn, txKbps);
- if (runTcCmd(cmd)) {
- ALOGE("Failed to add egress throttling class (%s)", strerror(errno));
- goto fail;
- }
-
- /*
- * Bring up the IFD device
- */
- ifc_init();
- if (ifc_up("ifb0")) {
- ALOGE("Failed to up ifb0 (%s)", strerror(errno));
- goto fail;
- }
-
- /*
- * Add root qdisc for IFD
- */
- sprintf(cmd, "qdisc add dev ifb0 root handle 1: htb default 1 r2q 1000");
- if (runTcCmd(cmd)) {
- ALOGE("Failed to add root ifb qdisc (%s)", strerror(errno));
- goto fail;
- }
-
- /*
- * Add our ingress throttling class
- */
- sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 htb rate %dkbit", rxKbps);
- if (runTcCmd(cmd)) {
- ALOGE("Failed to add ingress throttling class (%s)", strerror(errno));
- goto fail;
- }
-
- /*
- * Add ingress qdisc for pkt redirection
- */
- sprintf(cmd, "qdisc add dev %s ingress", ifn);
- if (runTcCmd(cmd)) {
- ALOGE("Failed to add ingress qdisc (%s)", strerror(errno));
- goto fail;
- }
-
- /*
- * Add filter to link <ifn> -> ifb0
- */
- sprintf(cmd, "filter add dev %s parent ffff: protocol ip prio 10 u32 match "
- "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn);
- if (runTcCmd(cmd)) {
- ALOGE("Failed to add ifb filter (%s)", strerror(errno));
- goto fail;
- }
-
- return 0;
-fail:
- reset(ifn);
- return -1;
-}
-
-void ThrottleController::reset(const char *iface) {
- char cmd[128];
-
- sprintf(cmd, "qdisc del dev %s root", iface);
- runTcCmd(cmd);
- sprintf(cmd, "qdisc del dev %s ingress", iface);
- runTcCmd(cmd);
-
- runTcCmd("qdisc del dev ifb0 root");
-}
-
-int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) {
- *rx = 0;
- return 0;
-}
-
-int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) {
- *tx = 0;
- return 0;
-}
diff --git a/ThrottleController.h b/ThrottleController.h
deleted file mode 100644
index 3538e03..0000000
--- a/ThrottleController.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 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 _THROTTLE_CONTROLLER_H
-#define _THROTTLE_CONTROLLER_H
-
-class ThrottleController {
-public:
- static int setInterfaceThrottle(const char *iface, int rxKbps, int txKbps);
- static int getInterfaceRxThrottle(const char *iface, int *rx);
- static int getInterfaceTxThrottle(const char *iface, int *tx);
-
-private:
- static int runTcCmd(const char *cmd);
- static void reset(const char *iface);
-};
-
-#endif
diff --git a/logwrapper.c b/logwrapper.c
deleted file mode 100644
index e84ae89..0000000
--- a/logwrapper.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2008 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 <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "private/android_filesystem_config.h"
-#include "cutils/log.h"
-
-int parent(const char *tag, int parent_read) {
- int status;
- char buffer[4096];
-
- int a = 0; // start index of unprocessed data
- int b = 0; // end index of unprocessed data
- int sz;
- while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
-
- sz += b;
- // Log one line at a time
- for (b = 0; b < sz; b++) {
- if (buffer[b] == '\r') {
- buffer[b] = '\0';
- } else if (buffer[b] == '\n') {
- buffer[b] = '\0';
-
- ALOG(LOG_INFO, tag, "%s", &buffer[a]);
- a = b + 1;
- }
- }
-
- if (a == 0 && b == sizeof(buffer) - 1) {
- // buffer is full, flush
- buffer[b] = '\0';
- ALOG(LOG_INFO, tag, "%s", &buffer[a]);
- b = 0;
- } else if (a != b) {
- // Keep left-overs
- b -= a;
- memmove(buffer, &buffer[a], b);
- a = 0;
- } else {
- a = 0;
- b = 0;
- }
-
- }
- // Flush remaining data
- if (a != b) {
- buffer[b] = '\0';
- ALOG(LOG_INFO, tag, "%s", &buffer[a]);
- }
- status = 0xAAAA;
- if (wait(&status) != -1) { // Wait for child
- if (WIFEXITED(status)) {
- if (WEXITSTATUS(status) != 0) {
- ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
- WEXITSTATUS(status));
- }
- return WEXITSTATUS(status);
- } else if (WIFSIGNALED(status))
- ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
- WTERMSIG(status));
- else if (WIFSTOPPED(status))
- ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
- WSTOPSIG(status));
- } else
- ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
- strerror(errno), errno);
- return -EAGAIN;
-}
-
-void child(int argc, const char**argv) {
- // create null terminated argv_child array
- char* argv_child[argc + 1];
- memcpy(argv_child, argv, argc * sizeof(char *));
- argv_child[argc] = NULL;
-
- // XXX: PROTECT FROM VIKING KILLER
- if (execv(argv_child[0], argv_child)) {
- ALOG(LOG_ERROR, "logwrapper",
- "executing %s failed: %s", argv_child[0], strerror(errno));
- }
- _exit(1);
-}
-
-int logwrap(int argc, const char* argv[])
-{
- pid_t pid;
-
- int parent_ptty;
- int child_ptty;
- char child_devname[64]; // same size as libc/unistd/ptsname_r.c
-
- /* Use ptty instead of socketpair so that STDOUT is not buffered */
- parent_ptty = open("/dev/ptmx", O_RDWR);
- if (parent_ptty < 0) {
- ALOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
- return -errno;
- }
-
- if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
- ptsname_r(parent_ptty, child_devname, sizeof(child_devname))) {
- close(parent_ptty);
- ALOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
- return -1;
- }
-
- pid = fork();
- if (pid < 0) {
- close(parent_ptty);
- ALOG(LOG_ERROR, "logwrapper", "Failed to fork");
- return -errno;
- } else if (pid == 0) {
- /*
- * Child
- */
- child_ptty = open(child_devname, O_RDWR);
- if (child_ptty < 0) {
- close(parent_ptty);
- ALOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
- _exit(errno < 128 ? errno : 1); // XXX lame
- }
-
- // redirect stdout and stderr
- close(parent_ptty);
- dup2(child_ptty, 1);
- dup2(child_ptty, 2);
- close(child_ptty);
-
- child(argc, argv);
- } else {
- /*
- * Parent
- */
- int rc = parent(argv[0], parent_ptty);
- close(parent_ptty);
- return rc;
- }
-
- 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
- */
-int system_nosh(const char *command)
-{
- char buffer[255];
- char *argp[32];
- char *next = buffer;
- char *tmp;
- int i = 0;
-
- if (!command) /* just checking... */
- return(1);
-
- /*
- * The command to argp splitting is from code that was
- * reverted in Change: 11b4e9b2
- */
- if (strnlen(command, sizeof(buffer) - 1) == sizeof(buffer) - 1) {
- ALOGE("command line too long while processing: %s", command);
- errno = E2BIG;
- return -1;
- }
- strcpy(buffer, command); // Command len is already checked.
- while ((tmp = strsep(&next, " "))) {
- argp[i++] = tmp;
- if (i == 32) {
- ALOGE("argument overflow while processing: %s", command);
- errno = E2BIG;
- return -1;
- }
- }
- 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);
- sigprocmask(SIG_BLOCK, &mask, &omask);
- switch (pid = vfork()) {
- case -1: /* error */
- sigprocmask(SIG_SETMASK, &omask, NULL);
- return(-1);
- case 0: /* child */
- sigprocmask(SIG_SETMASK, &omask, NULL);
- execve(filename, argv, environ);
- _exit(127);
- }
-
- intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
- quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
- pid = waitpid(pid, (int *)&pstat, 0);
- sigprocmask(SIG_SETMASK, &omask, NULL);
- (void)bsd_signal(SIGINT, intsave);
- (void)bsd_signal(SIGQUIT, quitsave);
- return (pid == -1 ? -1 : pstat);
-}
diff --git a/oem_iptables_hook.cpp b/oem_iptables_hook.cpp
index fbf14f8..70260f3 100644
--- a/oem_iptables_hook.cpp
+++ b/oem_iptables_hook.cpp
@@ -24,31 +24,39 @@
#define LOG_TAG "OemIptablesHook"
#include <cutils/log.h>
+#include <logwrap/logwrap.h>
#include "NetdConstants.h"
-extern "C" int system_nosh(const char *command);
-
-
-static int runIptablesCmd(const char *cmd) {
- char *buffer;
- size_t len = strnlen(cmd, 255);
+static int runIptablesCmd(int argc, const char **argv) {
int res;
- if (len == 255) {
- ALOGE("command too long");
- return -1;
- }
-
- asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
- res = system_nosh(buffer);
- free(buffer);
+ res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
return res;
}
static bool oemCleanupHooks() {
- runIptablesCmd("-F oem_out");
- runIptablesCmd("-F oem_fwd");
- runIptablesCmd("-t nat -F oem_nat_pre");
+ const char *cmd1[] = {
+ IPTABLES_PATH,
+ "-F",
+ "oem_out"
+ };
+ runIptablesCmd(ARRAY_SIZE(cmd1), cmd1);
+
+ const char *cmd2[] = {
+ IPTABLES_PATH,
+ "-F",
+ "oem_fwd"
+ };
+ runIptablesCmd(ARRAY_SIZE(cmd2), cmd2);
+
+ const char *cmd3[] = {
+ IPTABLES_PATH,
+ "-t",
+ "nat",
+ "-F",
+ "oem_nat_pre"
+ };
+ runIptablesCmd(ARRAY_SIZE(cmd3), cmd3);
return true;
}