diff options
| author | Emīls <emils@mullvad.net> | 2018-06-12 17:09:10 +0100 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2018-06-27 11:42:40 +0100 |
| commit | d4be5a08de10047ff0bea51f5a8bbdee299b39be (patch) | |
| tree | a56cd12f0514fe03e9758fdae9f95bd723b1c0ef /windows | |
| parent | 3ec389495457e5d56b2c19bf9acd37be5e809ee3 (diff) | |
| download | mullvadvpn-d4be5a08de10047ff0bea51f5a8bbdee299b39be.tar.xz mullvadvpn-d4be5a08de10047ff0bea51f5a8bbdee299b39be.zip | |
Add NetworkInterfaces class
Diffstat (limited to 'windows')
| -rw-r--r-- | windows/winroute/src/winroute/NetworkInterfaces.cpp | 159 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/NetworkInterfaces.h | 26 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.cpp | bin | 44 -> 1256 bytes | |||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.h | 22 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.vcxproj | 5 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.vcxproj.filters | 2 | ||||
| -rw-r--r-- | windows/winroute/winroute.sln | 15 |
7 files changed, 228 insertions, 1 deletions
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.cpp b/windows/winroute/src/winroute/NetworkInterfaces.cpp new file mode 100644 index 0000000000..72ff982ae0 --- /dev/null +++ b/windows/winroute/src/winroute/NetworkInterfaces.cpp @@ -0,0 +1,159 @@ +#include "stdafx.h" + +#include <windows.h> + +#include "NetworkInterfaces.h" + +#include <memory> +#include <sstream> +#include <stdexcept> +#include <cstdint> + +#include <libcommon/string.h> + + + + + +PMIB_IPINTERFACE_ROW NetworkInterfaces::RowByLuid(NET_LUID rowId) +{ + for (int i = 0; i < (int)mInterfaces->NumEntries; ++i) + { + PMIB_IPINTERFACE_ROW row = &mInterfaces->Table[i]; + // Currnetly, only IPv4 is supported + if (row->InterfaceLuid.Value == rowId.Value && row->Family == AF_INET) + { + return row; + } + } + return nullptr; +} + +bool NetworkInterfaces::HasHighestMetric(PMIB_IPINTERFACE_ROW targetIface) +{ + for (unsigned int i = 0; i < mInterfaces->NumEntries; ++i) + { + PMIB_IPINTERFACE_ROW iface = &mInterfaces->Table[i]; + + if (iface->InterfaceLuid.Value != targetIface->InterfaceLuid.Value + && targetIface->Metric >= iface->Metric) + return false; + } + return true; +} + + +void NetworkInterfaces::EnsureIfaceMetricIsHighest(PMIB_IPINTERFACE_ROW targetIface) +{ + PMIB_IPINTERFACE_ROW iface; + DWORD success = 0; + for (int i = 0; i < (int)mInterfaces->NumEntries; ++i) + { + iface = &mInterfaces->Table[i]; + // Ignoring the target interface. + if (iface->InterfaceLuid.Value == targetIface->InterfaceLuid.Value) + { + continue; + } + + if (iface->UseAutomaticMetric) + { + continue; + } + iface->Metric++; + if (iface->Family == AF_INET) { + iface->SitePrefixLength = 0; + } + success = SetIpInterfaceEntry(iface); + if (success != NO_ERROR) + { + std::stringstream ss; + ss << L"Failed to increment metric for interface with LUID " + << &iface->InterfaceLuid.Value + << ": " + << success; + throw std::runtime_error(ss.str()); + } + + } +} + +NetworkInterfaces::NetworkInterfaces() +{ + mInterfaces = nullptr; + DWORD success = 0; + + success = GetIpInterfaceTable(AF_UNSPEC, &mInterfaces); + if (success != NO_ERROR) + { + std::stringstream ss; + ss << L"Failed to enumerate network interfaces: " << success; + throw std::runtime_error(ss.str()); + } +} + +bool NetworkInterfaces::SetTopMetricForInterfaceByAlias(const wchar_t * deviceAlias) +{ + NET_LUID targetIfaceLuid; + DWORD success = 0; + success = ConvertInterfaceAliasToLuid(deviceAlias, &targetIfaceLuid); + if (success != NO_ERROR) + { + std::wstringstream ss; + ss << L"Failed to convert interface alias '" + << deviceAlias + << "' into LUID: " + << success; + throw std::runtime_error(common::string::ToAnsi(ss.str())); + } + return SetTopMetricForInterfaceWithLuid(targetIfaceLuid); +} + +bool NetworkInterfaces::SetTopMetricForInterfaceWithLuid(NET_LUID targetIfaceId) +{ + + DWORD success = 0; + + PMIB_IPINTERFACE_ROW targetIface = RowByLuid(targetIfaceId); + if (targetIface == nullptr) + { + std::stringstream ss; + ss << L"No interface with LUID " << targetIfaceId.Value; + throw std::runtime_error(ss.str()); + } + + if (targetIface->Metric == MAX_METRIC) + { + return false; + } + + targetIface->UseAutomaticMetric = false; + targetIface->Metric = MAX_METRIC; + if (targetIface->Family == AF_INET) { + targetIface->SitePrefixLength = 0; + } + + success = SetIpInterfaceEntry(targetIface); + if (success != NO_ERROR) + { + std::stringstream ss; + ss << L"Failed to set metric " + << MAX_METRIC + << " for interface with LUID " + << targetIfaceId.Value + << ". Error code - " + << success; + throw std::runtime_error(ss.str()); + } + if (!HasHighestMetric(targetIface)) + { + EnsureIfaceMetricIsHighest(targetIface); + } + return true; +} + + +NetworkInterfaces::~NetworkInterfaces() +{ + FreeMibTable(mInterfaces); +} diff --git a/windows/winroute/src/winroute/NetworkInterfaces.h b/windows/winroute/src/winroute/NetworkInterfaces.h new file mode 100644 index 0000000000..66cea53fc0 --- /dev/null +++ b/windows/winroute/src/winroute/NetworkInterfaces.h @@ -0,0 +1,26 @@ +#pragma once + +#include <windows.h> +#include <winsock2.h> +#include <ws2ipdef.h> +#include <iphlpapi.h> +#include <netioapi.h> +#include <cstdint> + +class NetworkInterfaces +{ + +private: + PMIB_IPINTERFACE_TABLE mInterfaces; + PMIB_IPINTERFACE_ROW RowByLuid(NET_LUID rowId); + bool HasHighestMetric(PMIB_IPINTERFACE_ROW targetIface); + void EnsureIfaceMetricIsHighest(PMIB_IPINTERFACE_ROW iface); + +public: + NetworkInterfaces(); + bool SetTopMetricForInterfaceByAlias (const wchar_t *deviceAlias); + bool SetTopMetricForInterfaceWithLuid(NET_LUID targetIface); + ~NetworkInterfaces(); +}; + +const static uint32_t MAX_METRIC = 1; diff --git a/windows/winroute/src/winroute/winroute.cpp b/windows/winroute/src/winroute/winroute.cpp Binary files differindex 08343afdf7..c28a1a4927 100644 --- a/windows/winroute/src/winroute/winroute.cpp +++ b/windows/winroute/src/winroute/winroute.cpp diff --git a/windows/winroute/src/winroute/winroute.h b/windows/winroute/src/winroute/winroute.h index 6f70f09bee..316a024d79 100644 --- a/windows/winroute/src/winroute/winroute.h +++ b/windows/winroute/src/winroute/winroute.h @@ -1 +1,23 @@ #pragma once +#include <cstdint> + +#ifdef WINROUTE_EXPORTS +#define WINROUTE_LINKAGE __declspec(dllexport) +#else +#define WINROUTE_LINKAGE __declspec(dllimport) +#endif + +#define WINROUTE_API __stdcall + +typedef void (WINROUTE_API *WinRouteErrorSink)(const char *errorMessage, void *context); + + +extern "C" +WINROUTE_LINKAGE +int32_t +WINROUTE_API +WinRoute_EnsureTopMetric( + const wchar_t *deviceAlias, + WinRouteErrorSink errorSink, + void* errorSinkContext +);
\ No newline at end of file diff --git a/windows/winroute/src/winroute/winroute.vcxproj b/windows/winroute/src/winroute/winroute.vcxproj index ca2462750e..cb53e1fc29 100644 --- a/windows/winroute/src/winroute/winroute.vcxproj +++ b/windows/winroute/src/winroute/winroute.vcxproj @@ -20,10 +20,12 @@ </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp" /> + <ClCompile Include="NetworkInterfaces.cpp" /> <ClCompile Include="stdafx.cpp" /> <ClCompile Include="winroute.cpp" /> </ItemGroup> <ItemGroup> + <ClInclude Include="NetworkInterfaces.h" /> <ClInclude Include="stdafx.h" /> <ClInclude Include="targetver.h" /> <ClInclude Include="winroute.h" /> @@ -126,10 +128,13 @@ <ConformanceMode>true</ConformanceMode> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <LanguageStandard>stdcpplatest</LanguageStandard> + <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\windows-libraries\src\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> diff --git a/windows/winroute/src/winroute/winroute.vcxproj.filters b/windows/winroute/src/winroute/winroute.vcxproj.filters index 309944827c..1d8c3d59f5 100644 --- a/windows/winroute/src/winroute/winroute.vcxproj.filters +++ b/windows/winroute/src/winroute/winroute.vcxproj.filters @@ -4,10 +4,12 @@ <ClCompile Include="dllmain.cpp" /> <ClCompile Include="stdafx.cpp" /> <ClCompile Include="winroute.cpp" /> + <ClCompile Include="NetworkInterfaces.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="stdafx.h" /> <ClInclude Include="targetver.h" /> <ClInclude Include="winroute.h" /> + <ClInclude Include="NetworkInterfaces.h" /> </ItemGroup> </Project>
\ No newline at end of file diff --git a/windows/winroute/winroute.sln b/windows/winroute/winroute.sln index 912c71c2f1..28b21fc2f1 100644 --- a/windows/winroute/winroute.sln +++ b/windows/winroute/winroute.sln @@ -3,7 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winroute", "src/winroute/winroute.vcxproj", "{89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winroute", "src\winroute\winroute.vcxproj", "{89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}" + 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 @@ -21,6 +26,14 @@ Global {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x64.Build.0 = Release|x64 {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x86.ActiveCfg = Release|Win32 {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x86.Build.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 |
