summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2018-07-12 19:58:27 +0100
committerEmīls Piņķis <emils@mullvad.net>2018-07-12 19:58:27 +0100
commitee7ca9b8987baa11efedb5d320204237aee087fb (patch)
treec3d499a32d33bc1d45cf7c9ba5a0048cbf380b2a
parenta196ecaa4330bc6c3a66520ebd58dee3247f21b2 (diff)
parent8d5141b52910a1837730a748703800160a3bbd8a (diff)
downloadmullvadvpn-ee7ca9b8987baa11efedb5d320204237aee087fb.tar.xz
mullvadvpn-ee7ca9b8987baa11efedb5d320204237aee087fb.zip
Merge branch 'windows-support-ipv6-in-winroute'
-rw-r--r--CHANGELOG.md1
-rw-r--r--windows/winroute/src/winroute/InterfacePair.cpp96
-rw-r--r--windows/winroute/src/winroute/InterfacePair.h25
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.cpp64
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.h7
-rw-r--r--windows/winroute/src/winroute/winroute.cpp4
-rw-r--r--windows/winroute/src/winroute/winroute.h8
-rw-r--r--windows/winroute/src/winroute/winroute.vcxproj2
-rw-r--r--windows/winroute/src/winroute/winroute.vcxproj.filters2
9 files changed, 144 insertions, 65 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1f8b2da04..91894b7662 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,7 @@ Line wrap the file at 100 chars. Th
#### Windows
- Rename tunnel interface to "Mullvad".
+- Change tunnel interface metric for both IPv4 and IPv6.
### Fixed
- Disable account input when logging in.
diff --git a/windows/winroute/src/winroute/InterfacePair.cpp b/windows/winroute/src/winroute/InterfacePair.cpp
new file mode 100644
index 0000000000..eda7dd8314
--- /dev/null
+++ b/windows/winroute/src/winroute/InterfacePair.cpp
@@ -0,0 +1,96 @@
+#include "stdafx.h"
+#include "InterfacePair.h"
+
+#include <sstream>
+#include <stdexcept>
+
+#ifndef STATUS_NOT_FOUND
+#define STATUS_NOT_FOUND 0xC0000225
+#endif
+
+InterfacePair::InterfacePair(NET_LUID interface_luid)
+{
+ IPv4Iface.Family = AF_INET;
+ IPv4Iface.InterfaceLuid = interface_luid;
+ InitializeInterface(&IPv4Iface);
+
+ IPv6Iface.Family = AF_INET6;
+ IPv6Iface.InterfaceLuid = interface_luid;
+ InitializeInterface(&IPv6Iface);
+
+ if (!(HasIPv4() || HasIPv6())) {
+ std::stringstream ss;
+ ss << L"LUID "
+ << interface_luid.Value
+ << " does not specify any IPv4 or IPv6 interfaces";
+ throw std::runtime_error(ss.str());
+ }
+}
+
+int InterfacePair::HighestMetric()
+{
+ return IPv6Iface.Metric < IPv4Iface.Metric ? IPv4Iface.Metric : IPv6Iface.Metric;
+}
+
+void InterfacePair::SetMetric(int metric)
+{
+ if (HasIPv4())
+ {
+ IPv4Iface.SitePrefixLength = 0;
+ IPv4Iface.Metric = metric;
+ IPv4Iface.UseAutomaticMetric = false;
+ SetInterface(&IPv4Iface);
+ }
+
+ if (HasIPv6())
+ {
+ IPv6Iface.Metric = metric;
+ IPv6Iface.UseAutomaticMetric = false;
+ SetInterface(&IPv6Iface);
+ }
+}
+
+void InterfacePair::SetInterface(PMIB_IPINTERFACE_ROW iface) {
+
+ DWORD status = SetIpInterfaceEntry(iface);
+ if (status != NO_ERROR)
+ {
+ std::stringstream ss;
+ ss << L"Failed to set metric for "
+ << (iface->Family == AF_INET ? "IPv4" : "IPv6")
+ << " interface with LUID"
+ << iface->InterfaceLuid.Value
+ << " with error code "
+ << status;
+ throw std::runtime_error(ss.str());
+ }
+}
+
+bool InterfacePair::HasIPv4()
+{
+ return IPv4Iface.Family != AF_UNSPEC;
+}
+
+bool InterfacePair::HasIPv6()
+{
+ return IPv6Iface.Family != AF_UNSPEC;
+}
+
+void InterfacePair::InitializeInterface(PMIB_IPINTERFACE_ROW iface)
+{
+ DWORD status = GetIpInterfaceEntry(iface);
+
+ if (status != NO_ERROR) {
+ if (status == STATUS_NOT_FOUND) {
+ iface->Family = AF_UNSPEC;
+ }
+ else {
+ std::stringstream ss;
+ ss << L"Failed get network interface with LUID "
+ << &iface->InterfaceLuid.Value
+ << ": "
+ << status;
+ throw std::runtime_error(ss.str());
+ }
+ }
+}
diff --git a/windows/winroute/src/winroute/InterfacePair.h b/windows/winroute/src/winroute/InterfacePair.h
new file mode 100644
index 0000000000..3926ba0430
--- /dev/null
+++ b/windows/winroute/src/winroute/InterfacePair.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <winsock2.h>
+#include <ws2ipdef.h>
+#include <iphlpapi.h>
+#include <netioapi.h>
+
+class InterfacePair
+{
+public:
+ InterfacePair(NET_LUID interface_luid);
+ int HighestMetric();
+ void SetMetric(int metric);
+
+
+private:
+ MIB_IPINTERFACE_ROW IPv4Iface;
+ MIB_IPINTERFACE_ROW IPv6Iface;
+
+ void InitializeInterface(PMIB_IPINTERFACE_ROW iface);
+ bool HasIPv4();
+ bool HasIPv6();
+ void SetInterface(PMIB_IPINTERFACE_ROW iface);
+
+};
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.cpp b/windows/winroute/src/winroute/NetworkInterfaces.cpp
index 4b2bc9319f..f80c2f5f3b 100644
--- a/windows/winroute/src/winroute/NetworkInterfaces.cpp
+++ b/windows/winroute/src/winroute/NetworkInterfaces.cpp
@@ -1,8 +1,7 @@
#include "stdafx.h"
-#include <windows.h>
-
#include "NetworkInterfaces.h"
+#include "InterfacePair.h"
#include <memory>
#include <sstream>
@@ -14,21 +13,6 @@
-
-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)
@@ -43,7 +27,7 @@ bool NetworkInterfaces::HasHighestMetric(PMIB_IPINTERFACE_ROW targetIface)
}
-void NetworkInterfaces::EnsureIfaceMetricIsHighest(PMIB_IPINTERFACE_ROW targetIface)
+void NetworkInterfaces::EnsureIfaceMetricIsHighest(NET_LUID interfaceLuid)
{
PMIB_IPINTERFACE_ROW iface;
DWORD success = 0;
@@ -51,15 +35,11 @@ void NetworkInterfaces::EnsureIfaceMetricIsHighest(PMIB_IPINTERFACE_ROW targetIf
{
iface = &mInterfaces->Table[i];
// Ignoring the target interface.
- if (iface->InterfaceLuid.Value == targetIface->InterfaceLuid.Value)
+ if (iface->InterfaceLuid.Value == interfaceLuid.Value || iface->UseAutomaticMetric || iface->Metric > MAX_METRIC)
{
continue;
}
- if (iface->UseAutomaticMetric)
- {
- continue;
- }
iface->Metric++;
if (iface->Family == AF_INET) {
iface->SitePrefixLength = 0;
@@ -92,7 +72,7 @@ NetworkInterfaces::NetworkInterfaces()
}
}
-bool NetworkInterfaces::SetTopMetricForInterfaceByAlias(const wchar_t * deviceAlias)
+bool NetworkInterfaces::SetTopMetricForInterfacesByAlias(const wchar_t * deviceAlias)
{
NET_LUID targetIfaceLuid;
DWORD success = 0;
@@ -106,45 +86,19 @@ bool NetworkInterfaces::SetTopMetricForInterfaceByAlias(const wchar_t * deviceAl
<< success;
throw std::runtime_error(common::string::ToAnsi(ss.str()));
}
- return SetTopMetricForInterfaceWithLuid(targetIfaceLuid);
+ return SetTopMetricForInterfacesWithLuid(targetIfaceLuid);
}
-bool NetworkInterfaces::SetTopMetricForInterfaceWithLuid(NET_LUID targetIfaceId)
+bool NetworkInterfaces::SetTopMetricForInterfacesWithLuid(NET_LUID targetIfaceId)
{
+ InterfacePair targetInterfaces = InterfacePair(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)
+ if (targetInterfaces.HighestMetric() == 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());
- }
+ targetInterfaces.SetMetric(MAX_METRIC);
return true;
}
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.h b/windows/winroute/src/winroute/NetworkInterfaces.h
index 66cea53fc0..b29ce0fa44 100644
--- a/windows/winroute/src/winroute/NetworkInterfaces.h
+++ b/windows/winroute/src/winroute/NetworkInterfaces.h
@@ -12,14 +12,13 @@ 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:
+ void EnsureIfaceMetricIsHighest(NET_LUID interfaceLuid);
NetworkInterfaces();
- bool SetTopMetricForInterfaceByAlias (const wchar_t *deviceAlias);
- bool SetTopMetricForInterfaceWithLuid(NET_LUID targetIface);
+ bool SetTopMetricForInterfacesByAlias(const wchar_t *deviceAlias);
+ bool SetTopMetricForInterfacesWithLuid(NET_LUID targetIface);
~NetworkInterfaces();
};
diff --git a/windows/winroute/src/winroute/winroute.cpp b/windows/winroute/src/winroute/winroute.cpp
index fe5d82d3c3..c417bd44ea 100644
--- a/windows/winroute/src/winroute/winroute.cpp
+++ b/windows/winroute/src/winroute/winroute.cpp
@@ -17,10 +17,10 @@ WinRoute_EnsureTopMetric(
try
{
NetworkInterfaces interfaces;
- bool metrics_set = interfaces.SetTopMetricForInterfaceByAlias(deviceAlias);
+ bool metrics_set = interfaces.SetTopMetricForInterfacesByAlias(deviceAlias);
return metrics_set ? WINROUTE_STATUS::METRIC_SET : WINROUTE_STATUS::METRIC_NO_CHANGE;
}
- catch (std::exception &err)
+ catch (std::exception &err)
{
if (nullptr != errorSink)
{
diff --git a/windows/winroute/src/winroute/winroute.h b/windows/winroute/src/winroute/winroute.h
index 593108936e..6bf0c3b882 100644
--- a/windows/winroute/src/winroute/winroute.h
+++ b/windows/winroute/src/winroute/winroute.h
@@ -24,7 +24,7 @@ WINROUTE_LINKAGE
WINROUTE_STATUS
WINROUTE_API
WinRoute_EnsureTopMetric(
- const wchar_t *deviceAlias,
- WinRouteErrorSink errorSink,
- void* errorSinkContext
-); \ No newline at end of file
+ const wchar_t *deviceAlias,
+ WinRouteErrorSink errorSink,
+ void* errorSinkContext
+);
diff --git a/windows/winroute/src/winroute/winroute.vcxproj b/windows/winroute/src/winroute/winroute.vcxproj
index 1ed84cd53c..09efb76938 100644
--- a/windows/winroute/src/winroute/winroute.vcxproj
+++ b/windows/winroute/src/winroute/winroute.vcxproj
@@ -20,11 +20,13 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="InterfacePair.cpp" />
<ClCompile Include="NetworkInterfaces.cpp" />
<ClCompile Include="stdafx.cpp" />
<ClCompile Include="winroute.cpp" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="InterfacePair.h" />
<ClInclude Include="NetworkInterfaces.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
diff --git a/windows/winroute/src/winroute/winroute.vcxproj.filters b/windows/winroute/src/winroute/winroute.vcxproj.filters
index 62487f561b..216502d069 100644
--- a/windows/winroute/src/winroute/winroute.vcxproj.filters
+++ b/windows/winroute/src/winroute/winroute.vcxproj.filters
@@ -5,12 +5,14 @@
<ClCompile Include="stdafx.cpp" />
<ClCompile Include="winroute.cpp" />
<ClCompile Include="NetworkInterfaces.cpp" />
+ <ClCompile Include="InterfacePair.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="winroute.h" />
<ClInclude Include="NetworkInterfaces.h" />
+ <ClInclude Include="InterfacePair.h" />
</ItemGroup>
<ItemGroup>
<None Include="winroute.def" />