From 0da73fcecc30140439f856118056df8908609627 Mon Sep 17 00:00:00 2001 From: Daniel Drown Date: Wed, 20 Jun 2012 16:51:39 -0500 Subject: [PATCH] Launch android-clat via netd This patch adds the commands: "clatd start [interface]", "clatd stop", and "clatd status" Change-Id: I4b041d1f13c25108476621d2e2a1e5bac69841f5 Signed-off-by: Daniel Drown Depends-on: If2bc6916fc66fd4bca7cc241c83cfae839b82e15 --- Android.mk | 1 + ClatdController.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ClatdController.h | 32 ++++++++++++++++++ CommandListener.cpp | 45 +++++++++++++++++++++++++ CommandListener.h | 9 +++++ ResponseCode.h | 1 + 6 files changed, 185 insertions(+) create mode 100644 ClatdController.cpp create mode 100644 ClatdController.h diff --git a/Android.mk b/Android.mk index 8b7acf0..e4b6ad6 100644 --- a/Android.mk +++ b/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ BandwidthController.cpp \ + ClatdController.cpp \ CommandListener.cpp \ DnsProxyListener.cpp \ FirewallController.cpp \ diff --git a/ClatdController.cpp b/ClatdController.cpp new file mode 100644 index 0000000..ba4ca27 --- /dev/null +++ b/ClatdController.cpp @@ -0,0 +1,97 @@ +/* + * 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 +#include +#include +#include + +#define LOG_TAG "ClatdController" +#include + +#include "ClatdController.h" + +ClatdController::ClatdController() { + mClatdPid = 0; +} + +ClatdController::~ClatdController() { +} + +int ClatdController::startClatd(char *interface) { + pid_t pid; + + if(mClatdPid != 0) { + ALOGE("clatd already running"); + errno = EBUSY; + return -1; + } + + ALOGD("starting clatd"); + + if ((pid = fork()) < 0) { + ALOGE("fork failed (%s)", strerror(errno)); + return -1; + } + + if (!pid) { + char **args = (char **)malloc(sizeof(char *) * 4); + args[0] = (char *)"/system/bin/clatd"; + args[1] = (char *)"-i"; + args[2] = interface; + args[3] = NULL; + + if (execv(args[0], args)) { + ALOGE("execv failed (%s)", strerror(errno)); + } + ALOGE("Should never get here!"); + free(args); + _exit(0); + } else { + mClatdPid = pid; + ALOGD("clatd started"); + } + + return 0; +} + +int ClatdController::stopClatd() { + if (mClatdPid == 0) { + ALOGE("clatd already stopped"); + return -1; + } + + ALOGD("Stopping clatd"); + + kill(mClatdPid, SIGTERM); + waitpid(mClatdPid, NULL, 0); + mClatdPid = 0; + + ALOGD("clatd stopped"); + + return 0; +} + +bool ClatdController::isClatdStarted() { + pid_t waitpid_status; + if(mClatdPid == 0) { + return false; + } + waitpid_status = waitpid(mClatdPid, NULL, WNOHANG); + if(waitpid_status != 0) { + mClatdPid = 0; // child exited, don't call waitpid on it again + } + return waitpid_status == 0; // 0 while child is running +} diff --git a/ClatdController.h b/ClatdController.h new file mode 100644 index 0000000..f059c31 --- /dev/null +++ b/ClatdController.h @@ -0,0 +1,32 @@ +/* + * 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 _CLATD_CONTROLLER_H +#define _CLATD_CONTROLLER_H + +class ClatdController { + pid_t mClatdPid; + +public: + ClatdController(); + virtual ~ClatdController(); + + int startClatd(char *interface); + int stopClatd(); + bool isClatdStarted(); +}; + +#endif diff --git a/CommandListener.cpp b/CommandListener.cpp index 7b82682..6f81524 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -53,6 +53,7 @@ InterfaceController *CommandListener::sInterfaceCtrl = NULL; ResolverController *CommandListener::sResolverCtrl = NULL; SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL; FirewallController *CommandListener::sFirewallCtrl = NULL; +ClatdController *CommandListener::sClatdCtrl = NULL; /** * List of module chains to be created, along with explicit ordering. ORDERING @@ -136,6 +137,7 @@ CommandListener::CommandListener() : registerCmd(new IdletimerControlCmd()); registerCmd(new ResolverCmd()); registerCmd(new FirewallCmd()); + registerCmd(new ClatdCmd()); if (!sSecondaryTableCtrl) sSecondaryTableCtrl = new SecondaryTableController(); @@ -157,6 +159,8 @@ CommandListener::CommandListener() : sFirewallCtrl = new FirewallController(); if (!sInterfaceCtrl) sInterfaceCtrl = new InterfaceController(); + if (!sClatdCtrl) + sClatdCtrl = new ClatdController(); /* * This is the only time we touch top-level chains in iptables; controllers @@ -1439,3 +1443,44 @@ int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc, cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false); return 0; } + +CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") { +} + +int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc, + char **argv) { + int rc = 0; + if (argc < 2) { + cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); + return 0; + } + + if(!strcmp(argv[1], "stop")) { + rc = sClatdCtrl->stopClatd(); + } else if (!strcmp(argv[1], "status")) { + char *tmp = NULL; + + asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted() ? + "started" : "stopped")); + cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false); + free(tmp); + return 0; + } else if(!strcmp(argv[1], "start")) { + if (argc < 3) { + cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); + return 0; + } + rc = sClatdCtrl->startClatd(argv[2]); + } else { + cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false); + return 0; + } + + if (!rc) { + cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false); + } else { + cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false); + } + + return 0; +} diff --git a/CommandListener.h b/CommandListener.h index 6cae13e..e8d92a8 100644 --- a/CommandListener.h +++ b/CommandListener.h @@ -30,6 +30,7 @@ #include "ResolverController.h" #include "SecondaryTableController.h" #include "FirewallController.h" +#include "ClatdController.h" class CommandListener : public FrameworkListener { static TetherController *sTetherCtrl; @@ -42,6 +43,7 @@ class CommandListener : public FrameworkListener { static ResolverController *sResolverCtrl; static SecondaryTableController *sSecondaryTableCtrl; static FirewallController *sFirewallCtrl; + static ClatdController *sClatdCtrl; public: CommandListener(); @@ -136,6 +138,13 @@ private: int sendGenericOkFail(SocketClient *cli, int cond); static FirewallRule parseRule(const char* arg); }; + + class ClatdCmd : public NetdCommand { + public: + ClatdCmd(); + virtual ~ClatdCmd() {} + int runCommand(SocketClient *c, int argc, char ** argv); + }; }; #endif diff --git a/ResponseCode.h b/ResponseCode.h index c6f5c2d..7689ef8 100644 --- a/ResponseCode.h +++ b/ResponseCode.h @@ -44,6 +44,7 @@ public: static const int QuotaCounterResult = 220; static const int TetheringStatsResult = 221; static const int DnsProxyQueryResult = 222; + static const int ClatdStatusResult = 223; // 400 series - The command was accepted but the requested action // did not take place. -- 2.11.0