summaryrefslogtreecommitdiffhomepage
path: root/windows
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2018-06-12 17:09:10 +0100
committerEmīls <emils@mullvad.net>2018-06-27 11:42:40 +0100
commitd4be5a08de10047ff0bea51f5a8bbdee299b39be (patch)
treea56cd12f0514fe03e9758fdae9f95bd723b1c0ef /windows
parent3ec389495457e5d56b2c19bf9acd37be5e809ee3 (diff)
downloadmullvadvpn-d4be5a08de10047ff0bea51f5a8bbdee299b39be.tar.xz
mullvadvpn-d4be5a08de10047ff0bea51f5a8bbdee299b39be.zip
Add NetworkInterfaces class
Diffstat (limited to 'windows')
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.cpp159
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.h26
-rw-r--r--windows/winroute/src/winroute/winroute.cppbin44 -> 1256 bytes
-rw-r--r--windows/winroute/src/winroute/winroute.h22
-rw-r--r--windows/winroute/src/winroute/winroute.vcxproj5
-rw-r--r--windows/winroute/src/winroute/winroute.vcxproj.filters2
-rw-r--r--windows/winroute/winroute.sln15
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
index 08343afdf7..c28a1a4927 100644
--- a/windows/winroute/src/winroute/winroute.cpp
+++ b/windows/winroute/src/winroute/winroute.cpp
Binary files differ
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