diff options
| author | David Lönnhager <david.l@mullvad.net> | 2021-09-03 11:09:01 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2021-09-28 12:41:49 +0200 |
| commit | 2d475611604e7b1271a2e3b8b2873e7590e2be76 (patch) | |
| tree | 259a50b1460243b26134023982f5bb3ba6c95dfb | |
| parent | bccc5247f7f3b9eec70a51710f2621b3a29d9125 (diff) | |
| download | mullvadvpn-2d475611604e7b1271a2e3b8b2873e7590e2be76.tar.xz mullvadvpn-2d475611604e7b1271a2e3b8b2873e7590e2be76.zip | |
Move generic network functions out of wireguard_nt mod
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_nt.rs | 168 | ||||
| -rw-r--r-- | talpid-core/src/windows.rs | 136 |
2 files changed, 164 insertions, 140 deletions
diff --git a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs index 8f8206aa3a..723e3f00d0 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs @@ -4,13 +4,13 @@ use super::{ stats::{Stats, StatsMap}, Tunnel, }; +use crate::windows; use bitflags::bitflags; use ipnetwork::IpNetwork; use lazy_static::lazy_static; use std::{ ffi::CStr, fmt, io, iter, mem, - net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, os::windows::{ffi::OsStrExt, io::RawHandle}, path::Path, ptr, @@ -248,12 +248,12 @@ impl PartialEq for WgAllowedIp { } match self.address_family as i32 { AF_INET => { - inaddr_to_ipaddr(unsafe { self.address.v4 }) - == inaddr_to_ipaddr(unsafe { other.address.v4 }) + windows::ipaddr_from_inaddr(unsafe { self.address.v4 }) + == windows::ipaddr_from_inaddr(unsafe { other.address.v4 }) } AF_INET6 => { - in6addr_to_ipaddr(unsafe { self.address.v6 }) - == in6addr_to_ipaddr(unsafe { other.address.v6 }) + windows::ipaddr_from_in6addr(unsafe { self.address.v6 }) + == windows::ipaddr_from_in6addr(unsafe { other.address.v6 }) } _ => { log::error!("Allowed IP uses unknown address family"); @@ -268,8 +268,14 @@ impl fmt::Debug for WgAllowedIp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("WgAllowedIp"); match self.address_family as i32 { - AF_INET => s.field("address", &inaddr_to_ipaddr(unsafe { self.address.v4 })), - AF_INET6 => s.field("address", &in6addr_to_ipaddr(unsafe { self.address.v6 })), + AF_INET => s.field( + "address", + &windows::ipaddr_from_inaddr(unsafe { self.address.v4 }), + ), + AF_INET6 => s.field( + "address", + &windows::ipaddr_from_in6addr(unsafe { self.address.v6 }), + ), _ => s.field("address", &"<unknown>"), }; s.field("address_family", &self.address_family) @@ -320,7 +326,7 @@ impl From<SOCKADDR_INET> for SockAddrInet { } impl PartialEq for SockAddrInet { fn eq(&self, other: &Self) -> bool { - let self_addr = match try_sockaddr_to_socket_address(self.addr) { + let self_addr = match windows::try_socketaddr_from_inet_sockaddr(self.addr) { Ok(addr) => addr, Err(error) => { log::error!( @@ -330,7 +336,7 @@ impl PartialEq for SockAddrInet { return true; } }; - let other_addr = match try_sockaddr_to_socket_address(other.addr) { + let other_addr = match windows::try_socketaddr_from_inet_sockaddr(other.addr) { Ok(addr) => addr, Err(error) => { log::error!( @@ -348,7 +354,7 @@ impl Eq for SockAddrInet {} impl fmt::Debug for SockAddrInet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("SockAddrInet"); - let self_addr = try_sockaddr_to_socket_address(self.addr) + let self_addr = windows::try_socketaddr_from_inet_sockaddr(self.addr) .map(|addr| addr.to_string()) .unwrap_or("<unknown>".to_string()); s.field("addr", &self_addr).finish() @@ -881,7 +887,7 @@ fn serialize_config(config: &Config) -> Result<Vec<u8>> { public_key: peer.public_key.as_bytes().clone(), preshared_key: [0u8; WIREGUARD_KEY_LENGTH], persistent_keepalive: 0, - endpoint: convert_socket_address(peer.endpoint).into(), + endpoint: windows::inet_sockaddr_from_socketaddr(peer.endpoint).into(), tx_bytes: 0, rx_bytes: 0, last_handshake: 0, @@ -897,10 +903,10 @@ fn serialize_config(config: &Config) -> Result<Vec<u8>> { }; let address = match allowed_ip { IpNetwork::V4(v4_network) => WgIpAddr { - v4: convert_v4_address(v4_network.ip()), + v4: windows::inaddr_from_ipaddr(v4_network.ip()), }, IpNetwork::V6(v6_network) => WgIpAddr { - v6: convert_v6_address(v6_network.ip()), + v6: windows::in6addr_from_ipaddr(v6_network.ip()), }, }; @@ -973,96 +979,14 @@ unsafe fn deserialize_config( Ok((interface, peers)) } -fn convert_v4_address(addr: Ipv4Addr) -> IN_ADDR { - let mut in_addr: IN_ADDR = unsafe { mem::zeroed() }; - let addr_octets = addr.octets(); - unsafe { - ptr::copy_nonoverlapping( - &addr_octets as *const _, - in_addr.S_un.S_addr_mut() as *mut _ as *mut u8, - addr_octets.len(), - ); - } - in_addr -} - -fn convert_v6_address(addr: Ipv6Addr) -> IN6_ADDR { - let mut in_addr: IN6_ADDR = unsafe { mem::zeroed() }; - let addr_octets = addr.octets(); - unsafe { - ptr::copy_nonoverlapping( - &addr_octets as *const _, - in_addr.u.Byte_mut() as *mut _, - addr_octets.len(), - ); - } - in_addr -} - -fn convert_socket_address(addr: SocketAddr) -> SOCKADDR_INET { - let mut sockaddr: SOCKADDR_INET = unsafe { mem::zeroed() }; - - match addr { - SocketAddr::V4(v4_addr) => { - unsafe { - *sockaddr.si_family_mut() = AF_INET as u16; - } - - let mut v4sockaddr = unsafe { sockaddr.Ipv4_mut() }; - v4sockaddr.sin_family = AF_INET as u16; - v4sockaddr.sin_port = v4_addr.port().to_be(); - v4sockaddr.sin_addr = convert_v4_address(*v4_addr.ip()); - } - SocketAddr::V6(v6_addr) => { - unsafe { - *sockaddr.si_family_mut() = AF_INET6 as u16; - } - - let mut v6sockaddr = unsafe { sockaddr.Ipv6_mut() }; - v6sockaddr.sin6_family = AF_INET6 as u16; - v6sockaddr.sin6_port = v6_addr.port().to_be(); - v6sockaddr.sin6_addr = convert_v6_address(*v6_addr.ip()); - v6sockaddr.sin6_flowinfo = v6_addr.flowinfo(); - *unsafe { v6sockaddr.u.sin6_scope_id_mut() } = v6_addr.scope_id(); - } - } - - sockaddr -} - -fn inaddr_to_ipaddr(addr: IN_ADDR) -> Ipv4Addr { - Ipv4Addr::from(unsafe { *(addr.S_un.S_addr()) }.to_be()) -} - -fn in6addr_to_ipaddr(addr: IN6_ADDR) -> Ipv6Addr { - Ipv6Addr::from(*unsafe { addr.u.Byte() }) -} - -fn try_sockaddr_to_socket_address(addr: SOCKADDR_INET) -> Result<SocketAddr> { - unsafe { - match *addr.si_family() as i32 { - AF_INET => Ok(SocketAddr::V4(SocketAddrV4::new( - inaddr_to_ipaddr(addr.Ipv4().sin_addr), - u16::from_be(addr.Ipv4().sin_port), - ))), - AF_INET6 => Ok(SocketAddr::V6(SocketAddrV6::new( - in6addr_to_ipaddr(addr.Ipv6().sin6_addr), - u16::from_be(addr.Ipv6().sin6_port), - addr.Ipv6().sin6_flowinfo, - *addr.Ipv6().u.sin6_scope_id(), - ))), - family => Err(Error::UnknownAddressFamily(family)), - } - } -} - fn set_interface_mtu(luid: &NET_LUID, family: u16, mtu: u32) -> io::Result<()> { - let family = crate::tunnel::windows::AddressFamily::try_from_af_family(family) - .map_err(|error| io::Error::new(io::ErrorKind::InvalidInput, error))?; - let mut iface = crate::tunnel::windows::get_ip_interface_entry(family, luid)?; + let family = windows::AddressFamily::try_from_af_family(family).map_err(|error| { + io::Error::new(io::ErrorKind::InvalidInput, error) + })?; + let mut iface = windows::get_ip_interface_entry(family, luid)?; iface.SitePrefixLength = 0; iface.NlMtu = mtu; - crate::tunnel::windows::set_ip_interface_entry(&iface) + windows::set_ip_interface_entry(&iface) } impl Tunnel for WgNtTunnel { @@ -1168,7 +1092,8 @@ mod tests { public_key: WG_PUBLIC_KEY.as_bytes().clone(), preshared_key: [0; WIREGUARD_KEY_LENGTH], persistent_keepalive: 0, - endpoint: convert_socket_address("1.2.3.4:1234".parse().unwrap()).into(), + endpoint: windows::inet_sockaddr_from_socketaddr("1.2.3.4:1234".parse().unwrap()) + .into(), tx_bytes: 0, rx_bytes: 0, last_handshake: 0, @@ -1176,7 +1101,7 @@ mod tests { }, p0_allowed_ip_0: WgAllowedIp { address: WgIpAddr { - v4: convert_v4_address("1.3.3.0".parse().unwrap()), + v4: windows::inaddr_from_ipaddr("1.3.3.0".parse().unwrap()), }, address_family: AF_INET as u16, cidr: 24, @@ -1194,29 +1119,6 @@ mod tests { } #[test] - fn test_sockaddr_v4() { - let addr_v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 1234)); - assert_eq!( - addr_v4, - try_sockaddr_to_socket_address(convert_socket_address(addr_v4)).unwrap() - ); - } - - #[test] - fn test_sockaddr_v6() { - let addr_v6 = SocketAddr::V6(SocketAddrV6::new( - Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), - 1234, - 0xa, - 0xb, - )); - assert_eq!( - addr_v6, - try_sockaddr_to_socket_address(convert_socket_address(addr_v6)).unwrap() - ); - } - - #[test] fn test_config_serialization() { let serialized_data = serialize_config(&*WG_CONFIG).unwrap(); assert_eq!(mem::size_of::<Interface>(), serialized_data.len()); @@ -1241,7 +1143,7 @@ mod tests { // Valid: /32 prefix let address_family = AF_INET as u16; let address = WgIpAddr { - v4: convert_v4_address("127.0.0.1".parse().unwrap()), + v4: windows::inaddr_from_ipaddr("127.0.0.1".parse().unwrap()), }; let cidr = 32; WgAllowedIp::new(address, address_family, cidr).unwrap(); @@ -1249,21 +1151,21 @@ mod tests { // Invalid host bits let cidr = 24; let address = WgIpAddr { - v4: convert_v4_address("0.0.0.1".parse().unwrap()), + v4: windows::inaddr_from_ipaddr("0.0.0.1".parse().unwrap()), }; assert!(WgAllowedIp::new(address, address_family, cidr).is_err()); // Valid host bits let cidr = 24; let address = WgIpAddr { - v4: convert_v4_address("255.255.255.0".parse().unwrap()), + v4: windows::inaddr_from_ipaddr("255.255.255.0".parse().unwrap()), }; WgAllowedIp::new(address, address_family, cidr).unwrap(); // 0.0.0.0/0 let cidr = 0; let address = WgIpAddr { - v4: convert_v4_address("0.0.0.0".parse().unwrap()), + v4: windows::inaddr_from_ipaddr("0.0.0.0".parse().unwrap()), }; WgAllowedIp::new(address, address_family, cidr).unwrap(); @@ -1277,7 +1179,7 @@ mod tests { // Valid: /128 prefix let address_family = AF_INET6 as u16; let address = WgIpAddr { - v6: convert_v6_address("::1".parse().unwrap()), + v6: windows::in6addr_from_ipaddr("::1".parse().unwrap()), }; let cidr = 128; WgAllowedIp::new(address, address_family, cidr).unwrap(); @@ -1288,14 +1190,16 @@ mod tests { // Valid host bits let address = WgIpAddr { - v6: convert_v6_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe".parse().unwrap()), + v6: windows::in6addr_from_ipaddr( + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe".parse().unwrap(), + ), }; WgAllowedIp::new(address, address_family, cidr).unwrap(); // ::/0 let cidr = 0; let address = WgIpAddr { - v6: convert_v6_address("::".parse().unwrap()), + v6: windows::in6addr_from_ipaddr("::".parse().unwrap()), }; WgAllowedIp::new(address, address_family, cidr).unwrap(); diff --git a/talpid-core/src/windows.rs b/talpid-core/src/windows.rs index e0667aa092..e39bb1037e 100644 --- a/talpid-core/src/windows.rs +++ b/talpid-core/src/windows.rs @@ -2,11 +2,15 @@ use std::{ ffi::OsStr, fmt, io, mem, os::windows::{ffi::OsStrExt, io::RawHandle}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, + ptr, sync::Mutex, time::{Duration, Instant}, }; use winapi::shared::{ ifdef::NET_LUID, + in6addr::IN6_ADDR, + inaddr::IN_ADDR, netioapi::{ CancelMibChangeNotify2, ConvertInterfaceAliasToLuid, FreeMibTable, GetIpInterfaceEntry, GetUnicastIpAddressEntry, GetUnicastIpAddressTable, MibAddInstance, @@ -17,6 +21,7 @@ use winapi::shared::{ ntdef::FALSE, winerror::{ERROR_NOT_FOUND, NO_ERROR}, ws2def::{AF_INET, AF_INET6, AF_UNSPEC}, + ws2ipdef::SOCKADDR_INET, }; /// Result type for this module. @@ -58,6 +63,10 @@ pub enum Error { #[cfg(windows)] #[error(display = "Unicast channel sender was unexpectedly dropped")] UnicastSenderDropped, + + /// Unknown address family + #[error(display = "Unknown address family: {}", _0)] + UnknownAddressFamily(i32), } /// Address family. These correspond to the `AF_*` constants. @@ -78,15 +87,9 @@ impl fmt::Display for AddressFamily { } } -#[derive(err_derive::Error, Debug)] -pub enum Error { - /// Unknown address family - #[error(display = "Unknown address family: {}", _0)] - UnknownAddressFamily(i32), -} - impl AddressFamily { - pub fn try_from_af_family(family: u16) -> Result<AddressFamily, Error> { + /// Convert an [`AddressFamily`] to one of the `AF_*` constants. + pub fn try_from_af_family(family: u16) -> Result<AddressFamily> { match family as i32 { AF_INET => Ok(AddressFamily::Ipv4), AF_INET6 => Ok(AddressFamily::Ipv6), @@ -358,3 +361,120 @@ fn af_family_from_family(family: Option<AddressFamily>) -> u16 { .map(|family| family as u16) .unwrap_or(AF_UNSPEC as u16) } + +/// Converts an `Ipv4Addr` to `IN_ADDR` +pub fn inaddr_from_ipaddr(addr: Ipv4Addr) -> IN_ADDR { + let mut in_addr: IN_ADDR = unsafe { mem::zeroed() }; + let addr_octets = addr.octets(); + unsafe { + ptr::copy_nonoverlapping( + &addr_octets as *const _, + in_addr.S_un.S_addr_mut() as *mut _ as *mut u8, + addr_octets.len(), + ); + } + in_addr +} + +/// Converts an `Ipv6Addr` to `IN6_ADDR` +pub fn in6addr_from_ipaddr(addr: Ipv6Addr) -> IN6_ADDR { + let mut in_addr: IN6_ADDR = unsafe { mem::zeroed() }; + let addr_octets = addr.octets(); + unsafe { + ptr::copy_nonoverlapping( + &addr_octets as *const _, + in_addr.u.Byte_mut() as *mut _, + addr_octets.len(), + ); + } + in_addr +} + +/// Converts an `IN_ADDR` to `Ipv4Addr` +pub fn ipaddr_from_inaddr(addr: IN_ADDR) -> Ipv4Addr { + Ipv4Addr::from(unsafe { *(addr.S_un.S_addr()) }.to_be()) +} + +/// Converts an `IN6_ADDR` to `Ipv6Addr` +pub fn ipaddr_from_in6addr(addr: IN6_ADDR) -> Ipv6Addr { + Ipv6Addr::from(*unsafe { addr.u.Byte() }) +} + +/// Converts a `SocketAddr` to `SOCKADDR_INET` +pub fn inet_sockaddr_from_socketaddr(addr: SocketAddr) -> SOCKADDR_INET { + let mut sockaddr: SOCKADDR_INET = unsafe { mem::zeroed() }; + + match addr { + SocketAddr::V4(v4_addr) => { + unsafe { + *sockaddr.si_family_mut() = AF_INET as u16; + } + + let mut v4sockaddr = unsafe { sockaddr.Ipv4_mut() }; + v4sockaddr.sin_family = AF_INET as u16; + v4sockaddr.sin_port = v4_addr.port().to_be(); + v4sockaddr.sin_addr = inaddr_from_ipaddr(*v4_addr.ip()); + } + SocketAddr::V6(v6_addr) => { + unsafe { + *sockaddr.si_family_mut() = AF_INET6 as u16; + } + + let mut v6sockaddr = unsafe { sockaddr.Ipv6_mut() }; + v6sockaddr.sin6_family = AF_INET6 as u16; + v6sockaddr.sin6_port = v6_addr.port().to_be(); + v6sockaddr.sin6_addr = in6addr_from_ipaddr(*v6_addr.ip()); + v6sockaddr.sin6_flowinfo = v6_addr.flowinfo(); + *unsafe { v6sockaddr.u.sin6_scope_id_mut() } = v6_addr.scope_id(); + } + } + + sockaddr +} + +/// Converts a `SOCKADDR_INET` to `SocketAddr`. Returns an error if the address family is invalid. +pub fn try_socketaddr_from_inet_sockaddr(addr: SOCKADDR_INET) -> Result<SocketAddr> { + unsafe { + match *addr.si_family() as i32 { + AF_INET => Ok(SocketAddr::V4(SocketAddrV4::new( + ipaddr_from_inaddr(addr.Ipv4().sin_addr), + u16::from_be(addr.Ipv4().sin_port), + ))), + AF_INET6 => Ok(SocketAddr::V6(SocketAddrV6::new( + ipaddr_from_in6addr(addr.Ipv6().sin6_addr), + u16::from_be(addr.Ipv6().sin6_port), + addr.Ipv6().sin6_flowinfo, + *addr.Ipv6().u.sin6_scope_id(), + ))), + family => Err(Error::UnknownAddressFamily(family)), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sockaddr_v4() { + let addr_v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 1234)); + assert_eq!( + addr_v4, + try_socketaddr_from_inet_sockaddr(inet_sockaddr_from_socketaddr(addr_v4)).unwrap() + ); + } + + #[test] + fn test_sockaddr_v6() { + let addr_v6 = SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), + 1234, + 0xa, + 0xb, + )); + assert_eq!( + addr_v6, + try_socketaddr_from_inet_sockaddr(inet_sockaddr_from_socketaddr(addr_v6)).unwrap() + ); + } +} |
