summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-09-16 12:13:02 +0200
committerDavid Lönnhager <david.l@mullvad.net>2021-09-17 14:35:26 +0200
commit1d30a20d5e4125846d50ce818e5a27fe15920192 (patch)
tree5c74a78e6bd0a25d3f276c5944364a70605b0039
parent3a9ed2a87e12545ab7ff4debe797672f75397e9e (diff)
downloadmullvadvpn-1d30a20d5e4125846d50ce818e5a27fe15920192.tar.xz
mullvadvpn-1d30a20d5e4125846d50ce818e5a27fe15920192.zip
Generalize networking code in openvpn monitor
-rw-r--r--talpid-core/src/tunnel/openvpn/mod.rs62
-rw-r--r--talpid-core/src/tunnel/windows.rs45
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)
+}