diff options
| author | David Lönnhager <david.l@mullvad.net> | 2021-09-16 12:13:02 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2021-09-17 14:35:26 +0200 |
| commit | 1d30a20d5e4125846d50ce818e5a27fe15920192 (patch) | |
| tree | 5c74a78e6bd0a25d3f276c5944364a70605b0039 | |
| parent | 3a9ed2a87e12545ab7ff4debe797672f75397e9e (diff) | |
| download | mullvadvpn-1d30a20d5e4125846d50ce818e5a27fe15920192.tar.xz mullvadvpn-1d30a20d5e4125846d50ce818e5a27fe15920192.zip | |
Generalize networking code in openvpn monitor
| -rw-r--r-- | talpid-core/src/tunnel/openvpn/mod.rs | 62 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/windows.rs | 45 |
2 files changed, 57 insertions, 50 deletions
diff --git a/talpid-core/src/tunnel/openvpn/mod.rs b/talpid-core/src/tunnel/openvpn/mod.rs index 8ae967975a..22d9147adc 100644 --- a/talpid-core/src/tunnel/openvpn/mod.rs +++ b/talpid-core/src/tunnel/openvpn/mod.rs @@ -15,11 +15,7 @@ use lazy_static::lazy_static; #[cfg(target_os = "linux")] use std::collections::{HashMap, HashSet}; #[cfg(windows)] -use std::{ - ffi::{OsStr, OsString}, - os::windows::ffi::OsStrExt, - time::Instant, -}; +use std::{ffi::OsString, time::Instant}; use std::{ fs, io::{self, Write}, @@ -42,10 +38,7 @@ use widestring::U16CString; use winapi::shared::{ guiddef::GUID, ifdef::NET_LUID, - netioapi::{ - ConvertInterfaceAliasToLuid, FreeMibTable, GetUnicastIpAddressEntry, - GetUnicastIpAddressTable, MIB_UNICASTIPADDRESS_ROW, MIB_UNICASTIPADDRESS_TABLE, - }, + netioapi::{GetUnicastIpAddressEntry, MIB_UNICASTIPADDRESS_ROW}, nldef::{IpDadStatePreferred, IpDadStateTentative, NL_DAD_STATE}, winerror::NO_ERROR, ws2def::AF_UNSPEC, @@ -1241,44 +1234,17 @@ mod event_server { #[cfg(windows)] fn wait_for_ready_device(alias: &str) -> Result<()> { // Obtain luid for alias - let alias_wide: Vec<u16> = OsStr::new(alias) - .encode_wide() - .chain(std::iter::once(0u16)) - .collect(); - - let mut luid: NET_LUID = unsafe { std::mem::zeroed() }; - let status = unsafe { ConvertInterfaceAliasToLuid(alias_wide.as_ptr(), &mut luid) }; - if status != NO_ERROR { - return Err(Error::NoDeviceLuid(io::Error::last_os_error())); - } + let luid = crate::tunnel::windows::luid_from_alias(alias).map_err(Error::NoDeviceLuid)?; // Obtain unicast IP addresses - let mut unicast_rows = vec![]; - - unsafe { - let mut unicast_table: *mut MIB_UNICASTIPADDRESS_TABLE = std::ptr::null_mut(); - - let status = GetUnicastIpAddressTable(AF_UNSPEC as u16, &mut unicast_table); - if status != NO_ERROR { - return Err(Error::ObtainUnicastAddress(io::Error::last_os_error())); - } - - if (*unicast_table).NumEntries == 0 { - FreeMibTable(unicast_table as *mut _); - return Err(Error::NoUnicastAddress); - } - - let first_row = &(*unicast_table).Table[0] as *const MIB_UNICASTIPADDRESS_ROW; - - for i in 0..(*unicast_table).NumEntries { - let row = first_row.offset(i as isize); - if (*row).InterfaceLuid.Value != luid.Value { - continue; - } - unicast_rows.push(*row); - } - - FreeMibTable(unicast_table as *mut _); + let mut unicast_rows: Vec<MIB_UNICASTIPADDRESS_ROW> = + crate::tunnel::windows::get_unicast_table(AF_UNSPEC as u16) + .map_err(Error::ObtainUnicastAddress)? + .into_iter() + .filter(|row| row.InterfaceLuid.Value == luid.Value) + .collect(); + if unicast_rows.is_empty() { + return Err(Error::NoUnicastAddress); } // Poll DAD status using GetUnicastIpAddressEntry @@ -1289,9 +1255,11 @@ fn wait_for_ready_device(alias: &str) -> Result<()> { let mut ready = true; for row in &mut unicast_rows { - let status = unsafe { GetUnicastIpAddressEntry(row as *mut _) }; + let status = unsafe { GetUnicastIpAddressEntry(row) }; if status != NO_ERROR { - return Err(Error::ObtainUnicastAddress(io::Error::last_os_error())); + return Err(Error::ObtainUnicastAddress(io::Error::from_raw_os_error( + status as i32, + ))); } if row.DadState == IpDadStateTentative { ready = false; diff --git a/talpid-core/src/tunnel/windows.rs b/talpid-core/src/tunnel/windows.rs index 2d4fcf85e5..53fac1bca4 100644 --- a/talpid-core/src/tunnel/windows.rs +++ b/talpid-core/src/tunnel/windows.rs @@ -1,9 +1,15 @@ -use std::{io, mem, os::windows::io::RawHandle, sync::Mutex}; +use std::{ + ffi::OsStr, + io, mem, + os::windows::{ffi::OsStrExt, io::RawHandle}, + sync::Mutex, +}; use winapi::shared::{ ifdef::NET_LUID, netioapi::{ - CancelMibChangeNotify2, GetIpInterfaceEntry, MibAddInstance, NotifyIpInterfaceChange, - MIB_IPINTERFACE_ROW, + CancelMibChangeNotify2, ConvertInterfaceAliasToLuid, FreeMibTable, GetIpInterfaceEntry, + GetUnicastIpAddressTable, MibAddInstance, NotifyIpInterfaceChange, MIB_IPINTERFACE_ROW, + MIB_UNICASTIPADDRESS_ROW, MIB_UNICASTIPADDRESS_TABLE, }, ntdef::FALSE, winerror::{ERROR_NOT_FOUND, NO_ERROR}, @@ -131,3 +137,36 @@ pub async fn wait_for_interfaces(luid: NET_LUID, ipv4: bool, ipv6: bool) -> io:: let _ = rx.await; Ok(()) } + +/// Returns the unicast IP address table. +pub fn get_unicast_table(family: u16) -> io::Result<Vec<MIB_UNICASTIPADDRESS_ROW>> { + let mut unicast_rows = vec![]; + let mut unicast_table: *mut MIB_UNICASTIPADDRESS_TABLE = std::ptr::null_mut(); + + let status = unsafe { GetUnicastIpAddressTable(family, &mut unicast_table) }; + if status != NO_ERROR { + return Err(io::Error::from_raw_os_error(status as i32)); + } + let first_row = unsafe { &(*unicast_table).Table[0] } as *const MIB_UNICASTIPADDRESS_ROW; + for i in 0..unsafe { *unicast_table }.NumEntries { + unicast_rows.push(unsafe { *(first_row.offset(i as isize)) }); + } + unsafe { FreeMibTable(unicast_table as *mut _) }; + + Ok(unicast_rows) +} + +/// Returns the LUID of an interface given its alias. +pub fn luid_from_alias<T: AsRef<OsStr>>(alias: T) -> io::Result<NET_LUID> { + let alias_wide: Vec<u16> = alias + .as_ref() + .encode_wide() + .chain(std::iter::once(0u16)) + .collect(); + let mut luid: NET_LUID = unsafe { std::mem::zeroed() }; + let status = unsafe { ConvertInterfaceAliasToLuid(alias_wide.as_ptr(), &mut luid) }; + if status != NO_ERROR { + return Err(io::Error::from_raw_os_error(status as i32)); + } + Ok(luid) +} |
