use std::error::Error; use std::fmt; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::thread; use std::time::{Duration, Instant}; use pnet::packet::ipv4::MutableIpv4Packet; use pnet::packet::ipv6::MutableIpv6Packet; use super::super::types::{Bind, Key, KeyPair, Tun}; use super::{Device, Peer, SIZE_MESSAGE_PREFIX}; #[derive(Debug)] enum TunError {} impl Error for TunError { fn description(&self) -> &str { "Generic Tun Error" } fn source(&self) -> Option<&(dyn Error + 'static)> { None } } impl fmt::Display for TunError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Not Possible") } } struct TunTest {} impl Tun for TunTest { type Error = TunError; fn mtu(&self) -> usize { 1500 } fn read(&self, buf: &mut [u8], offset: usize) -> Result { Ok(0) } fn write(&self, src: &[u8]) -> Result<(), Self::Error> { Ok(()) } } struct BindTest {} impl Bind for BindTest { type Error = BindError; type Endpoint = SocketAddr; fn new() -> BindTest { BindTest {} } fn set_port(&self, port: u16) -> Result<(), Self::Error> { Ok(()) } fn get_port(&self) -> Option { None } fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error> { Ok((0, "127.0.0.1:8080".parse().unwrap())) } fn send(&self, buf: &[u8], dst: &Self::Endpoint) -> Result<(), Self::Error> { Ok(()) } } #[derive(Debug)] enum BindError {} impl Error for BindError { fn description(&self) -> &str { "Generic Bind Error" } fn source(&self) -> Option<&(dyn Error + 'static)> { None } } impl fmt::Display for BindError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Not Possible") } } fn dummy_keypair(initiator: bool) -> KeyPair { let k1 = Key { key: [0x53u8; 32], id: 0x646e6573, }; let k2 = Key { key: [0x52u8; 32], id: 0x76636572, }; if initiator { KeyPair { birth: Instant::now(), initiator: true, send: k1, recv: k2, } } else { KeyPair { birth: Instant::now(), initiator: false, send: k2, recv: k1, } } } #[test] fn test_outbound() { // type for tracking events inside the router module struct Flags { send: AtomicBool, recv: AtomicBool, need_key: AtomicBool, } type Opaque = Arc; let opaque = Arc::new(Flags { send: AtomicBool::new(false), recv: AtomicBool::new(false), need_key: AtomicBool::new(false), }); // create device let workers = 4; let router = Device::new( workers, TunTest {}, BindTest {}, |t: &Opaque, data: bool, sent: bool| t.send.store(true, Ordering::SeqCst), |t: &Opaque, data: bool, sent: bool| t.recv.store(true, Ordering::SeqCst), |t: &Opaque| t.need_key.store(true, Ordering::SeqCst), ); // create peer let peer = router.new_peer(opaque.clone()); let tests = vec![ ("192.168.1.0", 24, "192.168.1.20", true), ("172.133.133.133", 32, "172.133.133.133", true), ("172.133.133.133", 32, "172.133.133.132", false), ( "2001:db8::ff00:42:0000", 112, "2001:db8::ff00:42:3242", true, ), ( "2001:db8::ff00:42:8000", 113, "2001:db8::ff00:42:0660", false, ), ( "2001:db8::ff00:42:8000", 113, "2001:db8::ff00:42:ffff", true, ), ]; peer.add_keypair(dummy_keypair(true)); for (mask, len, ip, okay) in &tests { opaque.send.store(false, Ordering::SeqCst); opaque.recv.store(false, Ordering::SeqCst); opaque.need_key.store(false, Ordering::SeqCst); let mask: IpAddr = mask.parse().unwrap(); // map subnet to peer peer.add_subnet(mask, *len); // create "IP packet" let mut msg = Vec::::new(); msg.resize(SIZE_MESSAGE_PREFIX + 1024, 0); if mask.is_ipv4() { let mut packet = MutableIpv4Packet::new(&mut msg[SIZE_MESSAGE_PREFIX..]).unwrap(); packet.set_destination(ip.parse().unwrap()); packet.set_version(4); } else { let mut packet = MutableIpv6Packet::new(&mut msg[SIZE_MESSAGE_PREFIX..]).unwrap(); packet.set_destination(ip.parse().unwrap()); packet.set_version(6); } // cryptkey route the IP packet let res = router.send(msg); // allow some scheduling thread::sleep(Duration::from_millis(1)); if *okay { // cryptkey routing succeeded assert!(res.is_ok()); // attempted to send message assert_eq!(opaque.need_key.load(Ordering::Acquire), false); assert_eq!(opaque.send.load(Ordering::Acquire), true); assert_eq!(opaque.recv.load(Ordering::Acquire), false); } else { // no such cryptkey route assert!(res.is_err()); // did not attempt to send message assert_eq!(opaque.need_key.load(Ordering::Acquire), false); assert_eq!(opaque.send.load(Ordering::Acquire), false); assert_eq!(opaque.recv.load(Ordering::Acquire), false); } // clear subnets for next test peer.remove_subnets(); } }