diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2018-07-12 19:58:27 +0100 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2018-07-12 19:58:27 +0100 |
| commit | ee7ca9b8987baa11efedb5d320204237aee087fb (patch) | |
| tree | c3d499a32d33bc1d45cf7c9ba5a0048cbf380b2a | |
| parent | a196ecaa4330bc6c3a66520ebd58dee3247f21b2 (diff) | |
| parent | 8d5141b52910a1837730a748703800160a3bbd8a (diff) | |
| download | mullvadvpn-ee7ca9b8987baa11efedb5d320204237aee087fb.tar.xz mullvadvpn-ee7ca9b8987baa11efedb5d320204237aee087fb.zip | |
Merge branch 'windows-support-ipv6-in-winroute'
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/InterfacePair.cpp | 96 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/InterfacePair.h | 25 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/NetworkInterfaces.cpp | 64 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/NetworkInterfaces.h | 7 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.cpp | 4 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.h | 8 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.vcxproj | 2 | ||||
| -rw-r--r-- | windows/winroute/src/winroute/winroute.vcxproj.filters | 2 |
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" /> |
