Merge change 1694 into donut
* changes: nexus: Flesh out VPN support a bit more, cleanup service handling
This commit is contained in:
commit
e398151e78
9 changed files with 187 additions and 165 deletions
|
@ -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") {
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue