Merge change 1694 into donut

* changes:
  nexus: Flesh out VPN support a bit more, cleanup service handling
This commit is contained in:
Android (Google) Code Review 2009-05-15 10:44:22 -07:00
commit e398151e78
9 changed files with 187 additions and 165 deletions

View file

@ -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 @@ 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") {
}

View file

@ -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();

View file

@ -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;

View file

@ -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::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;
}

View file

@ -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

View file

@ -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 @@ 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;
}

View file

@ -19,6 +19,7 @@
struct wpa_ctrl;
class SupplicantListener;
class SupplicantEvent;
class ServiceManager;
#include <pthread.h>
@ -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; }

View file

@ -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 @@ 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;
}

View file

@ -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 @@ 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:
};