Merge change 1820
* changes:
ACC ARM codegen: Implement calling indirect functions.
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index a47f2e4..6ed5514 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -49,6 +49,7 @@
#define AID_MEDIA 1013 /* mediaserver process */
#define AID_DHCP 1014 /* dhcp client */
#define AID_SDCARD_RW 1015 /* external storage write access */
+#define AID_VPN 1016 /* vpn system */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
@@ -95,6 +96,7 @@
{ "net_bt_admin", AID_NET_BT_ADMIN, },
{ "net_bt", AID_NET_BT, },
{ "sdcard_rw", AID_SDCARD_RW, },
+ { "vpn", AID_VPN, },
{ "inet", AID_INET, },
{ "net_raw", AID_NET_RAW, },
{ "misc", AID_MISC, },
diff --git a/include/sysutils/ServiceManager.h b/include/sysutils/ServiceManager.h
new file mode 100644
index 0000000..c31dd8f
--- /dev/null
+++ b/include/sysutils/ServiceManager.h
@@ -0,0 +1,30 @@
+/*
+ * 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 _SERVICE_MANAGER_H
+#define _SERVICE_MANAGER_H
+
+class ServiceManager {
+public:
+ ServiceManager();
+ virtual ~ServiceManager() {}
+
+ int start(const char *name);
+ int stop(const char *name);
+ bool isRunning(const char *name);
+};
+
+#endif
diff --git a/init/devices.c b/init/devices.c
index 8aea772..300faab 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -131,9 +131,9 @@
{ "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
-
/* CDMA radio interface MUX */
{ "/dev/ts0710mux", 0640, AID_RADIO, AID_RADIO, 1 },
+ { "/dev/tun", 0640, AID_VPN , AID_VPN, 0 },
{ NULL, 0, 0, 0, 0 },
};
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
index 2f3e106..dd2b32d 100644
--- a/libsysutils/Android.mk
+++ b/libsysutils/Android.mk
@@ -16,6 +16,7 @@
src/NetlinkEvent.cpp \
src/FrameworkCommand.cpp \
src/SocketClient.cpp \
+ src/ServiceManager.cpp \
LOCAL_MODULE:= libsysutils
diff --git a/libsysutils/src/ServiceManager.cpp b/libsysutils/src/ServiceManager.cpp
new file mode 100644
index 0000000..700ac91
--- /dev/null
+++ b/libsysutils/src/ServiceManager.cpp
@@ -0,0 +1,73 @@
+#include <errno.h>
+
+#include <sysutils/ServiceManager.h>
+
+#define LOG_TAG "Service"
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+ServiceManager::ServiceManager() {
+}
+
+int ServiceManager::start(const char *name) {
+ if (isRunning(name)) {
+ LOGW("Service '%s' is already running", name);
+ return 0;
+ }
+
+ LOGD("Starting service '%s'", name);
+ property_set("ctl.start", name);
+
+ int count = 200;
+ while(count--) {
+ sched_yield();
+ if (isRunning(name))
+ break;
+ }
+ if (!count) {
+ LOGW("Timed out waiting for service '%s' to start", name);
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ LOGD("Sucessfully started '%s'", name);
+ return 0;
+}
+
+int ServiceManager::stop(const char *name) {
+ if (!isRunning(name)) {
+ LOGW("Service '%s' is already stopped", name);
+ return 0;
+ }
+
+ LOGD("Stopping service '%s'", name);
+ property_set("ctl.stop", name);
+
+ int count = 200;
+ while(count--) {
+ sched_yield();
+ if (!isRunning(name))
+ break;
+ }
+
+ if (!count) {
+ LOGW("Timed out waiting for service '%s' to stop", name);
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ LOGD("Sucessfully stopped '%s'", name);
+ return 0;
+}
+
+bool ServiceManager::isRunning(const char *name) {
+ char propVal[PROPERTY_VALUE_MAX];
+ char propName[255];
+
+ snprintf(propName, sizeof(propVal), "init.svc.%s", name);
+
+
+ if (property_get(propName, propVal, NULL)) {
+ if (!strcmp(propVal, "running"))
+ return true;
+ }
+ return false;
+}
diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp
index d9ee971..fdf3fed 100644
--- a/nexus/CommandListener.cpp
+++ b/nexus/CommandListener.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <errno.h>
#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 @@
registerCmd(new WifiGetVarCmd());
registerCmd(new VpnEnableCmd());
+ registerCmd(new VpnSetVarCmd());
+ registerCmd(new VpnGetVarCmd());
registerCmd(new VpnDisableCmd());
}
@@ -261,6 +267,79 @@
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 7bc89e3..a44aa29 100644
--- a/nexus/CommandListener.h
+++ b/nexus/CommandListener.h
@@ -95,6 +95,20 @@
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 8ca6cae..57c99c2 100644
--- a/nexus/ErrorCode.h
+++ b/nexus/ErrorCode.h
@@ -26,6 +26,9 @@
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 eff653a..d326ad5 100644
--- a/nexus/OpenVpnController.cpp
+++ b/nexus/OpenVpnController.cpp
@@ -14,17 +14,27 @@
* limitations under the License.
*/
#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#define LOG_TAG "OpenVpnController"
#include <cutils/log.h>
#include <cutils/properties.h>
+#include <sysutils/ServiceManager.h>
+
#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::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 1ecc3fb..7bcc098 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 @@
protected:
private:
- int startServiceDaemon();
- int stopServiceDaemon();
+ int validateConfig();
};
#endif
diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp
index 22964bb..6737d91 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 <sys/_system_properties.h>
-#endif
+#include <sysutils/ServiceManager.h>
#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 @@
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::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 @@
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 @@
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 @@
!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 4a7ec3a..2ea0892 100644
--- a/nexus/Supplicant.h
+++ b/nexus/Supplicant.h
@@ -19,6 +19,7 @@
struct wpa_ctrl;
class SupplicantListener;
class SupplicantEvent;
+class ServiceManager;
#include <pthread.h>
@@ -31,13 +32,14 @@
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 @@
int removeNetwork(int networkId);
WifiNetworkCollection *createNetworkList();
-
int getState() { return mState; }
diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp
index 17bfe41..cd24c19 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 <string.h>
#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include "VpnController.h"
VpnController::VpnController() :
@@ -21,21 +27,34 @@
}
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 049fe6e..4088e6a 100644
--- a/nexus/VpnController.h
+++ b/nexus/VpnController.h
@@ -16,9 +16,15 @@
#ifndef _VPN_CONTROLLER_H
#define _VPN_CONTROLLER_H
+#include <netinet/in.h>
+
#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 @@
virtual int enable();
virtual int disable();
+ struct in_addr &getVpnGateway() { return mVpnGateway; }
+ int setVpnGateway(const char *vpnGw);
+ int setVpnGateway(struct in_addr *vpnGw);
+
protected:
};