diff options
-rw-r--r-- | Android.mk | 3 | ||||
-rw-r--r-- | CommandListener.cpp | 16 | ||||
-rw-r--r-- | CommandListener.h | 3 | ||||
-rw-r--r-- | NatController.cpp | 123 | ||||
-rw-r--r-- | NatController.h | 39 |
5 files changed, 174 insertions, 10 deletions
@@ -16,7 +16,8 @@ LOCAL_SRC_FILES:= \ NetlinkManager.cpp \ NetlinkHandler.cpp \ logwrapper.c \ - TetherController.cpp + TetherController.cpp \ + NatController.cpp LOCAL_MODULE:= netd diff --git a/CommandListener.cpp b/CommandListener.cpp index 56f55fbd..4bfb356a 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -31,6 +31,7 @@ #include "ResponseCode.h" TetherController *CommandListener::sTetherCtrl = NULL; +NatController *CommandListener::sNatCtrl = NULL; CommandListener::CommandListener() : FrameworkListener("netd") { @@ -41,6 +42,8 @@ CommandListener::CommandListener() : if (!sTetherCtrl) sTetherCtrl = new TetherController(); + if (!sNatCtrl) + sNatCtrl = new NatController(); } CommandListener::ListInterfacesCmd::ListInterfacesCmd() : @@ -196,15 +199,10 @@ int CommandListener::NatCmd::runCommand(SocketClient *cli, return 0; } - if (!strcmp(argv[1], "binding")) { - if (!strcmp(argv[2], "add")) { - rc = 0; - } else if (!strcmp(argv[2], "remove")) { - rc = 0; - } else { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat binding cmd", false); - return 0; - } + if (!strcmp(argv[1], "enable")) { + rc = sNatCtrl->enableNat(argv[2], argv[3]); + } else if (!strcmp(argv[1], "disable")) { + rc = sNatCtrl->disableNat(argv[2], argv[3]); } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false); return 0; diff --git a/CommandListener.h b/CommandListener.h index 1ec65ae6..3d69ebad 100644 --- a/CommandListener.h +++ b/CommandListener.h @@ -18,11 +18,14 @@ #define _COMMANDLISTENER_H__ #include <sysutils/FrameworkListener.h> + #include "NetdCommand.h" #include "TetherController.h" +#include "NatController.h" class CommandListener : public FrameworkListener { static TetherController *sTetherCtrl; + static NatController *sNatCtrl; public: CommandListener(); diff --git a/NatController.cpp b/NatController.cpp new file mode 100644 index 00000000..3539844f --- /dev/null +++ b/NatController.cpp @@ -0,0 +1,123 @@ +/* + * 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 <sys/socket.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#define LOG_TAG "NatController" +#include <cutils/log.h> + +#include "NatController.h" + +extern "C" int logwrap(int argc, const char **argv, int background); + +static char IPTABLES_PATH[] = "/system/bin/iptables"; + +NatController::NatController() { +} + +NatController::~NatController() { +} + +int NatController::runIptablesCmd(const char *cmd) { + char buffer[255]; + + strncpy(buffer, cmd, sizeof(buffer)-1); + + const char *args[16]; + char *next = buffer; + char *tmp; + + args[0] = IPTABLES_PATH; + args[1] = "--verbose"; + int i = 2; + + while ((tmp = strsep(&next, " "))) { + args[i++] = tmp; + if (i == 16) { + LOGE("iptables argument overflow"); + errno = E2BIG; + return -1; + } + } + args[i] = NULL; + + return logwrap(i, args, 0); +} + +int NatController::setDefaults() { + + if (runIptablesCmd("-P INPUT ACCEPT")) + return -1; + if (runIptablesCmd("-F INPUT")) + return -1; + if (runIptablesCmd("-P OUTPUT ACCEPT")) + return -1; + if (runIptablesCmd("-F OUTPUT")) + return -1; + if (runIptablesCmd("-P FORWARD DROP")) + return -1; + if (runIptablesCmd("-F FORWARD")) + return -1; + if (runIptablesCmd("-t nat -F")) + return -1; + return 0; +} + +bool NatController::interfaceExists(const char *iface) { + // XXX: STOPSHIP - Implement this + return true; +} + +// TODO: Make this work for multiple masqueraded networks +int NatController::enableNat(const char *intIface, const char *extIface) { + char cmd[255]; + + if (!interfaceExists(intIface) || !interfaceExists (extIface)) { + LOGE("Invalid interface specified"); + errno = ENODEV; + return -1; + } + + snprintf(cmd, sizeof(cmd), + "-A FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", + extIface, intIface); + if (runIptablesCmd(cmd)) { + return -1; + } + + snprintf(cmd, sizeof(cmd), "-A FORWARD -i %s -o %s -j ACCEPT", intIface, extIface); + if (runIptablesCmd(cmd)) { + return -1; + } + + snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface); + if (runIptablesCmd(cmd)) { + return -1; + } + + return 0; +} + +// TODO: Make this work for multiple masqueraded networks +int NatController::disableNat(const char *intIface, const char *extIface) { + return setDefaults(); +} diff --git a/NatController.h b/NatController.h new file mode 100644 index 00000000..4182f1d1 --- /dev/null +++ b/NatController.h @@ -0,0 +1,39 @@ +/* + * 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 _NAT_CONTROLLER_H +#define _NAT_CONTROLLER_H + +#include <linux/in.h> + +#include <utils/List.h> + +class NatController { + +public: + NatController(); + virtual ~NatController(); + + int enableNat(const char *intIface, const char *extIface); + int disableNat(const char *intIface, const char *extIface); + +private: + int setDefaults(); + int runIptablesCmd(const char *cmd); + bool interfaceExists(const char *iface); +}; + +#endif |