From 5d6d417972f8d946c223c4efb9636b1ba4280543 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Thu, 14 May 2009 15:00:06 -0700 Subject: [PATCH] nexus: Flesh out VPN support a bit more, cleanup service handling Signed-off-by: San Mehat --- nexus/CommandListener.cpp | 79 ++++++++++++++++++++++++ nexus/CommandListener.h | 14 +++++ nexus/ErrorCode.h | 3 + nexus/OpenVpnController.cpp | 88 ++++++++++----------------- nexus/OpenVpnController.h | 9 ++- nexus/Supplicant.cpp | 117 ++++++------------------------------ nexus/Supplicant.h | 5 +- nexus/VpnController.cpp | 27 +++++++-- nexus/VpnController.h | 10 +++ 9 files changed, 187 insertions(+), 165 deletions(-) diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp index d9ee971c9..fdf3fed5d 100644 --- a/nexus/CommandListener.cpp +++ b/nexus/CommandListener.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ #include +#include +#include +#include #include #define LOG_TAG "CommandListener" @@ -25,6 +28,7 @@ #include "Controller.h" #include "NetworkManager.h" #include "WifiController.h" +#include "VpnController.h" #include "ErrorCode.h" CommandListener::CommandListener() : @@ -40,6 +44,8 @@ CommandListener::CommandListener() : registerCmd(new WifiGetVarCmd()); registerCmd(new VpnEnableCmd()); + registerCmd(new VpnSetVarCmd()); + registerCmd(new VpnGetVarCmd()); registerCmd(new VpnDisableCmd()); } @@ -261,6 +267,79 @@ int CommandListener::VpnEnableCmd::runCommand(SocketClient *cli, char *data) { return 0; } +CommandListener::VpnSetVarCmd::VpnSetVarCmd() : + NexusCommand("vpn_setvar") { +} + +int CommandListener::VpnSetVarCmd::runCommand(SocketClient *cli, char *data) { + VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN"); + + char *bword; + char *last; + char varname[32]; + char val[250]; + + if (!(bword = strtok_r(data, ":", &last))) + goto out_inval; + + strncpy(varname, bword, sizeof(varname)); + + if (!(bword = strtok_r(NULL, ":", &last))) + goto out_inval; + + strncpy(val, bword, sizeof(val)); + + if (!strcasecmp(varname, "vpn_gateway")) { + if (vc->setVpnGateway(val)) + goto out_inval; + } else { + cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true); + return 0; + } + + cli->sendMsg(ErrorCode::CommandOkay, "Variable written.", false); + return 0; + +out_inval: + errno = EINVAL; + cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true); + return 0; +} + +CommandListener::VpnGetVarCmd::VpnGetVarCmd() : + NexusCommand("vpn_getvar") { +} + +int CommandListener::VpnGetVarCmd::runCommand(SocketClient *cli, char *data) { + VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN"); + + char *bword; + char *last; + char varname[32]; + + if (!(bword = strtok_r(data, ":", &last))) + goto out_inval; + + strncpy(varname, bword, sizeof(varname)); + + if (!strcasecmp(varname, "vpn_gateway")) { + char buffer[255]; + + sprintf(buffer, "%s:%s", varname, inet_ntoa(vc->getVpnGateway())); + cli->sendMsg(ErrorCode::VariableRead, buffer, false); + } else { + cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true); + return 0; + } + + cli->sendMsg(ErrorCode::CommandOkay, "Variable read.", false); + return 0; +out_inval: + errno = EINVAL; + cli->sendMsg(ErrorCode::CommandParameterError, "Failed to get variable.", true); + return 0; +} + CommandListener::VpnDisableCmd::VpnDisableCmd() : NexusCommand("vpn_disable") { } diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h index 7bc89e3f4..a44aa2905 100644 --- a/nexus/CommandListener.h +++ b/nexus/CommandListener.h @@ -95,6 +95,20 @@ private: int runCommand(SocketClient *c, char *data); }; + class VpnSetVarCmd : public NexusCommand { + public: + VpnSetVarCmd(); + virtual ~VpnSetVarCmd() {} + int runCommand(SocketClient *c, char *data); + }; + + class VpnGetVarCmd : public NexusCommand { + public: + VpnGetVarCmd(); + virtual ~VpnGetVarCmd() {} + int runCommand(SocketClient *c, char *data); + }; + class VpnDisableCmd : public NexusCommand { public: VpnDisableCmd(); diff --git a/nexus/ErrorCode.h b/nexus/ErrorCode.h index 8ca6cae58..57c99c227 100644 --- a/nexus/ErrorCode.h +++ b/nexus/ErrorCode.h @@ -26,6 +26,9 @@ public: static const int WifiScanResult = 125; static const int WifiNetworkList = 126; + static const int VariableRead = 127; + static const int VariableWrite = 128; + // 200 series - Requested action has been successfully completed static const int CommandOkay = 200; diff --git a/nexus/OpenVpnController.cpp b/nexus/OpenVpnController.cpp index eff653a8b..d326ad5df 100644 --- a/nexus/OpenVpnController.cpp +++ b/nexus/OpenVpnController.cpp @@ -14,17 +14,27 @@ * limitations under the License. */ #include +#include +#include #define LOG_TAG "OpenVpnController" #include #include +#include + #include "OpenVpnController.h" #define DAEMON_PROP_NAME "vpn.openvpn.status" +#define DAEMON_CONFIG_FILE "/data/misc/openvpn/openvpn.conf" OpenVpnController::OpenVpnController() : VpnController() { + mServiceManager = new ServiceManager(); +} + +OpenVpnController::~OpenVpnController() { + delete mServiceManager; } int OpenVpnController::start() { @@ -37,68 +47,32 @@ int OpenVpnController::stop() { int OpenVpnController::enable() { - // Validate configuration file - - // Validate key file - - if (startServiceDaemon()) - return -1; - - errno = -ENOSYS; - return -1; -} - -int OpenVpnController::startServiceDaemon() { - char status[PROPERTY_VALUE_MAX]; - int count = 100; - - property_set("ctl.start", "openvpn"); - sched_yield(); - - while (count-- > 0) { - if (property_get(DAEMON_PROP_NAME, status, NULL)) { - if (strcmp(status, "ok") == 0) - return 0; - else if (strcmp(DAEMON_PROP_NAME, "failed") == 0) - return -1; - } - usleep(200000); - } - property_set(DAEMON_PROP_NAME, "timeout"); - return -1; -} - -int OpenVpnController::stopServiceDaemon() { - char status[PROPERTY_VALUE_MAX] = {'\0'}; - int count = 50; - - if (property_get(DAEMON_PROP_NAME, status, NULL) && - !strcmp(status, "stopped")) { - LOGD("Service already stopped"); - return 0; - } - - property_set("ctl.stop", "openvpn"); - sched_yield(); - - while (count-- > 0) { - if (property_get(DAEMON_PROP_NAME, status, NULL)) { - if (!strcmp(status, "stopped")) - break; - } - usleep(100000); - } - - if (!count) { - LOGD("Timed out waiting for openvpn to stop"); - errno = ETIMEDOUT; + if (validateConfig()) { + LOGE("Error validating configuration file"); return -1; } + if (mServiceManager->start("openvpn")) + return -1; + return 0; } int OpenVpnController::disable() { - errno = -ENOSYS; - return -1; + + if (mServiceManager->stop("openvpn")) + return -1; + return 0; +} + +int OpenVpnController::validateConfig() { + unlink(DAEMON_CONFIG_FILE); + + FILE *fp = fopen(DAEMON_CONFIG_FILE, "w"); + if (!fp) + return -1; + + fprintf(fp, "remote %s 1194\n", inet_ntoa(getVpnGateway())); + fclose(fp); + return 0; } diff --git a/nexus/OpenVpnController.h b/nexus/OpenVpnController.h index 1ecc3fb3c..7bcc098f1 100644 --- a/nexus/OpenVpnController.h +++ b/nexus/OpenVpnController.h @@ -19,11 +19,15 @@ #include "VpnController.h" +class ServiceManager; + class OpenVpnController : public VpnController { +private: + ServiceManager *mServiceManager; public: OpenVpnController(); - virtual ~OpenVpnController() {} + virtual ~OpenVpnController(); int start(); int stop(); @@ -33,8 +37,7 @@ public: protected: private: - int startServiceDaemon(); - int stopServiceDaemon(); + int validateConfig(); }; #endif diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp index 22964bbc8..6737d9172 100644 --- a/nexus/Supplicant.cpp +++ b/nexus/Supplicant.cpp @@ -25,12 +25,7 @@ #include "private/android_filesystem_config.h" -#undef HAVE_LIBC_SYSTEM_PROPERTIES - -#ifdef HAVE_LIBC_SYSTEM_PROPERTIES -#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ -#include -#endif +#include #include "Supplicant.h" #include "SupplicantListener.h" @@ -44,12 +39,10 @@ #define IFACE_DIR "/data/system/wpa_supplicant" #define DRIVER_PROP_NAME "wlan.driver.status" -#define SUPPLICANT_NAME "wpa_supplicant" -#define SUPP_PROP_NAME "init.svc.wpa_supplicant" +#define SUPPLICANT_SERVICE_NAME "wpa_supplicant" #define SUPP_CONFIG_TEMPLATE "/system/etc/wifi/wpa_supplicant.conf" #define SUPP_CONFIG_FILE "/data/misc/wifi/wpa_supplicant.conf" - Supplicant::Supplicant() { mCtrl = NULL; mMonitor = NULL; @@ -57,62 +50,25 @@ Supplicant::Supplicant() { mState = SupplicantState::UNKNOWN; - mLatestScanResults = new ScanResultCollection(); + mServiceManager = new ServiceManager(); + mLatestScanResults = new ScanResultCollection(); pthread_mutex_init(&mLatestScanResultsLock, NULL); } +Supplicant::~Supplicant() { + delete mServiceManager; +} + int Supplicant::start() { if (setupConfig()) { LOGW("Unable to setup supplicant.conf"); } - - char status[PROPERTY_VALUE_MAX] = {'\0'}; - int count = 200; -#ifdef HAVE_LIBC_SYSTEM_PROPERTIES - const prop_info *pi; - unsigned int serial = 0; -#endif - - if (property_get(SUPP_PROP_NAME, status, NULL) && - !strcmp(status, "running")) { - } else { -#ifdef HAVE_LIBC_SYSTEM_PROPERTIES - pi = __system_property_find(SUPP_PROP_NAME); - if (pi != NULL) - serial = pi->serial; -#endif - - LOGD("Starting Supplicant"); - property_set("ctl.start", SUPPLICANT_NAME); - sched_yield(); - while (count--) { -#ifdef HAVE_LIBC_SYSTEM_PROPERTIES - if (!pi) - pi = __system_property_find(SUPP_PROP_NAME); - if (pi) { - __system_property_read(pi, NULL, status); - if (strcmp(status, "running") == 0) - break; - else if (pi->serial != serial && - strcmp(status, "stopped") == 0) { - errno = EIO; - return -1; - } - } -#else - if (property_get(SUPP_PROP_NAME, status, NULL)) { - if (!strcmp(status, "running")) - break; - } -#endif - usleep(100000); - } - if (!count) { - errno = ETIMEDOUT; - return -1; - } + + if (mServiceManager->start(SUPPLICANT_SERVICE_NAME)) { + LOGE("Error starting supplicant (%s)", strerror(errno)); + return -1; } wpa_ctrl_cleanup(); @@ -125,30 +81,13 @@ int Supplicant::start() { int Supplicant::stop() { - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - int count = 50; - if (mListener->stopListener()) { LOGW("Unable to stop supplicant listener (%s)", strerror(errno)); return -1; } - if (property_get(SUPP_PROP_NAME, supp_status, NULL) - && strcmp(supp_status, "stopped") == 0) { - LOGD("Supplicant already stopped"); - return 0; - } - - LOGD("Stopping Supplicant"); - property_set("ctl.stop", SUPPLICANT_NAME); - sched_yield(); - - while (count-- > 0) { - if (property_get(SUPP_PROP_NAME, supp_status, NULL)) { - if (strcmp(supp_status, "stopped") == 0) - break; - } - usleep(100000); + if (mServiceManager->stop(SUPPLICANT_SERVICE_NAME)) { + LOGW("Error stopping supplicant (%s)", strerror(errno)); } if (mCtrl) { @@ -160,35 +99,15 @@ int Supplicant::stop() { mMonitor = NULL; } - if (!count) { - LOGD("Timed out waiting for supplicant to stop"); - errno = ETIMEDOUT; - return -1; - } - - LOGD("Supplicant shutdown"); - return 0; } bool Supplicant::isStarted() { - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - - property_get(SUPP_PROP_NAME, supp_status, NULL); - - if (!strcmp(supp_status, "running")) - return true; - - return false; + return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME); } int Supplicant::connectToSupplicant() { - char ifname[256]; - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - - LOGD("connectToSupplicant()"); - if (!property_get(SUPP_PROP_NAME, supp_status, NULL) - || strcmp(supp_status, "running") != 0) { + if (!isStarted()) { LOGE("Supplicant not running, cannot connect"); return -1; } @@ -229,7 +148,7 @@ int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) return -1; } - LOGD("sendCommand(): -> '%s'", cmd); +// LOGD("sendCommand(): -> '%s'", cmd); int rc; if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2) { @@ -245,7 +164,7 @@ int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) !strncmp(cmd, "SCAN_RESULTS", 12)) reply[*reply_len] = '\0'; - LOGD("sendCommand(): <- '%s'", reply); +// LOGD("sendCommand(): <- '%s'", reply); return 0; } diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h index 4a7ec3a60..2ea0892b0 100644 --- a/nexus/Supplicant.h +++ b/nexus/Supplicant.h @@ -19,6 +19,7 @@ struct wpa_ctrl; class SupplicantListener; class SupplicantEvent; +class ServiceManager; #include @@ -31,13 +32,14 @@ private: struct wpa_ctrl *mMonitor; SupplicantListener *mListener; int mState; + ServiceManager *mServiceManager; ScanResultCollection *mLatestScanResults; pthread_mutex_t mLatestScanResultsLock; public: Supplicant(); - virtual ~Supplicant() {} + virtual ~Supplicant(); int start(); int stop(); @@ -50,7 +52,6 @@ public: int removeNetwork(int networkId); WifiNetworkCollection *createNetworkList(); - int getState() { return mState; } diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp index 17bfe4161..cd24c19eb 100644 --- a/nexus/VpnController.cpp +++ b/nexus/VpnController.cpp @@ -13,7 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include +#include +#include +#include + #include "VpnController.h" VpnController::VpnController() : @@ -21,21 +27,34 @@ VpnController::VpnController() : } int VpnController::start() { - errno = -ENOSYS; + errno = ENOSYS; return -1; } int VpnController::stop() { - errno = -ENOSYS; + errno = ENOSYS; return -1; } int VpnController::enable() { - errno = -ENOSYS; + errno = ENOSYS; return -1; } int VpnController::disable() { - errno = -ENOSYS; + errno = ENOSYS; return -1; } + +int VpnController::setVpnGateway(const char *vpnGw) { + if (!inet_aton(vpnGw, &mVpnGateway)) { + errno = EINVAL; + return -1; + } + return 0; +} + +int VpnController::setVpnGateway(struct in_addr *vpnGw) { + memcpy(&mVpnGateway, vpnGw, sizeof(struct in_addr)); + return 0; +} diff --git a/nexus/VpnController.h b/nexus/VpnController.h index 049fe6e1b..4088e6a22 100644 --- a/nexus/VpnController.h +++ b/nexus/VpnController.h @@ -16,9 +16,15 @@ #ifndef _VPN_CONTROLLER_H #define _VPN_CONTROLLER_H +#include + #include "Controller.h" class VpnController : public Controller { + /* + * Gateway of the VPN server to connect to + */ + struct in_addr mVpnGateway; public: VpnController(); @@ -30,6 +36,10 @@ public: virtual int enable(); virtual int disable(); + struct in_addr &getVpnGateway() { return mVpnGateway; } + int setVpnGateway(const char *vpnGw); + int setVpnGateway(struct in_addr *vpnGw); + protected: };