summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-09-11 19:21:39 +0200
committerDavid Lönnhager <david.l@mullvad.net>2020-11-09 14:54:58 +0100
commit8781e5909ff418cb9fc97918b7da328ad148b643 (patch)
treead5c986bbba97a9bc1aa2a44900274329360907c
parentc3921b60fd92e114368e1df07b977ec7178a5e65 (diff)
downloadmullvadvpn-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.rs38
-rw-r--r--windows/winnet/src/winnet/winnet.cpp70
-rw-r--r--windows/winnet/src/winnet/winnet.def1
-rw-r--r--windows/winnet/src/winnet/winnet.h19
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.