diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-09-11 19:21:39 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-11-09 14:54:58 +0100 |
| commit | 8781e5909ff418cb9fc97918b7da328ad148b643 (patch) | |
| tree | ad5c986bbba97a9bc1aa2a44900274329360907c | |
| parent | c3921b60fd92e114368e1df07b977ec7178a5e65 (diff) | |
| download | mullvadvpn-8781e5909ff418cb9fc97918b7da328ad148b643.tar.xz mullvadvpn-8781e5909ff418cb9fc97918b7da328ad148b643.zip | |
Add winnet function for obtaining the IP address given an interface luid
| -rw-r--r-- | talpid-core/src/winnet.rs | 38 | ||||
| -rw-r--r-- | windows/winnet/src/winnet/winnet.cpp | 70 | ||||
| -rw-r--r-- | windows/winnet/src/winnet/winnet.def | 1 | ||||
| -rw-r--r-- | windows/winnet/src/winnet/winnet.h | 19 |
4 files changed, 128 insertions, 0 deletions
diff --git a/talpid-core/src/winnet.rs b/talpid-core/src/winnet.rs index a648aad982..3015369282 100644 --- a/talpid-core/src/winnet.rs +++ b/talpid-core/src/winnet.rs @@ -33,6 +33,10 @@ pub enum Error { #[error(display = "Failed to obtain default route")] GetDefaultRoute, + /// Failed to obtain an IP address given a LUID. + #[error(display = "Failed to obtain IP address for the given interface")] + GetIpAddressFromLuid, + /// Failed to read IPv6 status on the TAP network interface. #[error(display = "Failed to read IPv6 status on the TAP network interface")] GetIpv6Status, @@ -410,6 +414,28 @@ pub fn get_best_default_route( } } +// TODO: Remove attribute once this is in use. +#[allow(dead_code)] +pub fn interface_luid_to_ip( + family: WinNetAddrFamily, + luid: u64, +) -> Result<Option<WinNetIp>, Error> { + let mut ip = WinNetIp::default(); + match unsafe { + WinNet_InterfaceLuidToIpAddress( + family, + luid, + &mut ip as *mut _, + Some(log_sink), + logging_context(), + ) + } { + InterfaceLuidToIpAddressStatus::Success => Ok(Some(ip)), + InterfaceLuidToIpAddressStatus::NotFound => Ok(None), + InterfaceLuidToIpAddressStatus::Failure => Err(Error::GetIpAddressFromLuid), + } +} + pub fn add_device_ip_addresses(iface: &String, addresses: &Vec<IpAddr>) -> bool { let raw_iface = WideCString::from_str(iface) .expect("Failed to convert UTF-8 string to null terminated UCS string") @@ -438,6 +464,7 @@ mod api { Failure = 2, } pub type GetBestDefaultRouteStatus = FailableOptionalStatus; + pub type InterfaceLuidToIpAddressStatus = FailableOptionalStatus; extern "system" { #[link_name = "WinNet_ActivateRouteManager"] @@ -485,6 +512,17 @@ mod api { sink_context: *const u8, ) -> GetBestDefaultRouteStatus; + // TODO: Remove "allow(dead_code)" this is in use. + #[allow(dead_code)] + #[link_name = "WinNet_InterfaceLuidToIpAddress"] + pub fn WinNet_InterfaceLuidToIpAddress( + family: super::WinNetAddrFamily, + luid: u64, + ip: *mut super::WinNetIp, + sink: Option<LogSink>, + sink_context: *const u8, + ) -> InterfaceLuidToIpAddressStatus; + #[link_name = "WinNet_GetTapInterfaceAlias"] pub fn WinNet_GetTapInterfaceAlias( tunnel_interface_alias: *mut *mut wchar_t, diff --git a/windows/winnet/src/winnet/winnet.cpp b/windows/winnet/src/winnet/winnet.cpp index 4532e43d14..343c9e146d 100644 --- a/windows/winnet/src/winnet/winnet.cpp +++ b/windows/winnet/src/winnet/winnet.cpp @@ -9,6 +9,7 @@ #include <libshared/logging/unwind.h>
#include <libshared/network/interfaceutils.h>
#include <libcommon/error.h>
+#include <libcommon/memory.h>
#include <libcommon/valuemapper.h>
#include <libcommon/network.h>
#include <cstdint>
@@ -143,6 +144,75 @@ WinNet_GetBestDefaultRoute( extern "C"
WINNET_LINKAGE
+WINNET_ILTIA_STATUS
+WINNET_API
+WinNet_InterfaceLuidToIpAddress(
+ WINNET_ADDR_FAMILY family,
+ uint64_t interfaceLuid,
+ WINNET_IP *ip,
+ MullvadLogSink logSink,
+ void *logSinkContext
+)
+{
+ try
+ {
+ if (nullptr == ip)
+ {
+ THROW_ERROR("Invalid argument: ip");
+ }
+
+ static const std::pair<WINNET_ADDR_FAMILY, ADDRESS_FAMILY> familyMap[] =
+ {
+ { WINNET_ADDR_FAMILY_IPV4, static_cast<ADDRESS_FAMILY>(AF_INET) },
+ { WINNET_ADDR_FAMILY_IPV6, static_cast<ADDRESS_FAMILY>(AF_INET6) }
+ };
+ const auto win_family = common::ValueMapper::Map<>(family, familyMap);
+
+ MIB_UNICASTIPADDRESS_TABLE *table = nullptr;
+ const auto status = GetUnicastIpAddressTable(win_family, &table);
+
+ if (NO_ERROR != status)
+ {
+ THROW_WINDOWS_ERROR(status, "GetUnicastIpAddressTable");
+ }
+
+ common::memory::ScopeDestructor destructor;
+
+ destructor += [table]() {
+ FreeMibTable(table);
+ };
+
+ for (ULONG i = 0; i < table->NumEntries; i++)
+ {
+ const auto entry = table->Table[i];
+
+ if (interfaceLuid != entry.InterfaceLuid.Value)
+ {
+ continue;
+ }
+
+ // Found IP address
+ const auto ips = winnet::ConvertNativeAddresses(&entry.Address, 1);
+ *ip = ips[0];
+
+ return WINNET_ILTIA_STATUS_SUCCESS;
+ }
+
+ return WINNET_ILTIA_STATUS_NOT_FOUND;
+ }
+ catch (const std::exception & err)
+ {
+ shared::logging::UnwindAndLog(logSink, logSinkContext, err);
+ return WINNET_ILTIA_STATUS_FAILURE;
+ }
+ catch (...)
+ {
+ return WINNET_ILTIA_STATUS_FAILURE;
+ }
+}
+
+extern "C"
+WINNET_LINKAGE
bool
WINNET_API
WinNet_GetTapInterfaceAlias(
diff --git a/windows/winnet/src/winnet/winnet.def b/windows/winnet/src/winnet/winnet.def index 187ce253d9..21bb2725c7 100644 --- a/windows/winnet/src/winnet/winnet.def +++ b/windows/winnet/src/winnet/winnet.def @@ -11,3 +11,4 @@ EXPORTS WinNet_DeactivateRouteManager WinNet_AddDeviceIpAddresses WinNet_GetBestDefaultRoute + WinNet_InterfaceLuidToIpAddress diff --git a/windows/winnet/src/winnet/winnet.h b/windows/winnet/src/winnet/winnet.h index c102ebdba3..8cb5691a60 100644 --- a/windows/winnet/src/winnet/winnet.h +++ b/windows/winnet/src/winnet/winnet.h @@ -205,6 +205,25 @@ WinNet_GetBestDefaultRoute( void *logSinkContext ); +enum WINNET_ILTIA_STATUS +{ + WINNET_ILTIA_STATUS_SUCCESS = 0, + WINNET_ILTIA_STATUS_NOT_FOUND = 1, + WINNET_ILTIA_STATUS_FAILURE = 2, +}; + +extern "C" +WINNET_LINKAGE +WINNET_ILTIA_STATUS +WINNET_API +WinNet_InterfaceLuidToIpAddress( + WINNET_ADDR_FAMILY family, + uint64_t interfaceLuid, + WINNET_IP *ip, + MullvadLogSink logSink, + void *logSinkContext +); + enum WINNET_DEFAULT_ROUTE_CHANGED_EVENT_TYPE { // Best default route changed. |
