Bug fixes:
- auto install tap - share connectionState - service crash fix
This commit is contained in:
parent
a50cdd5bc2
commit
953eca6695
25 changed files with 919 additions and 89 deletions
|
|
@ -6,11 +6,17 @@
|
|||
#include "localserver.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "router.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "tapcontroller_win.h"
|
||||
#endif
|
||||
|
||||
LocalServer::LocalServer(QObject *parent) : QObject(parent),
|
||||
m_clientConnection(nullptr),
|
||||
m_clientConnected(false)
|
||||
{
|
||||
m_server = new QLocalServer(this);
|
||||
m_server = QSharedPointer<QLocalServer>(new QLocalServer(this));
|
||||
m_server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
|
||||
if (!m_server->listen(Utils::serverName())) {
|
||||
|
|
@ -18,7 +24,7 @@ LocalServer::LocalServer(QObject *parent) : QObject(parent),
|
|||
return;
|
||||
}
|
||||
|
||||
connect(m_server, &QLocalServer::newConnection, this, &LocalServer::onNewConnection);
|
||||
connect(m_server.data(), &QLocalServer::newConnection, this, &LocalServer::onNewConnection);
|
||||
|
||||
qDebug().noquote() << QString("Local server started on '%1'").arg(m_server->serverName());
|
||||
}
|
||||
|
|
@ -68,9 +74,16 @@ void LocalServer::onNewConnection()
|
|||
qWarning().noquote() << "Message is not valid!";
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
qDebug().noquote() << QString("Got message id: '%1'").arg(static_cast<int>(incomingMessage.state()));
|
||||
//qDebug().noquote() << incomingMessage.rawData();
|
||||
}
|
||||
|
||||
switch (incomingMessage.state()) {
|
||||
case Message::State::Initialize:
|
||||
#ifdef Q_OS_WIN
|
||||
TapController::Instance().checkAndSetup();
|
||||
#endif
|
||||
sendMessage(Message(Message::State::Initialize, QStringList({"Server"})));
|
||||
break;
|
||||
case Message::State::StartRequest:
|
||||
|
|
@ -79,6 +92,23 @@ void LocalServer::onNewConnection()
|
|||
case Message::State::FinishRequest:
|
||||
finishProcess(incomingMessage.args());
|
||||
break;
|
||||
|
||||
case Message::State::RoutesAddRequest:
|
||||
routesAddRequest(incomingMessage.args());
|
||||
break;
|
||||
case Message::State::RouteDeleteRequest:
|
||||
routeDeleteRequest(incomingMessage.args());
|
||||
break;
|
||||
case Message::State::ClearSavedRoutesRequest:
|
||||
Router::Instance().clearSavedRoutes();
|
||||
break;
|
||||
case Message::State::FlushDnsRequest:
|
||||
Router::Instance().flushDns();
|
||||
break;
|
||||
case Message::State::InstallDriverRequest:
|
||||
checkAndInstallDriver(incomingMessage.args());
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
|
@ -128,6 +158,21 @@ void LocalServer::startProcess(const QStringList& messageArgs)
|
|||
m_processList.append(process);
|
||||
}
|
||||
|
||||
void LocalServer::routesAddRequest(const QStringList &messageArgs)
|
||||
{
|
||||
Router::Instance().routeAddList(messageArgs.first(), messageArgs.mid(1));
|
||||
}
|
||||
|
||||
void LocalServer::routeDeleteRequest(const QStringList &messageArgs)
|
||||
{
|
||||
Router::Instance().routeDelete(messageArgs.first());
|
||||
}
|
||||
|
||||
void LocalServer::checkAndInstallDriver(const QStringList &messageArgs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LocalServer::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
Q_UNUSED(exitStatus)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
#define LOCALSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QProcess>
|
||||
#include <QSharedPointer>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
|
|
@ -34,8 +36,14 @@ private:
|
|||
void sendMessage(const Message& message);
|
||||
void startProcess(const QStringList& messageArgs);
|
||||
|
||||
QLocalServer* m_server;
|
||||
QLocalSocket* m_clientConnection;
|
||||
void routesAddRequest(const QStringList& messageArgs);
|
||||
void routeDeleteRequest(const QStringList& messageArgs);
|
||||
|
||||
void checkAndInstallDriver(const QStringList& messageArgs);
|
||||
|
||||
QSharedPointer<QLocalServer> m_server;
|
||||
QPointer <QLocalSocket> m_clientConnection;
|
||||
|
||||
QVector<QProcess*> m_processList;
|
||||
bool m_clientConnected;
|
||||
};
|
||||
|
|
|
|||
327
service/server/router.cpp
Normal file
327
service/server/router.cpp
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
#include "router.h"
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
|
||||
Router &Router::Instance()
|
||||
{
|
||||
static Router s;
|
||||
return s;
|
||||
}
|
||||
|
||||
bool Router::routeAdd(const QString &ip, const QString &gw, QString mask)
|
||||
{
|
||||
qDebug().noquote() << QString("ROUTE ADD: IP:%1 %2 GW %3")
|
||||
.arg(ip)
|
||||
.arg(mask)
|
||||
.arg(gw);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (mask == "") {
|
||||
mask = "255.255.255.255";
|
||||
if (ip.endsWith(".0")) mask = "255.255.255.0";
|
||||
if (ip.endsWith(".0.0")) mask = "255.255.0.0";
|
||||
if (ip.endsWith(".0.0.0")) mask = "255.0.0.0";
|
||||
}
|
||||
|
||||
|
||||
PMIB_IPFORWARDTABLE pIpForwardTable = NULL;
|
||||
MIB_IPFORWARDROW ipfrow;
|
||||
DWORD dwSize = 0;
|
||||
BOOL bOrder = FALSE;
|
||||
DWORD dwStatus = 0;
|
||||
|
||||
|
||||
// Find out how big our buffer needs to be.
|
||||
dwStatus = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
|
||||
if (dwStatus == ERROR_INSUFFICIENT_BUFFER) {
|
||||
// Allocate the memory for the table
|
||||
if (!(pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc(dwSize))) {
|
||||
qDebug() << "Malloc failed. Out of memory.";
|
||||
return false;
|
||||
}
|
||||
// Now get the table.
|
||||
dwStatus = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
|
||||
}
|
||||
|
||||
|
||||
if (dwStatus != ERROR_SUCCESS) {
|
||||
qDebug() << "getIpForwardTable failed.";
|
||||
if (pIpForwardTable)
|
||||
free(pIpForwardTable);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set iface for route
|
||||
IPAddr dwGwAddr = inet_addr(gw.toStdString().c_str());
|
||||
if (GetBestInterface(dwGwAddr, &ipfrow.dwForwardIfIndex) != NO_ERROR) {
|
||||
qDebug() << "Router::routeAdd : GetBestInterface failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// address
|
||||
ipfrow.dwForwardDest = inet_addr(ip.toStdString().c_str());
|
||||
|
||||
// mask
|
||||
in_addr maskAddr;
|
||||
inet_pton(AF_INET, mask.toStdString().c_str(), &maskAddr);
|
||||
ipfrow.dwForwardMask = maskAddr.S_un.S_addr;
|
||||
|
||||
// Get TAP iface metric to set it for new routes
|
||||
MIB_IPINTERFACE_ROW tap_iface;
|
||||
InitializeIpInterfaceEntry(&tap_iface);
|
||||
tap_iface.InterfaceIndex = ipfrow.dwForwardIfIndex;
|
||||
tap_iface.Family = AF_INET;
|
||||
dwStatus = GetIpInterfaceEntry(&tap_iface);
|
||||
if (dwStatus == NO_ERROR){
|
||||
ipfrow.dwForwardMetric1 = tap_iface.Metric;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Router::routeAdd: failed GetIpInterfaceEntry(), Error:" << dwStatus;
|
||||
ipfrow.dwForwardMetric1 = 256;
|
||||
}
|
||||
ipfrow.dwForwardMetric2 = 0;
|
||||
ipfrow.dwForwardMetric3 = 0;
|
||||
ipfrow.dwForwardMetric4 = 0;
|
||||
ipfrow.dwForwardMetric5 = 0;
|
||||
|
||||
ipfrow.dwForwardAge = 0;
|
||||
|
||||
ipfrow.dwForwardNextHop = inet_addr(gw.toStdString().c_str());
|
||||
ipfrow.dwForwardType = 4; /* XXX - next hop != final dest */
|
||||
ipfrow.dwForwardProto = 3; /* XXX - MIB_PROTO_NETMGMT */
|
||||
|
||||
|
||||
dwStatus = CreateIpForwardEntry(&ipfrow);
|
||||
if (dwStatus == NO_ERROR){
|
||||
ipForwardRows.append(ipfrow);
|
||||
//qDebug() << "Gateway changed successfully";
|
||||
}
|
||||
else {
|
||||
qDebug() << "Router::routeAdd: failed CreateIpForwardEntry()";
|
||||
qDebug() << "Error: " << dwStatus;
|
||||
}
|
||||
|
||||
// Free resources
|
||||
if (pIpForwardTable)
|
||||
free(pIpForwardTable);
|
||||
|
||||
return (dwStatus == NO_ERROR);
|
||||
#else
|
||||
// Not implemented yet
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int Router::routeAddList(const QString &gw, const QStringList &ips)
|
||||
{
|
||||
qDebug().noquote() << QString("ROUTE ADD List: IPs size:%1, GW: %2")
|
||||
.arg(ips.size())
|
||||
.arg(gw);
|
||||
|
||||
qDebug().noquote() << QString("ROUTE ADD List: IPs:\n%1")
|
||||
.arg(ips.join("\n"));
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
PMIB_IPFORWARDTABLE pIpForwardTable = NULL;
|
||||
DWORD dwSize = 0;
|
||||
BOOL bOrder = FALSE;
|
||||
DWORD dwStatus = 0;
|
||||
|
||||
|
||||
// Find out how big our buffer needs to be.
|
||||
dwStatus = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
|
||||
if (dwStatus == ERROR_INSUFFICIENT_BUFFER) {
|
||||
// Allocate the memory for the table
|
||||
if (!(pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc(dwSize))) {
|
||||
qDebug() << "Malloc failed. Out of memory.";
|
||||
return 0;
|
||||
}
|
||||
// Now get the table.
|
||||
dwStatus = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
|
||||
}
|
||||
|
||||
|
||||
if (dwStatus != ERROR_SUCCESS) {
|
||||
qDebug() << "getIpForwardTable failed.";
|
||||
if (pIpForwardTable)
|
||||
free(pIpForwardTable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int success_count = 0;
|
||||
|
||||
|
||||
|
||||
QString mask;
|
||||
|
||||
MIB_IPFORWARDROW ipfrow;
|
||||
|
||||
|
||||
ipfrow.dwForwardPolicy = 0;
|
||||
ipfrow.dwForwardAge = 0;
|
||||
|
||||
ipfrow.dwForwardNextHop = inet_addr(gw.toStdString().c_str());
|
||||
ipfrow.dwForwardType = 4; /* XXX - next hop != final dest */
|
||||
ipfrow.dwForwardProto = 3; /* XXX - MIB_PROTO_NETMGMT */
|
||||
|
||||
|
||||
// Set iface for route
|
||||
IPAddr dwGwAddr = inet_addr(gw.toStdString().c_str());
|
||||
if (GetBestInterface(dwGwAddr, &ipfrow.dwForwardIfIndex) != NO_ERROR) {
|
||||
qDebug() << "Router::routeAddList : GetBestInterface failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get TAP iface metric to set it for new routes
|
||||
MIB_IPINTERFACE_ROW tap_iface;
|
||||
InitializeIpInterfaceEntry(&tap_iface);
|
||||
tap_iface.InterfaceIndex = ipfrow.dwForwardIfIndex;
|
||||
tap_iface.Family = AF_INET;
|
||||
dwStatus = GetIpInterfaceEntry(&tap_iface);
|
||||
if (dwStatus == NO_ERROR){
|
||||
ipfrow.dwForwardMetric1 = tap_iface.Metric;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Router::routeAddList: failed GetIpInterfaceEntry(), Error:" << dwStatus;
|
||||
ipfrow.dwForwardMetric1 = 256;
|
||||
}
|
||||
ipfrow.dwForwardMetric2 = 0;
|
||||
ipfrow.dwForwardMetric3 = 0;
|
||||
ipfrow.dwForwardMetric4 = 0;
|
||||
ipfrow.dwForwardMetric5 = 0;
|
||||
|
||||
for (int i = 0; i < ips.size(); ++i) {
|
||||
QString ip = ips.at(i);
|
||||
if (ip.isEmpty()) continue;
|
||||
|
||||
mask = "255.255.255.255";
|
||||
if (ip.endsWith(".0")) mask = "255.255.255.0";
|
||||
if (ip.endsWith(".0.0")) mask = "255.255.0.0";
|
||||
if (ip.endsWith(".0.0.0")) mask = "255.0.0.0";
|
||||
|
||||
// address
|
||||
ipfrow.dwForwardDest = inet_addr(ip.toStdString().c_str());
|
||||
|
||||
|
||||
// mask
|
||||
in_addr maskAddr;
|
||||
inet_pton(AF_INET, mask.toStdString().c_str(), &maskAddr);
|
||||
ipfrow.dwForwardMask = maskAddr.S_un.S_addr;
|
||||
|
||||
dwStatus = CreateIpForwardEntry(&ipfrow);
|
||||
if (dwStatus == NO_ERROR){
|
||||
ipForwardRows.append(ipfrow);
|
||||
//qDebug() << "Gateway changed successfully";
|
||||
}
|
||||
else {
|
||||
qDebug() << "Router::routeAdd: failed CreateIpForwardEntry(), Error:" << ip << dwStatus;
|
||||
}
|
||||
|
||||
if (dwStatus == NO_ERROR) success_count++;
|
||||
}
|
||||
|
||||
|
||||
// Free resources
|
||||
if (pIpForwardTable)
|
||||
free(pIpForwardTable);
|
||||
|
||||
qDebug() << "Router::routeAddList finished, success: " << success_count << "/" << ips.size();
|
||||
return success_count;
|
||||
#else
|
||||
// Not implemented yet
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Router::clearSavedRoutes()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
if (ipForwardRows.isEmpty()) return true;
|
||||
|
||||
qDebug() << "forward rows size:" << ipForwardRows.size();
|
||||
|
||||
// Declare and initialize variables
|
||||
PMIB_IPFORWARDTABLE pIpForwardTable = NULL;
|
||||
DWORD dwSize = 0;
|
||||
BOOL bOrder = FALSE;
|
||||
DWORD dwStatus = 0;
|
||||
|
||||
// Find out how big our buffer needs to be.
|
||||
dwStatus = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
|
||||
if (dwStatus == ERROR_INSUFFICIENT_BUFFER) {
|
||||
// Allocate the memory for the table
|
||||
if (!(pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc(dwSize))) {
|
||||
qDebug() << "Router::clearSavedRoutes : Malloc failed. Out of memory";
|
||||
return false;
|
||||
}
|
||||
// Now get the table.
|
||||
dwStatus = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
|
||||
}
|
||||
|
||||
if (dwStatus != ERROR_SUCCESS) {
|
||||
qDebug() << "Router::clearSavedRoutes : getIpForwardTable failed";
|
||||
if (pIpForwardTable)
|
||||
free(pIpForwardTable);
|
||||
return false;
|
||||
}
|
||||
|
||||
int removed_count = 0;
|
||||
for (int i = 0; i < ipForwardRows.size(); ++i) {
|
||||
dwStatus = DeleteIpForwardEntry(&ipForwardRows[i]);
|
||||
|
||||
if (dwStatus != ERROR_SUCCESS) {
|
||||
qDebug() << "Router::clearSavedRoutes : Could not delete old row" << i;
|
||||
}
|
||||
else removed_count++;
|
||||
}
|
||||
|
||||
if (pIpForwardTable)
|
||||
free(pIpForwardTable);
|
||||
|
||||
qDebug() << "Router::clearSavedRoutes : removed routes:" << removed_count << "of" << ipForwardRows.size();
|
||||
ipForwardRows.clear();
|
||||
|
||||
return true;
|
||||
#else
|
||||
// Not implemented yet
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Router::routeDelete(const QString &ip)
|
||||
{
|
||||
qDebug().noquote() << QString("ROUTE DELETE, IP: %1").arg(ip);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QProcess p;
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
QString command = QString("route delete %1")
|
||||
.arg(ip);
|
||||
|
||||
p.start(command);
|
||||
p.waitForFinished();
|
||||
qDebug().noquote() << "OUTPUT route delete: " + p.readAll();
|
||||
|
||||
return true;
|
||||
#else
|
||||
// Not implemented yet
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Router::flushDns()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QProcess p;
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
QString command = QString("ipconfig /flushdns");
|
||||
|
||||
p.start(command);
|
||||
p.waitForFinished();
|
||||
//qDebug().noquote() << "OUTPUT ipconfig /flushdns: " + p.readAll();
|
||||
#endif
|
||||
}
|
||||
60
service/server/router.h
Normal file
60
service/server/router.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef ROUTER_H
|
||||
#define ROUTER_H
|
||||
|
||||
#include <QTimer>
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
#include <QHash>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <WinSock2.h> //includes Windows.h
|
||||
#include <WS2tcpip.h>
|
||||
|
||||
|
||||
#include <iphlpapi.h>
|
||||
#include <IcmpAPI.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
typedef uint8_t u8_t ;
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
|
||||
#endif //Q_OS_WIN
|
||||
|
||||
|
||||
/**
|
||||
* @brief The Router class - General class for handling ip routing
|
||||
*/
|
||||
class Router : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static Router& Instance();
|
||||
|
||||
bool routeAdd(const QString &ip, const QString &gw, QString mask = QString());
|
||||
int routeAddList(const QString &gw, const QStringList &ips);
|
||||
bool clearSavedRoutes();
|
||||
bool routeDelete(const QString &ip);
|
||||
void flushDns();
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
Router() {}
|
||||
Router(Router const &) = delete;
|
||||
Router& operator= (Router const&) = delete;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QList<MIB_IPFORWARDROW> ipForwardRows;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // ROUTER_H
|
||||
|
|
@ -8,6 +8,7 @@ HEADERS = \
|
|||
../../client/utils.h \
|
||||
localserver.h \
|
||||
log.h \
|
||||
router.h \
|
||||
systemservice.h
|
||||
|
||||
SOURCES = \
|
||||
|
|
@ -16,8 +17,26 @@ SOURCES = \
|
|||
localserver.cpp \
|
||||
log.cpp \
|
||||
main.cpp \
|
||||
router.cpp \
|
||||
systemservice.cpp
|
||||
|
||||
win32 {
|
||||
HEADERS += \
|
||||
tapcontroller_win.h
|
||||
|
||||
SOURCES += \
|
||||
tapcontroller_win.cpp
|
||||
|
||||
LIBS += \
|
||||
-luser32 \
|
||||
-lrasapi32 \
|
||||
-lshlwapi \
|
||||
-liphlpapi \
|
||||
-lws2_32 \
|
||||
-liphlpapi \
|
||||
-lgdi32
|
||||
}
|
||||
|
||||
include(../src/qtservice.pri)
|
||||
|
||||
#CONFIG(release, debug|release) {
|
||||
|
|
|
|||
364
service/server/tapcontroller_win.cpp
Normal file
364
service/server/tapcontroller_win.cpp
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
#include <QProcess>
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatchIterator>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "tapcontroller_win.h"
|
||||
|
||||
#define TAP_EXE_ERROR { \
|
||||
qDebug() << "TapController: Can't start tapinstall.exe"; \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define TAP_NO_MATCHING_DEVICES_ERROR { \
|
||||
qDebug() << "TapController: No matching devices found"; \
|
||||
return false; \
|
||||
}
|
||||
|
||||
TapController &TapController::Instance()
|
||||
{
|
||||
static TapController s;
|
||||
return s;
|
||||
}
|
||||
|
||||
TapController::TapController()
|
||||
{
|
||||
}
|
||||
|
||||
bool TapController::checkInstaller()
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "/?");
|
||||
if(!tapInstallProc.waitForStarted()) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
bool TapController::enableTapAdapter(const QString &tapInstanceId)
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "enable" << QString("@") + tapInstanceId);
|
||||
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
QString output = QString(tapInstallProc.readAll());
|
||||
if (! output.contains("are enabled")) {
|
||||
qDebug() << "TapController: Failed to enable tap device";
|
||||
return false;
|
||||
}
|
||||
if (output.contains("No matching devices ")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
||||
|
||||
qDebug() << "Enabled TAP Instance id:" << tapInstanceId;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TapController::disableTapAdapter(const QString &tapInstanceId)
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "disable" << QString("@") + tapInstanceId);
|
||||
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
QString output = QString(tapInstallProc.readAll());
|
||||
if (! output.contains("disabled")) {
|
||||
qDebug() << "TapController: Failed to disable tap device";
|
||||
return false;
|
||||
}
|
||||
if (output.contains("No matching devices ")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
||||
|
||||
qDebug() << "Disabled TAP Instance id:" << tapInstanceId;
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList TapController::getTapList()
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "find" << "tap0901" );
|
||||
if(!tapInstallProc.waitForStarted()) {
|
||||
qDebug() << "TapController: TapController: Can't start tapinstall.exe";
|
||||
return QStringList();
|
||||
}
|
||||
tapInstallProc.waitForFinished();
|
||||
QString output = QString( tapInstallProc.readAll() );
|
||||
output.replace("\r", "");
|
||||
if (output.contains("No matched devices found")) {
|
||||
qDebug() << "TapController: No matching device instances found";
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList l = output.split("\n", QString::SkipEmptyParts);
|
||||
if (l.size() > 0) l.removeLast();
|
||||
|
||||
QStringList tapList;
|
||||
for (QString s : l) {
|
||||
if (s.contains(" ")) tapList.append(s.split(" ", QString::SkipEmptyParts).first());
|
||||
else tapList.append(s);
|
||||
}
|
||||
|
||||
return tapList;
|
||||
}
|
||||
|
||||
bool TapController::checkAndSetup()
|
||||
{
|
||||
qDebug().noquote() << "OpenVPN path" << getOpenVpnPath();
|
||||
qDebug().noquote() << "TapInstall path" << getTapInstallPath();
|
||||
qDebug().noquote() << "TapDriverDir path" << getTapDriverDir();
|
||||
//////////////////////////////////////////////
|
||||
/// Check if OpenVPN executable ready for use
|
||||
bool isOpenVpnExeExist = checkOpenVpn();
|
||||
if (!isOpenVpnExeExist) {
|
||||
qDebug() << "TapController::checkAndSetup :::: openvpn.exe not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// Check if any TAP adapter ready for use
|
||||
bool isAnyAvailableTap = false;
|
||||
QStringList tapList = getTapList();
|
||||
for (const QString &tap : tapList) {
|
||||
qDebug() << "TapController: Found TAP device" << tap << ", checking...";
|
||||
if (checkDriver(tap)) {
|
||||
isAnyAvailableTap = true;
|
||||
qDebug() << "TapController: Device" << tap << "is ready for using";
|
||||
}
|
||||
else
|
||||
qDebug() << "TapController: Device" << tap << "is NOT ready for using";
|
||||
}
|
||||
|
||||
if (isAnyAvailableTap) {
|
||||
qDebug() << "TapController: Check success, found usable TAP adapter";
|
||||
return true;
|
||||
}
|
||||
else qDebug() << "TapController: Check failed, usable TAP adapter NOT found";
|
||||
|
||||
/// Try to setup driver if it's not installed
|
||||
qDebug() << "TapController: Installing TAP driver...";
|
||||
bool ok = setupDriver();
|
||||
|
||||
if (ok) qDebug() << "TapController: TAP driver successfully installed";
|
||||
else qDebug() << "TapController: Failed to install TAP driver";
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool TapController::checkDriver(const QString& tapInstanceId)
|
||||
{
|
||||
/// Check for driver nodes
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "drivernodes" << QString("@") + tapInstanceId);
|
||||
if (!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
||||
tapInstallProc.waitForFinished(1000);
|
||||
|
||||
QString output = QString(tapInstallProc.readAll());
|
||||
if (output.contains("No driver nodes found")) {
|
||||
qDebug() << "TapController: No driver nodes found";
|
||||
return false;
|
||||
}
|
||||
if (output.contains("No matching devices")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
||||
}
|
||||
|
||||
|
||||
/// Check for files
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "driverfiles" << QString("@") + tapInstanceId);
|
||||
if (!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
||||
tapInstallProc.waitForFinished(1000);
|
||||
|
||||
QString output = QString(tapInstallProc.readAll());
|
||||
if (output.contains("No driver information")) {
|
||||
qDebug() << "TapController: No driver information";
|
||||
return false;
|
||||
}
|
||||
if (output.contains("No matching devices")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
||||
}
|
||||
|
||||
/// Check if network adapter enabled
|
||||
bool isDisabled = false;
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "status" << QString("@") + tapInstanceId);
|
||||
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
QString output = QString(tapInstallProc.readAll());
|
||||
output.replace("\r", "");
|
||||
|
||||
if (output.contains("No matching devices ")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
||||
|
||||
if (output.contains("is running")) {
|
||||
qDebug() << "TapController: Device" << tapInstanceId << "is active and ready";
|
||||
//return true;
|
||||
}
|
||||
else if (output.contains("is disabled")) isDisabled = true;
|
||||
else {
|
||||
qDebug() << "TapController: Device" << tapInstanceId << "is in unknown state";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable adapter if enabled
|
||||
if (!isDisabled) {
|
||||
qDebug() << "TapController: Device" << tapInstanceId << "is enabled. Disabling before use...";
|
||||
if (!disableTapAdapter(tapInstanceId)) return false;
|
||||
}
|
||||
|
||||
/// Enable adapter
|
||||
{
|
||||
qDebug() << "TapController: Device" << tapInstanceId << "is disabled. Enabling...";
|
||||
if (!enableTapAdapter(tapInstanceId)) return false;
|
||||
}
|
||||
|
||||
/// Check again
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "status" << QString("@") + tapInstanceId);
|
||||
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
QString output = QString(tapInstallProc.readAll());
|
||||
|
||||
if (output.contains("is running")) return true;
|
||||
else {
|
||||
qDebug() << "TapController: tap device final check failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool TapController::checkOpenVpn()
|
||||
{
|
||||
/// Check openvpn executable
|
||||
|
||||
QProcess openVpnProc;
|
||||
openVpnProc.start(getOpenVpnPath(), QStringList() << "--version");
|
||||
if (!openVpnProc.waitForStarted()) {
|
||||
qDebug() << "TapController: openvpn.exe NOT found";
|
||||
return false;
|
||||
}
|
||||
openVpnProc.waitForFinished(1000);
|
||||
|
||||
QString output = QString(openVpnProc.readAll());
|
||||
output.replace("\r", "");
|
||||
qDebug() << "TapController: openvpn.exe found, version:" << output;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString TapController::getTapInstallPath()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return qApp->applicationDirPath() + "\\tap\\"+ QSysInfo::currentCpuArchitecture() + "\\tapinstall.exe";
|
||||
// if (QSysInfo::currentCpuArchitecture() == "i386") {
|
||||
// return qApp->applicationDirPath() + "\\openvpn\\drivers_x32\\tapinstall.exe";
|
||||
// }
|
||||
// else if (QSysInfo::currentCpuArchitecture() == "x86_64") {
|
||||
// return qApp->applicationDirPath() + "\\openvpn\\drivers_x64\\tapinstall.exe";
|
||||
// }
|
||||
// else return "";
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
QString TapController::getOpenVpnPath()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
//return qApp->applicationDirPath() + "\\openvpn\\"+ QSysInfo::currentCpuArchitecture() + "\\openvpn.exe";
|
||||
return qApp->applicationDirPath() + "\\openvpn\\i386\\openvpn.exe";
|
||||
|
||||
//return qApp->applicationDirPath() + "\\openvpn\\bin\\openvpn.exe";
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
QString TapController::getTapDriverDir()
|
||||
{
|
||||
return qApp->applicationDirPath() + "\\tap\\"+ QSysInfo::currentCpuArchitecture() + "\\";
|
||||
|
||||
// if (QSysInfo::currentCpuArchitecture() == "i386") {
|
||||
// return qApp->applicationDirPath() + "\\openvpn\\drivers_x32\\";
|
||||
// }
|
||||
// else if (QSysInfo::currentCpuArchitecture() == "x86_64") {
|
||||
// return qApp->applicationDirPath() + "\\openvpn\\drivers_x64\\";
|
||||
// }
|
||||
// else return "";
|
||||
}
|
||||
|
||||
bool TapController::removeDriver(const QString& tapInstanceId)
|
||||
{
|
||||
/// remove tap by instance id
|
||||
{
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "remove" << QString("@") + tapInstanceId);
|
||||
if(!tapInstallProc.waitForStarted()) return false;
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
QString output = QString( tapInstallProc.readAll() );
|
||||
if (output.contains("were removed")) {
|
||||
qDebug() << "TAP device" << tapInstanceId << "suceccfully removed";
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Unable to remove TAP device" << tapInstanceId;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TapController::setupDriver()
|
||||
{
|
||||
//setupDriverCertificate();
|
||||
|
||||
QStringList tapList = getTapList();
|
||||
for (QString tap : tapList) {
|
||||
if (! checkDriver(tap)) removeDriver(tap);
|
||||
}
|
||||
tapList = getTapList();
|
||||
if (! tapList.isEmpty()) {
|
||||
qDebug() << "TapController: setupDriver :::: Found drivers count" << tapList.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// else try to install driver
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start(getTapInstallPath(), QStringList() << "install" << getTapDriverDir() + "OemVista.inf" << "tap0901");
|
||||
bool ok = tapInstallProc.waitForStarted();
|
||||
if (!ok) {
|
||||
qDebug() << "TapController: setupDriver failer to start tapInstallProc" << tapInstallProc.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
qDebug() << "TapController: setupDriver args" << tapInstallProc.arguments().join(" ");
|
||||
qDebug() << "TapController: setupDriver output" << tapInstallProc.readAll();
|
||||
|
||||
/// check again
|
||||
tapList = getTapList();
|
||||
for (QString tap : tapList) {
|
||||
if (! checkDriver(tap)) removeDriver(tap);
|
||||
}
|
||||
tapList = getTapList();
|
||||
if (!tapList.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool TapController::setupDriverCertificate()
|
||||
{
|
||||
QString cert = getTapDriverDir() + "\\OpenVPN.cer";
|
||||
QProcess tapInstallProc;
|
||||
tapInstallProc.start("certutil" , QStringList() << "-addstore" << "-f" << "trustedpublisher" << cert);
|
||||
|
||||
tapInstallProc.waitForFinished();
|
||||
|
||||
QString certOutput = QString(tapInstallProc.readAll());
|
||||
qDebug() << "TapController: OpenVPN certificate installed:" << certOutput;
|
||||
return true;
|
||||
}
|
||||
|
||||
41
service/server/tapcontroller_win.h
Normal file
41
service/server/tapcontroller_win.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef TAPCONTROLLER_H
|
||||
#define TAPCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
#define IPv6_DEBUG
|
||||
|
||||
//! The TapController class verifies Windows Tap Controller for existance on Windows platform.
|
||||
|
||||
class TapController
|
||||
{
|
||||
public:
|
||||
static TapController& Instance();
|
||||
static bool checkAndSetup();
|
||||
static QString getOpenVpnPath();
|
||||
|
||||
|
||||
bool checkInstaller();
|
||||
|
||||
static QStringList getTapList();
|
||||
static bool enableTapAdapter(const QString &tapInstanceId);
|
||||
static bool disableTapAdapter(const QString &tapInstanceId);
|
||||
private:
|
||||
explicit TapController();
|
||||
TapController(TapController const &) = delete;
|
||||
TapController& operator= (TapController const&) = delete;
|
||||
|
||||
static bool checkDriver(const QString& tapInstanceId);
|
||||
static bool checkOpenVpn();
|
||||
static QString getTapInstallPath();
|
||||
static QString getTapDriverDir();
|
||||
static bool setupDriver();
|
||||
static bool setupDriverCertificate();
|
||||
static bool removeDriver(const QString& tapInstanceId);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // TAPCONTROLLER_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue