diff --git a/client/amnizia-client.pro b/client/amnizia-client.pro index 077b7c9b..e19c530d 100644 --- a/client/amnizia-client.pro +++ b/client/amnizia-client.pro @@ -76,6 +76,7 @@ ICON = images/main.icns } SOURCES += main.cpp\ + core/router.cpp \ publib/debug.cpp \ publib/runguard.cpp \ publib/winhelp.cpp \ @@ -84,6 +85,7 @@ SOURCES += main.cpp\ ui/customshadoweffect.cpp HEADERS += ui/mainwindow.h \ + core/router.h \ publib/debug.h \ publib/runguard.h \ publib/winhelp.h \ diff --git a/client/core/router.cpp b/client/core/router.cpp new file mode 100644 index 00000000..247138cd --- /dev/null +++ b/client/core/router.cpp @@ -0,0 +1,306 @@ +#include "router.h" + +#include + + + +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); + + 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); +} + +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")); + + 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; +} + +bool Router::clearSavedRoutes() +{ + 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; +} + +bool Router::routeDelete(const QString &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; +#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 +} diff --git a/client/core/router.h b/client/core/router.h new file mode 100644 index 00000000..155aa43a --- /dev/null +++ b/client/core/router.h @@ -0,0 +1,58 @@ +#ifndef ROUTER_H +#define ROUTER_H + +#include +#include +#include +#include +#include + + +#ifdef Q_OS_WIN +#include //includes Windows.h +#include + + +#include +#include +#include +#include + + +#include +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; + + QList ipForwardRows; +}; + +#endif // ROUTER_H