Skip to content

Commit

Permalink
Merge pull request #145 from NordSecurity/LLT-4275-ipv6-telio-sockets…
Browse files Browse the repository at this point in the history
…-tests

Add tests that verify working ip v4/v6 sockets.
  • Loading branch information
tomaszklak authored Oct 4, 2023
2 parents 1b0d4d9 + 1780e1b commit 6cb73c1
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions crates/telio-lana/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ license = "GPL-3.0-only"
repository = "https://github.com/NordSecurity/libtelio"
publish = false

[features]
moose = []

[dependencies]
log.workspace = true
serde.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/telio-sockets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ telio-utils.workspace = true

[dev-dependencies]
mockall.workspace = true
rstest.workspace = true

[target.'cfg(target_os = "ios")'.dependencies]
objc = "0.2.7"
Expand Down
45 changes: 45 additions & 0 deletions crates/telio-sockets/src/protector/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,48 @@ fn set_fwmark(fd: i32, fwmark: u32) -> io::Result<()> {
_ => Err(io::Error::last_os_error()),
}
}

#[cfg(test)]
mod tests {
use std::{
io::ErrorKind,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, UdpSocket},
};

use crate::native::AsNativeSocket;

use rstest::rstest;

use super::*;

#[rstest]
#[case(IpAddr::V4(Ipv4Addr::LOCALHOST))]
#[case(IpAddr::V4(Ipv4Addr::UNSPECIFIED))]
#[case(IpAddr::V6(Ipv6Addr::LOCALHOST))]
#[case(IpAddr::V6(Ipv6Addr::UNSPECIFIED))]
fn test_make_external(#[case] ip_addr: IpAddr) {
let protector = NativeProtector::new().unwrap();
protector.set_fwmark(11673110);
let addr = SocketAddr::new(ip_addr, 0);

let socket = match UdpSocket::bind(addr) {
Ok(socket) => socket,
Err(e) if e.kind() == ErrorKind::AddrNotAvailable => {
// host has no interface with ipv4/ipv6
return;
}
Err(e) => panic!("Unexpected error: {:?}", e),
};
assert!(protector.make_external(socket.as_native_socket()).is_ok());

let socket = match TcpListener::bind(addr) {
Ok(socket) => socket,
Err(e) if e.kind() == ErrorKind::AddrNotAvailable => {
// host has no interface with ipv4/ipv6
return;
}
Err(e) => panic!("Unexpected error: {:?}", e),
};
assert!(protector.make_external(socket.as_native_socket()).is_ok());
}
}
25 changes: 25 additions & 0 deletions crates/telio-sockets/src/protector/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,28 @@ pub fn get_default_interface(tunnel_interface: u64) -> Result<Interface> {

Ok(default_interface)
}

#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, UdpSocket};

use crate::native::AsNativeSocket;
use rstest::rstest;

use super::*;

#[rstest]
#[case(IpAddr::V4(Ipv4Addr::LOCALHOST))]
#[case(IpAddr::V6(Ipv6Addr::LOCALHOST))]
#[tokio::test]
async fn test_make_external(#[case] ip_addr: IpAddr) {
let protector = NativeProtector::new().unwrap();
let addr = SocketAddr::new(ip_addr, 0);

let socket = std::net::UdpSocket::bind(addr).unwrap();
assert!(protector.make_external(socket.as_native_socket()).is_ok());

let socket = std::net::TcpListener::bind(addr).unwrap();
assert!(protector.make_external(socket.as_native_socket()).is_ok());
}
}
76 changes: 75 additions & 1 deletion crates/telio-sockets/src/socket_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,20 @@ impl MakeExternalBoringtun for SocketPool {
#[cfg(test)]
mod tests {
use std::{
net::{Ipv4Addr, SocketAddrV4},
io::ErrorKind,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4},
sync::Mutex,
};

use mockall::mock;
use rstest::rstest;

use crate::{native::NativeSocket, Protect};

use super::*;

const PACKET: [u8; 8] = *b"libtelio";

mock! {
Protector {}
impl Protector for Protector {
Expand Down Expand Up @@ -320,4 +324,74 @@ mod tests {

assert_eq!(socks.lock().unwrap().clone(), vec![tcp.as_native_socket()]);
}

#[rstest]
#[case(IpAddr::V4(Ipv4Addr::LOCALHOST))]
#[cfg(not(windows))]
#[case(IpAddr::V4(Ipv4Addr::UNSPECIFIED))]
#[case(IpAddr::V6(Ipv6Addr::LOCALHOST))]
#[cfg(not(any(windows, tarpaulin)))]
#[case(IpAddr::V6(Ipv6Addr::UNSPECIFIED))]
#[tokio::test]
async fn internal_udp_socket_can_transfer_data(#[case] ip_addr: IpAddr) {
let protect = MockProtector::default();
let pool = SocketPool::new(protect);
let addr = SocketAddr::new(ip_addr, 0);
let socket = match pool.new_internal_udp(addr, None).await {
Ok(socket) => socket,
Err(e) if e.kind() == ErrorKind::AddrNotAvailable => {
// host has no interface with ipv4/ipv6
return;
}
Err(e) => panic!("Unexpected error: {:?}", e),
};
let local_addr = socket.local_addr().unwrap();
tokio::spawn(async move {
let protect = MockProtector::default();
let pool = SocketPool::new(protect);
let addr = SocketAddr::new(ip_addr, 0);
let socket = pool.new_internal_udp(addr, None).await.unwrap();
socket.send_to(&PACKET, local_addr).await.unwrap();
});
let mut buf = [0; PACKET.len()];
assert_eq!(PACKET.len(), socket.recv_from(&mut buf).await.unwrap().0);
assert_eq!(PACKET, buf);
}

#[rstest]
#[case(IpAddr::V4(Ipv4Addr::LOCALHOST))]
#[cfg(not(windows))]
#[case(IpAddr::V4(Ipv4Addr::UNSPECIFIED))]
#[case(IpAddr::V6(Ipv6Addr::LOCALHOST))]
#[cfg(not(any(windows, tarpaulin)))]
#[case(IpAddr::V6(Ipv6Addr::UNSPECIFIED))]
#[tokio::test]
async fn external_udp_socket_can_transfer_data(#[case] ip_addr: IpAddr) {
let mut protect = MockProtector::default();
protect.expect_make_external().returning(|_| Ok(()));
protect.expect_clean().return_const(());
let pool = SocketPool::new(protect);
let addr = SocketAddr::new(ip_addr, 0);
let socket = match pool.new_internal_udp(addr, None).await {
Ok(socket) => socket,
Err(e) if e.kind() == ErrorKind::AddrNotAvailable => {
// host has no interface with ipv4/ipv6
return;
}
Err(e) => panic!("Unexpected error: {:?}", e),
};
let local_addr = socket.local_addr().unwrap();
tokio::spawn(async move {
let mut protect = MockProtector::default();
protect.expect_make_external().returning(|_| Ok(()));
protect.expect_clean().return_const(());
let pool = SocketPool::new(protect);
let addr = SocketAddr::new(ip_addr, 0);
let socket = pool.new_external_udp(addr, None).await.unwrap();
socket.send_to(&PACKET, local_addr).await.unwrap();
});
let mut buf = [0; PACKET.len()];
assert_eq!(PACKET.len(), socket.recv_from(&mut buf).await.unwrap().0);
assert_eq!(PACKET, buf);
}
}

0 comments on commit 6cb73c1

Please sign in to comment.