summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dist-assets/windows/installer.nsh37
-rw-r--r--windows/nsis-plugins/src/driverlogic/context.cpp371
-rw-r--r--windows/nsis-plugins/src/driverlogic/context.h17
-rw-r--r--windows/nsis-plugins/src/driverlogic/driverlogic.cpp55
-rw-r--r--windows/nsis-plugins/src/driverlogic/driverlogic.def1
-rw-r--r--windows/nsis-plugins/src/driverlogic/driverlogic.vcxproj4
-rw-r--r--windows/shared/shared.sln13
-rw-r--r--windows/shared/src/shared/network/interfaceutils.cpp177
-rw-r--r--windows/shared/src/shared/network/interfaceutils.h79
-rw-r--r--windows/shared/src/shared/shared.vcxproj2
-rw-r--r--windows/shared/src/shared/shared.vcxproj.filters11
-rw-r--r--windows/shared/src/shared/stdafx.h3
-rw-r--r--windows/windns/src/windns/windns.cpp18
-rw-r--r--windows/windns/src/windns/windns.vcxproj16
-rw-r--r--windows/windns/windns.sln11
m---------windows/windows-libraries0
-rw-r--r--windows/winnet/src/winnet/interfaceutils.cpp124
-rw-r--r--windows/winnet/src/winnet/interfaceutils.h51
-rw-r--r--windows/winnet/src/winnet/winnet.cpp4
-rw-r--r--windows/winnet/src/winnet/winnet.vcxproj14
-rw-r--r--windows/winnet/src/winnet/winnet.vcxproj.filters2
21 files changed, 664 insertions, 346 deletions
diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh
index d1bf3b28ed..1b3af33091 100644
--- a/dist-assets/windows/installer.nsh
+++ b/dist-assets/windows/installer.nsh
@@ -38,6 +38,10 @@
!define DRIVERLOGIC_GENERAL_ERROR 0
!define DRIVERLOGIC_SUCCESS 1
+# Return codes from driverlogic::RollbackTapAliases
+!define RTA_GENERAL_ERROR 0
+!define RTA_SUCCESS 1
+
# Return codes from tray::PromoteTrayIcon
!define PTI_GENERAL_ERROR 0
!define PTI_SUCCESS 1
@@ -312,23 +316,26 @@
Goto InstallDriver_return
${EndIf}
- ${If} $InstallDriver_BaselineStatus == ${EB_MULLVAD_ADAPTER_PRESENT}
- #
- # The TAP adapter may be renamed on update.
- # Check if we need to rename it.
- #
- log::Log "Identifying TAP adapter"
- driverlogic::IdentifyNewAdapter
+ #
+ # Driver updates will replace the GUIDs and names
+ # of our adapters, so let's restore them.
+ #
+ log::Log "Restoring any changed TAP adapter aliases"
+ driverlogic::RollbackTapAliases
- Pop $0
- Pop $1
+ Pop $0
+ Pop $1
- ${If} $0 != ${INA_SUCCESS}
- log::Log "Virtual adapter with custom name already present on system"
- Goto InstallDriver_return_success
- ${EndIf}
+ ${If} $0 != ${RTA_SUCCESS}
+ StrCpy $R0 "Failed to roll back TAP adapter aliases: error $0"
+ log::LogWithDetails $R0 $1
+ Goto InstallDriver_return
+ ${EndIf}
+
+ ${If} $InstallDriver_BaselineStatus == ${EB_MULLVAD_ADAPTER_PRESENT}
+ log::Log "Virtual adapter with custom name already present on system"
- Goto InstallDriver_rename_adapter
+ Goto InstallDriver_return_success
${EndIf}
InstallDriver_install_driver:
@@ -362,8 +369,6 @@
Goto InstallDriver_return
${EndIf}
- InstallDriver_rename_adapter:
-
StrCpy $InstallDriver_TapName $1
log::Log "New virtual adapter is named $\"$1$\""
diff --git a/windows/nsis-plugins/src/driverlogic/context.cpp b/windows/nsis-plugins/src/driverlogic/context.cpp
index 42394e25e3..2598377091 100644
--- a/windows/nsis-plugins/src/driverlogic/context.cpp
+++ b/windows/nsis-plugins/src/driverlogic/context.cpp
@@ -1,9 +1,11 @@
#include "stdafx.h"
#include "context.h"
+#include <libcommon/guid.h>
#include <libcommon/string.h>
#include <libcommon/error.h>
#include <libcommon/memory.h>
+#include <libcommon/network/nci.h>
#include <log/log.h>
#include <winsock2.h>
@@ -28,59 +30,6 @@ namespace
const wchar_t TAP_HARDWARE_ID[] = L"tap0901";
-std::set<Context::NetworkAdapter> GetAllAdapters()
-{
- ULONG bufferSize = 0;
-
- const ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
-
- auto status = GetAdaptersAddresses(AF_INET, flags, nullptr, nullptr, &bufferSize);
-
- THROW_UNLESS(ERROR_BUFFER_OVERFLOW, status, "Probe for adapter listing buffer size");
-
- // Memory is cheap, this avoids a looping construct.
- bufferSize *= 2;
-
- std::vector<uint8_t> buffer(bufferSize);
-
- status = GetAdaptersAddresses(AF_INET, flags, nullptr,
- reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer[0]), &bufferSize);
-
- THROW_UNLESS(ERROR_SUCCESS, status, "Retrieve adapter listing");
-
- std::set<Context::NetworkAdapter> adapters;
-
- for (auto it = (PIP_ADAPTER_ADDRESSES)&buffer[0]; nullptr != it; it = it->Next)
- {
- adapters.emplace(Context::NetworkAdapter(common::string::ToWide(it->AdapterName),
- it->Description, it->FriendlyName));
- }
-
- return adapters;
-}
-
-std::set<Context::NetworkAdapter> GetTapAdapters(const std::set<Context::NetworkAdapter> &adapters)
-{
- std::set<Context::NetworkAdapter> tapAdapters;
-
- for (const auto &adapter : adapters)
- {
- static const wchar_t name[] = L"TAP-Windows Adapter V9";
-
- //
- // Compare partial name, because once you start having more TAP adapters
- // they're named "TAP-Windows Adapter V9 #2" and so on.
- //
-
- if (0 == adapter.name.compare(0, _countof(name) - 1, name))
- {
- tapAdapters.insert(adapter);
- }
- }
-
- return tapAdapters;
-}
-
template<typename T>
void LogAdapters(const std::wstring &description, const T &adapters)
{
@@ -143,6 +92,212 @@ std::wstring GetNetCfgInstanceId(HDEVINFO devInfo, const SP_DEVINFO_DATA &devInf
return instanceId.data();
}
+std::wstring GetDeviceInstanceId(
+ HDEVINFO devInfo,
+ SP_DEVINFO_DATA* devInfoData
+)
+{
+ DWORD requiredSize = 0;
+
+ SetupDiGetDeviceInstanceIdW(
+ devInfo,
+ devInfoData,
+ nullptr,
+ 0,
+ &requiredSize
+ );
+
+ std::vector<wchar_t> deviceInstanceId;
+ deviceInstanceId.resize(1 + requiredSize * sizeof(wchar_t));
+
+ const auto status = SetupDiGetDeviceInstanceIdW(
+ devInfo,
+ devInfoData,
+ &deviceInstanceId[0],
+ deviceInstanceId.size(),
+ nullptr
+ );
+ THROW_GLE_IF(FALSE, status, "SetupDiGetDeviceInstanceIdW() failed");
+
+ return deviceInstanceId.data();
+}
+
+std::wstring GetDeviceStringProperty(
+ HDEVINFO devInfo,
+ SP_DEVINFO_DATA *devInfoData,
+ const DEVPROPKEY *property
+)
+{
+ //
+ // Obtain required buffer size
+ //
+
+ DWORD requiredSize = 0;
+ DEVPROPTYPE type;
+
+ const auto sizeStatus = SetupDiGetDevicePropertyW(
+ devInfo,
+ devInfoData,
+ property,
+ &type,
+ nullptr,
+ 0,
+ &requiredSize,
+ 0
+ );
+
+ const DWORD lastError = GetLastError();
+ if (FALSE == sizeStatus && ERROR_INSUFFICIENT_BUFFER != lastError)
+ {
+ common::error::Throw(
+ "Error obtaining device property length",
+ lastError
+ );
+ }
+
+ std::vector<wchar_t> buffer;
+ buffer.resize(1 + requiredSize / sizeof(wchar_t));
+
+ //
+ // Read property
+ //
+
+ const auto status = SetupDiGetDevicePropertyW(
+ devInfo,
+ devInfoData,
+ property,
+ &type,
+ reinterpret_cast<PBYTE>(&buffer[0]),
+ buffer.size() * sizeof(wchar_t),
+ nullptr,
+ 0
+ );
+
+ THROW_GLE_IF(FALSE, status, "Failed to read device property");
+
+ return buffer.data();
+}
+
+std::optional<std::wstring> GetDeviceRegistryStringProperty(
+ HDEVINFO devInfo,
+ SP_DEVINFO_DATA *devInfoData,
+ DWORD property
+)
+{
+ //
+ // Obtain required buffer size
+ //
+
+ DWORD requiredSize = 0;
+
+ const auto sizeStatus = SetupDiGetDeviceRegistryPropertyW(
+ devInfo,
+ devInfoData,
+ property,
+ nullptr,
+ nullptr,
+ 0,
+ &requiredSize
+ );
+
+ const DWORD lastError = GetLastError();
+ if (FALSE == sizeStatus && ERROR_INSUFFICIENT_BUFFER != lastError)
+ {
+ if (ERROR_INVALID_DATA == lastError)
+ {
+ // ERROR_INVALID_DATA may mean that the property does not exist
+ // TODO: Check if there may be other causes.
+ return std::nullopt;
+ }
+ THROW_GLE("Error obtaining device property length");
+ }
+
+ //
+ // Read property
+ //
+
+ std::vector<wchar_t> buffer;
+ buffer.resize(1 + requiredSize / sizeof(wchar_t));
+
+ const auto status = SetupDiGetDeviceRegistryPropertyW(
+ devInfo,
+ devInfoData,
+ property,
+ nullptr,
+ reinterpret_cast<PBYTE>(&buffer[0]),
+ buffer.size() * sizeof(wchar_t),
+ nullptr
+ );
+
+ THROW_GLE_IF(FALSE, status, "Failed to read device property");
+
+ return { buffer.data() };
+}
+
+std::set<Context::NetworkAdapter> GetTapAdapters()
+{
+ std::set<Context::NetworkAdapter> adapters;
+
+ HDEVINFO devInfo = SetupDiGetClassDevs(
+ &GUID_DEVCLASS_NET,
+ nullptr,
+ nullptr,
+ DIGCF_PRESENT
+ );
+ THROW_GLE_IF(INVALID_HANDLE_VALUE, devInfo, "SetupDiGetClassDevs() failed");
+
+ common::memory::ScopeDestructor scopeDestructor;
+ scopeDestructor += [devInfo]()
+ {
+ SetupDiDestroyDeviceInfoList(devInfo);
+ };
+
+ common::network::Nci nci;
+
+ for (int memberIndex = 0; ; memberIndex++)
+ {
+ SP_DEVINFO_DATA devInfoData = { 0 };
+ devInfoData.cbSize = sizeof(devInfoData);
+
+ if (FALSE == SetupDiEnumDeviceInfo(devInfo, memberIndex, &devInfoData))
+ {
+ if (ERROR_NO_MORE_ITEMS == GetLastError())
+ {
+ // Done
+ break;
+ }
+ THROW_GLE("SetupDiEnumDeviceInfo() failed while enumerating network adapters");
+ }
+
+ //
+ // Check whether this is a TAP adapter
+ //
+
+ const auto hardwareId = GetDeviceRegistryStringProperty(devInfo, &devInfoData, SPDRP_HARDWAREID);
+ if (!hardwareId.has_value()
+ || wcscmp(hardwareId.value().c_str(), TAP_HARDWARE_ID) != 0)
+ {
+ continue;
+ }
+
+ //
+ // Construct NetworkAdapter
+ //
+
+ const std::wstring guid = GetNetCfgInstanceId(devInfo, devInfoData);
+ GUID guidObj = common::Guid::FromString(guid);
+
+ adapters.emplace(Context::NetworkAdapter(
+ guid,
+ GetDeviceStringProperty(devInfo, &devInfoData, &DEVPKEY_Device_DriverDesc),
+ nci.getConnectionName(guidObj),
+ GetDeviceInstanceId(devInfo, &devInfoData)
+ ));
+ }
+
+ return adapters;
+}
+
} // anonymous namespace
//static
@@ -201,15 +356,14 @@ std::optional<Context::NetworkAdapter> Context::FindMullvadAdapter(const std::se
Context::BaselineStatus Context::establishBaseline()
{
- m_baseline = GetAllAdapters();
- const auto tapAdapters = GetTapAdapters(m_baseline);
+ m_baseline = GetTapAdapters();
- if (tapAdapters.empty())
+ if (m_baseline.empty())
{
return BaselineStatus::NO_TAP_ADAPTERS_PRESENT;
}
- if (FindMullvadAdapter(tapAdapters).has_value())
+ if (FindMullvadAdapter(m_baseline).has_value())
{
return BaselineStatus::MULLVAD_ADAPTER_PRESENT;
}
@@ -219,31 +373,50 @@ Context::BaselineStatus Context::establishBaseline()
void Context::recordCurrentState()
{
- m_currentState = GetAllAdapters();
+ m_currentState = GetTapAdapters();
+}
+
+void Context::rollbackTapAliases()
+{
+ common::network::Nci nci;
+
+ for (const auto &adapter : m_currentState)
+ {
+ const auto oldInfo = m_baseline.find(adapter);
+ if (m_baseline.end() != oldInfo)
+ {
+ GUID guidObj = common::Guid::FromString(&adapter.guid[0]);
+
+ nci.setConnectionName(guidObj, oldInfo->alias.c_str());
+ }
+ }
}
Context::NetworkAdapter Context::getNewAdapter()
{
std::list<NetworkAdapter> added;
- const auto baselineTaps = GetTapAdapters(m_baseline);
- const auto currentTaps = GetTapAdapters(m_currentState);
-
- for (const auto &adapter : currentTaps)
+ for (const auto &adapter : m_currentState)
{
- if (baselineTaps.end() == baselineTaps.find(adapter))
+ if (m_baseline.end() == m_baseline.find(adapter))
{
added.push_back(adapter);
}
}
- if (added.size() != 1)
+ if (added.size() == 0)
{
- LogAdapters(L"Enumerable network adapters", m_currentState);
- LogAdapters(L"Added TAP adapters", added);
+ LogAdapters(L"Enumerable network TAP adapters", m_currentState);
throw std::runtime_error("Unable to identify recently added TAP adapter");
}
+ else if (added.size() > 1)
+ {
+ LogAdapters(L"Enumerable network TAP adapters", m_currentState);
+ LogAdapters(L"New TAP adapters:", added);
+
+ throw std::runtime_error("Identified more TAP adapters than expected");
+ }
return *added.begin();
}
@@ -251,7 +424,7 @@ Context::NetworkAdapter Context::getNewAdapter()
//static
Context::DeletionResult Context::DeleteMullvadAdapter()
{
- auto tapAdapters = GetTapAdapters(GetAllAdapters());
+ auto tapAdapters = GetTapAdapters();
std::optional<NetworkAdapter> mullvadAdapter = FindMullvadAdapter(tapAdapters);
if (!mullvadAdapter.has_value())
@@ -276,71 +449,28 @@ Context::DeletionResult Context::DeleteMullvadAdapter()
SetupDiDestroyDeviceInfoList(devInfo);
};
- SP_DEVINFO_DATA devInfoData;
-
- std::vector<wchar_t> buffer;
- DWORD nameLen;
-
int numRemainingAdapters = 0;
for (int memberIndex = 0; ; memberIndex++)
{
- devInfoData = { 0 };
+ SP_DEVINFO_DATA devInfoData = { 0 };
devInfoData.cbSize = sizeof(devInfoData);
if (FALSE == SetupDiEnumDeviceInfo(devInfo, memberIndex, &devInfoData))
{
- if (GetLastError() == ERROR_NO_MORE_ITEMS)
+ if (ERROR_NO_MORE_ITEMS == GetLastError())
{
- /* done */
break;
}
THROW_GLE("Error enumerating network adapters");
}
- if (FALSE == SetupDiGetDeviceRegistryPropertyW(
- devInfo,
- &devInfoData,
- SPDRP_HARDWAREID,
- nullptr,
- nullptr,
- 0,
- &nameLen
- ))
- {
- const auto status = GetLastError();
- if (ERROR_INSUFFICIENT_BUFFER != status)
- {
- /* ERROR_INSUFFICIENT_BUFFER is expected */
- if (ERROR_INVALID_DATA == status)
- {
- /* ERROR_INVALID_DATA may mean that the property does not exist */
- continue;
- }
- THROW_GLE("Error obtaining network adapter hardware ID length");
- }
- }
-
- buffer.resize(nameLen / sizeof(wchar_t) + 1);
- buffer[nameLen / sizeof(wchar_t)] = L'\0';
-
- if (FALSE == SetupDiGetDeviceRegistryPropertyW(
- devInfo,
- &devInfoData,
- SPDRP_HARDWAREID,
- nullptr,
- reinterpret_cast<PBYTE>(buffer.data()),
- (buffer.size() - 1) * sizeof(wchar_t),
- nullptr
- ))
- {
- THROW_GLE("Error obtaining network adapter hardware ID");
- }
+ const auto hardwareId = GetDeviceRegistryStringProperty(devInfo, &devInfoData, SPDRP_HARDWAREID);
- if (wcscmp(TAP_HARDWARE_ID, buffer.data()) == 0)
+ if (hardwareId.has_value()
+ && wcscmp(TAP_HARDWARE_ID, hardwareId.value().data()) == 0)
{
- std::wstring netCfgInstanceId = GetNetCfgInstanceId(devInfo, devInfoData);
- if (netCfgInstanceId.compare(mullvadGuid) != 0)
+ if (0 != GetNetCfgInstanceId(devInfo, devInfoData).compare(mullvadGuid))
{
numRemainingAdapters++;
continue;
@@ -356,10 +486,7 @@ Context::DeletionResult Context::DeleteMullvadAdapter()
}
}
- if (numRemainingAdapters > 0)
- {
- return DeletionResult::SOME_REMAINING_TAP_ADAPTERS;
- }
-
- return DeletionResult::NO_REMAINING_TAP_ADAPTERS;
+ return (numRemainingAdapters > 0)
+ ? DeletionResult::SOME_REMAINING_TAP_ADAPTERS
+ : DeletionResult::NO_REMAINING_TAP_ADAPTERS;
}
diff --git a/windows/nsis-plugins/src/driverlogic/context.h b/windows/nsis-plugins/src/driverlogic/context.h
index eabf884ba8..9c0b19d62f 100644
--- a/windows/nsis-plugins/src/driverlogic/context.h
+++ b/windows/nsis-plugins/src/driverlogic/context.h
@@ -17,17 +17,19 @@ public:
std::wstring guid;
std::wstring name;
std::wstring alias;
+ std::wstring deviceInstanceId;
- NetworkAdapter(std::wstring _guid, std::wstring _name, std::wstring _alias)
- : guid(_guid)
- , name(_name)
- , alias(_alias)
+ NetworkAdapter(std::wstring guid, std::wstring name, std::wstring alias, std::wstring deviceInstanceId)
+ : guid(guid)
+ , name(name)
+ , alias(alias)
+ , deviceInstanceId(deviceInstanceId)
{
}
bool operator<(const NetworkAdapter &rhs) const
{
- return _wcsicmp(guid.c_str(), rhs.guid.c_str()) < 0;
+ return _wcsicmp(deviceInstanceId.c_str(), rhs.deviceInstanceId.c_str()) < 0;
}
};
@@ -43,6 +45,11 @@ public:
void recordCurrentState();
//
+ // Restore TAP aliases to baseline state
+ //
+ void rollbackTapAliases();
+
+ //
// Identify a single new TAP adapter
//
NetworkAdapter getNewAdapter();
diff --git a/windows/nsis-plugins/src/driverlogic/driverlogic.cpp b/windows/nsis-plugins/src/driverlogic/driverlogic.cpp
index 82259c015d..1e1ecc0fc7 100644
--- a/windows/nsis-plugins/src/driverlogic/driverlogic.cpp
+++ b/windows/nsis-plugins/src/driverlogic/driverlogic.cpp
@@ -126,6 +126,7 @@ void __declspec(dllexport) NSISCALL EstablishBaseline
{
pushstring(L"Initialize() function was not called or was not successful");
pushint(EstablishBaselineStatus::GENERAL_ERROR);
+ return;
}
try
@@ -247,7 +248,8 @@ void __declspec(dllexport) NSISCALL IdentifyNewAdapter
if (nullptr == g_context)
{
pushstring(L"Initialize() function was not called or was not successful");
- pushint(EstablishBaselineStatus::GENERAL_ERROR);
+ pushint(IdentifyNewAdapterStatus::GENERAL_ERROR);
+ return;
}
try
@@ -272,6 +274,57 @@ void __declspec(dllexport) NSISCALL IdentifyNewAdapter
}
//
+// RollbackTapAliases
+//
+// Updating the TAP driver may replace GUIDs and aliases.
+// Use this to restore the aliases to their baseline state.
+//
+enum class RollbackTapAliasesStatus
+{
+ GENERAL_ERROR = 0,
+ SUCCESS
+};
+
+void __declspec(dllexport) NSISCALL RollbackTapAliases
+(
+ HWND hwndParent,
+ int string_size,
+ LPTSTR variables,
+ stack_t** stacktop,
+ extra_parameters* extra,
+ ...
+)
+{
+ EXDLL_INIT();
+
+ if (nullptr == g_context)
+ {
+ pushstring(L"Initialize() function was not called or was not successful");
+ pushint(RollbackTapAliasesStatus::GENERAL_ERROR);
+ return;
+ }
+
+ try
+ {
+ g_context->recordCurrentState();
+ g_context->rollbackTapAliases();
+
+ pushstring(L"");
+ pushint(RollbackTapAliasesStatus::SUCCESS);
+ }
+ catch (std::exception & err)
+ {
+ pushstring(common::string::ToWide(err.what()).c_str());
+ pushint(RollbackTapAliasesStatus::GENERAL_ERROR);
+ }
+ catch (...)
+ {
+ pushstring(L"Unspecified error");
+ pushint(RollbackTapAliasesStatus::GENERAL_ERROR);
+ }
+}
+
+//
// Deinitialize
//
// Call this function once during shutdown.
diff --git a/windows/nsis-plugins/src/driverlogic/driverlogic.def b/windows/nsis-plugins/src/driverlogic/driverlogic.def
index b8735f1ada..f7982c513d 100644
--- a/windows/nsis-plugins/src/driverlogic/driverlogic.def
+++ b/windows/nsis-plugins/src/driverlogic/driverlogic.def
@@ -6,4 +6,5 @@ Initialize
EstablishBaseline
IdentifyNewAdapter
RemoveMullvadTap
+RollbackTapAliases
Deinitialize
diff --git a/windows/nsis-plugins/src/driverlogic/driverlogic.vcxproj b/windows/nsis-plugins/src/driverlogic/driverlogic.vcxproj
index 0bcb1a2179..5a4e4b18c4 100644
--- a/windows/nsis-plugins/src/driverlogic/driverlogic.vcxproj
+++ b/windows/nsis-plugins/src/driverlogic/driverlogic.vcxproj
@@ -70,7 +70,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/nsis/;$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
- <AdditionalDependencies>setupapi.lib;iphlpapi.lib;log.lib;libcommon.lib;pluginapi-x86-unicode.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>setupapi.lib;log.lib;libcommon.lib;pluginapi-x86-unicode.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<ModuleDefinitionFile>driverlogic.def</ModuleDefinitionFile>
</Link>
@@ -96,7 +96,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/nsis/;$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
- <AdditionalDependencies>setupapi.lib;iphlpapi.lib;log.lib;libcommon.lib;pluginapi-x86-unicode.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>setupapi.lib;log.lib;libcommon.lib;pluginapi-x86-unicode.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<ModuleDefinitionFile>driverlogic.def</ModuleDefinitionFile>
</Link>
diff --git a/windows/shared/shared.sln b/windows/shared/shared.sln
index d735b2d82d..d664af8399 100644
--- a/windows/shared/shared.sln
+++ b/windows/shared/shared.sln
@@ -3,6 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 16.0.29324.140
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "src\shared\shared.vcxproj", "{EE69EA4A-CF71-4B88-866B-957F60C4CE0D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcommon", "..\windows-libraries\src\libcommon\libcommon.vcxproj", "{B52E2D10-A94A-4605-914A-2DCEF6A757EF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -24,6 +29,14 @@ Global
{EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x86.ActiveCfg = Release|Win32
{EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x86.Build.0 = Release|Win32
{EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x86.Deploy.0 = Release|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.ActiveCfg = Debug|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.Build.0 = Debug|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.ActiveCfg = Debug|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.Build.0 = Debug|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.ActiveCfg = Release|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.Build.0 = Release|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.ActiveCfg = Release|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/windows/shared/src/shared/network/interfaceutils.cpp b/windows/shared/src/shared/network/interfaceutils.cpp
new file mode 100644
index 0000000000..6d56ec82d2
--- /dev/null
+++ b/windows/shared/src/shared/network/interfaceutils.cpp
@@ -0,0 +1,177 @@
+#include "stdafx.h"
+#include <sstream>
+#include <algorithm>
+#include "interfaceutils.h"
+#include <libcommon/error.h>
+#include <libcommon/string.h>
+
+namespace shared::network
+{
+
+InterfaceUtils::NetworkAdapter::NetworkAdapter(
+ const common::network::Nci &nci,
+ const std::shared_ptr<std::vector<uint8_t>> addressesBuffer,
+ const IP_ADAPTER_ADDRESSES &entry
+)
+ : m_addressesBuffer(addressesBuffer)
+ , m_entry(entry)
+{
+ m_guid = common::string::ToWide(entry.AdapterName);
+
+ try
+ {
+ //
+ // FIXME:
+ // Work around incorrect alias sometimes
+ // being returned on Windows 8.
+ //
+ // Steps to reproduce:
+ // 1. Install NDIS 6 TAP driver v9.00.00.21.
+ // 2. Update driver to v9.24.2.601.
+ // 3. Rename TAP adapter.
+ //
+ // GetAdaptersAddresses() returns a generic name
+ // for the *first* adapter instead of the correct
+ // one, whereas ConvertInterfaceAliasToLuid() and
+ // ConvertInterfaceLuidToAlias() yield correct values.
+ //
+
+ IID guidObj = { 0 };
+ if (S_OK != IIDFromString(&m_guid[0], &guidObj))
+ {
+ throw std::runtime_error("IIDFromString() failed");
+ }
+
+ m_alias = nci.getConnectionName(guidObj);
+ }
+ catch (const std::exception &)
+ {
+ m_alias = entry.FriendlyName;
+ }
+
+ m_name = entry.Description;
+}
+
+//static
+std::set<InterfaceUtils::NetworkAdapter> InterfaceUtils::GetAllAdapters(ULONG family, ULONG flags)
+{
+ ULONG bufferSize = 0;
+
+ auto status = GetAdaptersAddresses(family, flags, nullptr, nullptr, &bufferSize);
+
+ THROW_UNLESS(ERROR_BUFFER_OVERFLOW, status, "Probe for adapter listing buffer size");
+
+ // Memory is cheap, this avoids a looping construct.
+ bufferSize *= 2;
+
+ auto buffer = std::make_shared<std::vector<uint8_t>>(bufferSize);
+ auto addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&(*buffer)[0]);
+
+ status = GetAdaptersAddresses(family, flags, nullptr, addresses, &bufferSize);
+
+ THROW_UNLESS(ERROR_SUCCESS, status, "Retrieve adapter listing");
+
+ std::set<NetworkAdapter> adapters;
+
+ common::network::Nci nci;
+
+ for (auto it = addresses; nullptr != it; it = it->Next)
+ {
+ adapters.emplace(NetworkAdapter(nci, buffer, *it));
+ }
+
+ return adapters;
+}
+
+//static
+void InterfaceUtils::AddDeviceIpAddresses(NET_LUID device, const std::vector<SOCKADDR_INET> &addresses)
+{
+ for (const auto &address : addresses)
+ {
+ MIB_UNICASTIPADDRESS_ROW row;
+ InitializeUnicastIpAddressEntry(&row);
+
+ row.InterfaceLuid = device;
+ row.Address = address;
+
+ THROW_UNLESS(NO_ERROR, CreateUnicastIpAddressEntry(&row), "Assign IP address on network interface");
+ }
+}
+
+//static
+std::set<InterfaceUtils::NetworkAdapter>
+InterfaceUtils::GetTapAdapters(const std::set<NetworkAdapter>& adapters)
+{
+ std::set<NetworkAdapter> tapAdapters;
+
+ for (const auto& adapter : adapters)
+ {
+ static const wchar_t name[] = L"TAP-Windows Adapter V9";
+
+ //
+ // Compare partial name, because once you start having more TAP adapters
+ // they're named "TAP-Windows Adapter V9 #2" and so on.
+ //
+
+ if (0 == adapter.name().compare(0, _countof(name) - 1, name))
+ {
+ tapAdapters.insert(adapter);
+ }
+ }
+
+ return tapAdapters;
+}
+
+//static
+std::wstring InterfaceUtils::GetTapInterfaceAlias()
+{
+ //
+ // Look for TAP adapter with alias "Mullvad".
+ //
+
+ using shared::network::InterfaceUtils;
+
+ auto adapters = InterfaceUtils::GetTapAdapters(InterfaceUtils::GetAllAdapters(
+ AF_INET,
+ GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
+ ));
+
+ auto findByAlias = [](const std::set<InterfaceUtils::NetworkAdapter>& adapters, const std::wstring& alias)
+ {
+ const auto it = std::find_if(adapters.begin(), adapters.end(), [&alias](const InterfaceUtils::NetworkAdapter& candidate)
+ {
+ return 0 == _wcsicmp(candidate.alias().c_str(), alias.c_str());
+ });
+
+ return it != adapters.end();
+ };
+
+ static const wchar_t baseAlias[] = L"Mullvad";
+
+ if (findByAlias(adapters, baseAlias))
+ {
+ return baseAlias;
+ }
+
+ //
+ // Look for TAP adapter with alias "Mullvad-1", "Mullvad-2", etc.
+ //
+
+ for (auto i = 0; i < 10; ++i)
+ {
+ std::wstringstream ss;
+
+ ss << baseAlias << L"-" << i;
+
+ const auto alias = ss.str();
+
+ if (findByAlias(adapters, alias))
+ {
+ return alias;
+ }
+ }
+
+ throw std::runtime_error("Unable to find TAP adapter");
+}
+
+}
diff --git a/windows/shared/src/shared/network/interfaceutils.h b/windows/shared/src/shared/network/interfaceutils.h
new file mode 100644
index 0000000000..85a243d591
--- /dev/null
+++ b/windows/shared/src/shared/network/interfaceutils.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <string>
+#include <set>
+#include <vector>
+#include <memory>
+#include <cstdint>
+
+// Secret include order to get most common networking structs/apis
+// And avoiding compilation errors
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2def.h>
+#include <ws2ipdef.h>
+#include <iphlpapi.h>
+#include <netioapi.h>
+// end
+
+#include <libcommon/network/nci.h>
+
+namespace shared::network
+{
+
+class InterfaceUtils
+{
+ InterfaceUtils() = delete;
+
+public:
+
+ class NetworkAdapter
+ {
+
+ public:
+
+ const std::wstring &guid() const { return m_guid; }
+ const std::wstring &name() const { return m_name; }
+ const std::wstring &alias() const { return m_alias; }
+
+ bool operator<(const NetworkAdapter &rhs) const
+ {
+ return _wcsicmp(m_guid.c_str(), rhs.m_guid.c_str()) < 0;
+ }
+
+ const IP_ADAPTER_ADDRESSES &raw() const
+ {
+ return m_entry;
+ }
+
+ private:
+
+ NetworkAdapter(
+ const common::network::Nci &nci,
+ const std::shared_ptr<std::vector<uint8_t>> addressesBuffer,
+ const IP_ADAPTER_ADDRESSES &entry
+ );
+
+ friend class InterfaceUtils;
+
+ const IP_ADAPTER_ADDRESSES &m_entry;
+ std::shared_ptr<std::vector<uint8_t>> m_addressesBuffer;
+
+ std::wstring m_guid;
+ std::wstring m_name;
+ std::wstring m_alias;
+ };
+
+ static std::set<NetworkAdapter> GetAllAdapters(ULONG family, ULONG flags);
+
+ static void AddDeviceIpAddresses(NET_LUID device, const std::vector<SOCKADDR_INET> &addresses);
+
+ static std::set<NetworkAdapter> GetTapAdapters(const std::set<NetworkAdapter> &adapters);
+
+ //
+ // Determines alias of primary TAP adapter.
+ //
+ static std::wstring GetTapInterfaceAlias();
+};
+
+}
diff --git a/windows/shared/src/shared/shared.vcxproj b/windows/shared/src/shared/shared.vcxproj
index 771aaa14bd..a5dc7cf4f2 100644
--- a/windows/shared/src/shared/shared.vcxproj
+++ b/windows/shared/src/shared/shared.vcxproj
@@ -178,10 +178,12 @@
<ItemGroup>
<ClInclude Include="logsink.h" />
<ClInclude Include="ilogsink.h" />
+ <ClInclude Include="network\interfaceutils.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="network\interfaceutils.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
diff --git a/windows/shared/src/shared/shared.vcxproj.filters b/windows/shared/src/shared/shared.vcxproj.filters
index 00c566d6e6..61b48a6937 100644
--- a/windows/shared/src/shared/shared.vcxproj.filters
+++ b/windows/shared/src/shared/shared.vcxproj.filters
@@ -5,8 +5,19 @@
<ClInclude Include="logsink.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
+ <ClInclude Include="network\interfaceutils.h">
+ <Filter>network</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
+ <ClCompile Include="network\interfaceutils.cpp">
+ <Filter>network</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="network">
+ <UniqueIdentifier>{c36884fc-7afc-42a8-b852-c0aafcfcc1c2}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/windows/shared/src/shared/stdafx.h b/windows/shared/src/shared/stdafx.h
index fc6b905b83..59e4616a97 100644
--- a/windows/shared/src/shared/stdafx.h
+++ b/windows/shared/src/shared/stdafx.h
@@ -10,3 +10,6 @@
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
+#include <string>
+#include <sstream>
+#include <algorithm>
diff --git a/windows/windns/src/windns/windns.cpp b/windows/windns/src/windns/windns.cpp
index eae828973c..1ea10f0f08 100644
--- a/windows/windns/src/windns/windns.cpp
+++ b/windows/windns/src/windns/windns.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
+#include <libcommon/guid.h>
#include <libcommon/string.h>
-#include <libcommon/network/adapters.h>
+#include <shared/network/interfaceutils.h>
#include "windns.h"
#include "confineoperation.h"
#include "netsh.h"
@@ -92,20 +93,25 @@ struct AdapterDnsAddresses
//
AdapterDnsAddresses GetAdapterDnsAddresses(const std::wstring &adapterAlias)
{
- common::network::Adapters adapters(AF_UNSPEC, GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST);
+ using shared::network::InterfaceUtils;
- const IP_ADAPTER_ADDRESSES *adapter;
+ const auto adapters = InterfaceUtils::GetAllAdapters(
+ AF_UNSPEC,
+ GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
+ );
- while (nullptr != (adapter = adapters.next()))
+ for (const auto adapter : adapters)
{
- if (0 != _wcsicmp(adapter->FriendlyName, adapterAlias.c_str()))
+ const auto guidObj = common::Guid::FromString(adapter.guid());
+
+ if (0 != _wcsicmp(adapter.alias().c_str(), adapterAlias.c_str()))
{
continue;
}
AdapterDnsAddresses out;
- for (auto server = adapter->FirstDnsServerAddress; nullptr != server; server = server->Next)
+ for (auto server = adapter.raw().FirstDnsServerAddress; nullptr != server; server = server->Next)
{
if (AF_INET == server->Address.lpSockaddr->sa_family)
{
diff --git a/windows/windns/src/windns/windns.vcxproj b/windows/windns/src/windns/windns.vcxproj
index b2b68a999f..31a74eab87 100644
--- a/windows/windns/src/windns/windns.vcxproj
+++ b/windows/windns/src/windns/windns.vcxproj
@@ -98,7 +98,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;WINDNS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/;$(ProjectDir)../../../shared/src/</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
@@ -106,7 +106,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -117,7 +117,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;WINDNS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/;$(ProjectDir)../../../shared/src/</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
@@ -125,7 +125,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -138,7 +138,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;WINDNS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/;$(ProjectDir)../../../shared/src/</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
@@ -148,7 +148,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -161,7 +161,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;WINDNS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/;$(ProjectDir)../../../shared/src/</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
@@ -171,7 +171,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;wbemuuid.lib;comsuppw.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/windows/windns/windns.sln b/windows/windns/windns.sln
index 41811271f9..13f072ff31 100644
--- a/windows/windns/windns.sln
+++ b/windows/windns/windns.sln
@@ -7,8 +7,11 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windns", "src\windns\windns.vcxproj", "{A5344205-FC37-4572-9C63-8564ECC410AC}"
ProjectSection(ProjectDependencies) = postProject
{B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF}
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D} = {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "..\shared\src\shared\shared.vcxproj", "{EE69EA4A-CF71-4B88-866B-957F60C4CE0D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -37,6 +40,14 @@ Global
{A5344205-FC37-4572-9C63-8564ECC410AC}.Release|x86.ActiveCfg = Release|Win32
{A5344205-FC37-4572-9C63-8564ECC410AC}.Release|x86.Build.0 = Release|Win32
{A5344205-FC37-4572-9C63-8564ECC410AC}.Release|x86.Deploy.0 = Release|Win32
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Debug|x64.ActiveCfg = Debug|x64
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Debug|x64.Build.0 = Debug|x64
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Debug|x86.ActiveCfg = Debug|Win32
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Debug|x86.Build.0 = Debug|Win32
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x64.ActiveCfg = Release|x64
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x64.Build.0 = Release|x64
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x86.ActiveCfg = Release|Win32
+ {EE69EA4A-CF71-4B88-866B-957F60C4CE0D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/windows/windows-libraries b/windows/windows-libraries
-Subproject 05e4625383d8521a42da7a2b327fa257061e96f
+Subproject 19889be7a7e3555a03b9678dc486b429d5fad10
diff --git a/windows/winnet/src/winnet/interfaceutils.cpp b/windows/winnet/src/winnet/interfaceutils.cpp
deleted file mode 100644
index 202d9d0724..0000000000
--- a/windows/winnet/src/winnet/interfaceutils.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#include "stdafx.h"
-#include "interfaceutils.h"
-#include "libcommon/error.h"
-#include "libcommon/string.h"
-#include <cstdint>
-#include <algorithm>
-
-//static
-std::set<InterfaceUtils::NetworkAdapter> InterfaceUtils::GetAllAdapters()
-{
- ULONG bufferSize = 0;
-
- const ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
-
- auto status = GetAdaptersAddresses(AF_INET, flags, nullptr, nullptr, &bufferSize);
-
- THROW_UNLESS(ERROR_BUFFER_OVERFLOW, status, "Probe for adapter listing buffer size");
-
- // Memory is cheap, this avoids a looping construct.
- bufferSize *= 2;
-
- std::vector<uint8_t> buffer(bufferSize);
-
- status = GetAdaptersAddresses(AF_INET, flags, nullptr,
- reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer[0]), &bufferSize);
-
- THROW_UNLESS(ERROR_SUCCESS, status, "Retrieve adapter listing");
-
- std::set<NetworkAdapter> adapters;
-
- for (auto it = (PIP_ADAPTER_ADDRESSES)&buffer[0]; nullptr != it; it = it->Next)
- {
- adapters.emplace(NetworkAdapter(common::string::ToWide(it->AdapterName),
- it->Description, it->FriendlyName));
- }
-
- return adapters;
-}
-
-//static
-std::set<InterfaceUtils::NetworkAdapter>
-InterfaceUtils::GetTapAdapters(const std::set<InterfaceUtils::NetworkAdapter> &adapters)
-{
- std::set<NetworkAdapter> tapAdapters;
-
- for (const auto &adapter : adapters)
- {
- static const wchar_t name[] = L"TAP-Windows Adapter V9";
-
- //
- // Compare partial name, because once you start having more TAP adapters
- // they're named "TAP-Windows Adapter V9 #2" and so on.
- //
-
- if (0 == adapter.name.compare(0, _countof(name) - 1, name))
- {
- tapAdapters.insert(adapter);
- }
- }
-
- return tapAdapters;
-}
-
-//static
-std::wstring InterfaceUtils::GetTapInterfaceAlias()
-{
- //
- // Look for TAP adapter with alias "Mullvad".
- //
-
- auto adapters = GetTapAdapters(GetAllAdapters());
-
- auto findByAlias = [](const std::set<NetworkAdapter> &adapters, const std::wstring &alias)
- {
- const auto it = std::find_if(adapters.begin(), adapters.end(), [&alias](const NetworkAdapter &candidate)
- {
- return 0 == _wcsicmp(candidate.alias.c_str(), alias.c_str());
- });
-
- return it != adapters.end();
- };
-
- static const wchar_t baseAlias[] = L"Mullvad";
-
- if (findByAlias(adapters, baseAlias))
- {
- return baseAlias;
- }
-
- //
- // Look for TAP adapter with alias "Mullvad-1", "Mullvad-2", etc.
- //
-
- for (auto i = 0; i < 10; ++i)
- {
- std::wstringstream ss;
-
- ss << baseAlias << L"-" << i;
-
- const auto alias = ss.str();
-
- if (findByAlias(adapters, alias))
- {
- return alias;
- }
- }
-
- throw std::runtime_error("Unable to find TAP adapter");
-}
-
-//static
-void InterfaceUtils::AddDeviceIpAddresses(NET_LUID device, const std::vector<SOCKADDR_INET> &addresses)
-{
- for (const auto &address : addresses)
- {
- MIB_UNICASTIPADDRESS_ROW row;
- InitializeUnicastIpAddressEntry(&row);
-
- row.InterfaceLuid = device;
- row.Address = address;
-
- THROW_UNLESS(NO_ERROR, CreateUnicastIpAddressEntry(&row), "Assign IP address on network interface");
- }
-}
diff --git a/windows/winnet/src/winnet/interfaceutils.h b/windows/winnet/src/winnet/interfaceutils.h
deleted file mode 100644
index 8ab1249a50..0000000000
--- a/windows/winnet/src/winnet/interfaceutils.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include <string>
-#include <set>
-#include <vector>
-
-// Secret include order to get most common networking structs/apis
-// And avoiding compilation errors
-#include <winsock2.h>
-#include <windows.h>
-#include <ws2def.h>
-#include <ws2ipdef.h>
-#include <iphlpapi.h>
-#include <netioapi.h>
-// end
-
-class InterfaceUtils
-{
- InterfaceUtils() = delete;
-
-public:
-
- struct NetworkAdapter
- {
- std::wstring guid;
- std::wstring name;
- std::wstring alias;
-
- NetworkAdapter(std::wstring _guid, std::wstring _name, std::wstring _alias)
- : guid(_guid)
- , name(_name)
- , alias(_alias)
- {
- }
-
- bool operator<(const NetworkAdapter &rhs) const
- {
- return _wcsicmp(guid.c_str(), rhs.guid.c_str()) < 0;
- }
- };
-
- static std::set<NetworkAdapter> GetAllAdapters();
- static std::set<NetworkAdapter> GetTapAdapters(const std::set<NetworkAdapter> &adapters);
-
- //
- // Determines alias of primary TAP adapter.
- //
- static std::wstring GetTapInterfaceAlias();
-
- static void AddDeviceIpAddresses(NET_LUID device, const std::vector<SOCKADDR_INET> &addresses);
-};
diff --git a/windows/winnet/src/winnet/winnet.cpp b/windows/winnet/src/winnet/winnet.cpp
index 690af747f2..c94970b863 100644
--- a/windows/winnet/src/winnet/winnet.cpp
+++ b/windows/winnet/src/winnet/winnet.cpp
@@ -1,10 +1,10 @@
#include "stdafx.h"
#include "winnet.h"
#include "NetworkInterfaces.h"
-#include "interfaceutils.h"
#include "offlinemonitor.h"
#include "routing/routemanager.h"
#include <shared/logsinkadapter.h>
+#include <shared/network/interfaceutils.h>
#include <libcommon/error.h>
#include <libcommon/network.h>
#include <cstdint>
@@ -14,7 +14,9 @@
#include <mutex>
using namespace winnet::routing;
+using namespace common::network;
using AutoLockType = std::scoped_lock<std::mutex>;
+using namespace shared::network;
namespace
{
diff --git a/windows/winnet/src/winnet/winnet.vcxproj b/windows/winnet/src/winnet/winnet.vcxproj
index def37bc67d..5fb0a50ec5 100644
--- a/windows/winnet/src/winnet/winnet.vcxproj
+++ b/windows/winnet/src/winnet/winnet.vcxproj
@@ -30,7 +30,6 @@
<ClCompile Include="networkadaptermonitor.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="InterfacePair.cpp" />
- <ClCompile Include="interfaceutils.cpp" />
<ClCompile Include="offlinemonitor.cpp" />
<ClCompile Include="NetworkInterfaces.cpp" />
<ClCompile Include="routing\defaultroutemonitor.cpp" />
@@ -43,7 +42,6 @@
<ItemGroup>
<ClInclude Include="networkadaptermonitor.h" />
<ClInclude Include="InterfacePair.h" />
- <ClInclude Include="interfaceutils.h" />
<ClInclude Include="offlinemonitor.h" />
<ClInclude Include="NetworkInterfaces.h" />
<ClInclude Include="routing\defaultroutemonitor.h" />
@@ -179,7 +177,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>winnet.def</ModuleDefinitionFile>
<AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">
@@ -203,7 +201,7 @@
</Link>
<Lib>
<AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-Debug</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -221,7 +219,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>winnet.def</ModuleDefinitionFile>
</Link>
@@ -246,7 +244,7 @@
<ModuleDefinitionFile>winnet.def</ModuleDefinitionFile>
</Link>
<Lib>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-Debug</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
@@ -271,7 +269,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>winnet.def</ModuleDefinitionFile>
<AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -295,7 +293,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>winnet.def</ModuleDefinitionFile>
<AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>shared.lib;libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/windows/winnet/src/winnet/winnet.vcxproj.filters b/windows/winnet/src/winnet/winnet.vcxproj.filters
index dfe6d29ec7..db5a7c8b3a 100644
--- a/windows/winnet/src/winnet/winnet.vcxproj.filters
+++ b/windows/winnet/src/winnet/winnet.vcxproj.filters
@@ -6,7 +6,6 @@
<ClCompile Include="winnet.cpp" />
<ClCompile Include="NetworkInterfaces.cpp" />
<ClCompile Include="InterfacePair.cpp" />
- <ClCompile Include="interfaceutils.cpp" />
<ClCompile Include="networkadaptermonitor.cpp" />
<ClCompile Include="offlinemonitor.cpp" />
<ClCompile Include="routing\types.cpp">
@@ -28,7 +27,6 @@
<ClInclude Include="winnet.h" />
<ClInclude Include="NetworkInterfaces.h" />
<ClInclude Include="InterfacePair.h" />
- <ClInclude Include="interfaceutils.h" />
<ClInclude Include="networkadaptermonitor.h" />
<ClInclude Include="offlinemonitor.h" />
<ClInclude Include="routing\types.h">