summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-11-13 13:31:38 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-11-24 18:50:04 +0100
commit95bdf438a5ab00bbb4924c677fcc415447f4ed6b (patch)
treeb97f6bdac82be3948dc7ec6a5e68be4e0b90ee8b
parent4f78929be5845af02a45e51f21ce848ec5efa166 (diff)
downloadmullvadvpn-95bdf438a5ab00bbb4924c677fcc415447f4ed6b.tar.xz
mullvadvpn-95bdf438a5ab00bbb4924c677fcc415447f4ed6b.zip
Add wintun.dll functions to driverlogic
-rw-r--r--windows/driverlogic/driverlogic.vcxproj4
-rw-r--r--windows/driverlogic/src/driverlogic.cpp188
2 files changed, 190 insertions, 2 deletions
diff --git a/windows/driverlogic/driverlogic.vcxproj b/windows/driverlogic/driverlogic.vcxproj
index fd9ba06616..5d78c90479 100644
--- a/windows/driverlogic/driverlogic.vcxproj
+++ b/windows/driverlogic/driverlogic.vcxproj
@@ -61,7 +61,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <AdditionalIncludeDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../windows-libraries/src/;$(ProjectDir)../</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(ProjectDir)../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../windows-libraries/src/;$(ProjectDir)../</AdditionalIncludeDirectories>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
@@ -83,7 +83,7 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
- <AdditionalIncludeDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../windows-libraries/src/;$(ProjectDir)../</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(ProjectDir)../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../windows-libraries/src/;$(ProjectDir)../</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
diff --git a/windows/driverlogic/src/driverlogic.cpp b/windows/driverlogic/src/driverlogic.cpp
index 4133308d35..663436a7fd 100644
--- a/windows/driverlogic/src/driverlogic.cpp
+++ b/windows/driverlogic/src/driverlogic.cpp
@@ -6,6 +6,7 @@
#include <string>
#include <optional>
#include <set>
+#include <filesystem>
#include <libcommon/error.h>
#include <libcommon/guid.h>
#include <libcommon/memory.h>
@@ -20,6 +21,7 @@
#include <cfgmgr32.h>
#include <io.h>
#include <fcntl.h>
+#include <wintun.h>
namespace
@@ -768,6 +770,188 @@ void RemoveNetAdapterByAlias(const std::wstring &hardwareId, const std::wstring
}
}
+std::filesystem::path GetCurrentModulePath()
+{
+ std::vector<wchar_t> pathBuffer;
+
+ SetLastError(ERROR_SUCCESS);
+
+ size_t nextCapacity = 256;
+
+ do
+ {
+ pathBuffer.reserve(nextCapacity);
+
+ const auto writtenChars = GetModuleFileNameW(nullptr, &pathBuffer[0], static_cast<DWORD>(pathBuffer.capacity()));
+
+ if (0 == writtenChars)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "GetModuleFileNameW");
+ }
+
+ pathBuffer.resize(writtenChars);
+
+ nextCapacity = 2 * pathBuffer.capacity();
+ } while (ERROR_INSUFFICIENT_BUFFER == GetLastError());
+
+ return std::filesystem::path(pathBuffer.begin(), pathBuffer.end());
+}
+
+class WintunDll
+{
+public:
+
+ WintunDll() : dllHandle(nullptr)
+ {
+ auto wintunPath = GetCurrentModulePath().replace_filename(L"wintun.dll");
+ dllHandle = LoadLibraryExW(wintunPath.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
+
+ if (nullptr == dllHandle)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "LoadLibraryExW");
+ }
+
+ try
+ {
+ createAdapter = getProcAddressOrThrow<WINTUN_CREATE_ADAPTER_FUNC>("WintunCreateAdapter");
+ openAdapter = getProcAddressOrThrow<WINTUN_OPEN_ADAPTER_FUNC>("WintunOpenAdapter");
+ freeAdapter = getProcAddressOrThrow<WINTUN_FREE_ADAPTER_FUNC>("WintunFreeAdapter");
+ deletePoolDriver = getProcAddressOrThrow<WINTUN_DELETE_POOL_DRIVER_FUNC>("WintunDeletePoolDriver");
+ }
+ catch (...)
+ {
+ FreeLibrary(dllHandle);
+ throw;
+ }
+ }
+
+ ~WintunDll()
+ {
+ if (nullptr != dllHandle)
+ {
+ FreeLibrary(dllHandle);
+ }
+ }
+
+ WINTUN_CREATE_ADAPTER_FUNC createAdapter;
+ WINTUN_OPEN_ADAPTER_FUNC openAdapter;
+ WINTUN_FREE_ADAPTER_FUNC freeAdapter;
+ WINTUN_DELETE_POOL_DRIVER_FUNC deletePoolDriver;
+
+private:
+
+ template<typename T>
+ T getProcAddressOrThrow(const char *procName)
+ {
+ const T result = reinterpret_cast<T>(GetProcAddress(dllHandle, procName));
+ if (nullptr == result)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "GetProcAddress");
+ }
+ return result;
+ }
+
+ HMODULE dllHandle;
+};
+
+int HandleWintunCommands(int argc, const wchar_t *argv[])
+{
+ WintunDll wintun;
+
+ if (argc < 3)
+ {
+ goto INVALID_ARGUMENTS;
+ }
+
+ if (0 == _wcsicmp(argv[2], L"create-adapter"))
+ {
+ if (argc < 5)
+ {
+ goto INVALID_ARGUMENTS;
+ }
+
+ const wchar_t *pool = argv[3];
+ const wchar_t *adapter = argv[4];
+
+ GUID guidObject;
+ const GUID *requestGuid = nullptr;
+ if (argc >= 6)
+ {
+ guidObject = common::Guid::FromString(argv[5]);
+ requestGuid = &guidObject;
+ }
+
+ const auto handle = wintun.createAdapter(
+ pool,
+ adapter,
+ requestGuid,
+ nullptr
+ );
+
+ if (nullptr == handle)
+ {
+ const auto status = GetLastError();
+ if (ERROR_FILE_NOT_FOUND == status)
+ {
+ return ADAPTER_NOT_FOUND;
+ }
+ else
+ {
+ THROW_WINDOWS_ERROR(status, "wintun.createAdapter");
+ }
+ }
+ wintun.freeAdapter(handle);
+ }
+ else if (0 == _wcsicmp(argv[2], L"delete-pool-driver"))
+ {
+ if (4 != argc)
+ {
+ goto INVALID_ARGUMENTS;
+ }
+
+ const wchar_t *pool = argv[3];
+
+ wintun.deletePoolDriver(pool, nullptr);
+ }
+ else if (0 == _wcsicmp(argv[2], L"adapter-exists"))
+ {
+ if (5 != argc)
+ {
+ goto INVALID_ARGUMENTS;
+ }
+
+ const wchar_t *pool = argv[3];
+ const wchar_t *adapter = argv[4];
+
+ const auto handle = wintun.openAdapter(pool, adapter);
+
+ if (nullptr == handle)
+ {
+ const auto status = GetLastError();
+ if (ERROR_FILE_NOT_FOUND == status)
+ {
+ return ADAPTER_NOT_FOUND;
+ }
+ else
+ {
+ THROW_WINDOWS_ERROR(status, "wintun.openAdapter");
+ }
+ }
+ wintun.freeAdapter(handle);
+ }
+ else
+ {
+ goto INVALID_ARGUMENTS;
+ }
+
+ return GENERAL_SUCCESS;
+
+INVALID_ARGUMENTS:
+
+ LogError(L"Invalid arguments.");
+ return GENERAL_ERROR;
+}
+
} // anonymous namespace
int wmain(int argc, const wchar_t * argv[], const wchar_t * [])
@@ -827,6 +1011,10 @@ int wmain(int argc, const wchar_t * argv[], const wchar_t * [])
return ADAPTER_NOT_FOUND;
}
}
+ else if (0 == _wcsicmp(argv[1], L"wintun"))
+ {
+ return HandleWintunCommands(argc, argv);
+ }
else
{
goto INVALID_ARGUMENTS;