|
|
|
|
@ -2,10 +2,13 @@ use std::error::Error;
|
|
|
|
|
use std::fmt; |
|
|
|
|
use std::net::{IpAddr, SocketAddr}; |
|
|
|
|
use std::sync::atomic::{AtomicBool, Ordering}; |
|
|
|
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; |
|
|
|
|
use std::sync::Arc; |
|
|
|
|
use std::sync::Mutex; |
|
|
|
|
use std::thread; |
|
|
|
|
use std::time::{Duration, Instant}; |
|
|
|
|
|
|
|
|
|
use num_cpus; |
|
|
|
|
use pnet::packet::ipv4::MutableIpv4Packet; |
|
|
|
|
use pnet::packet::ipv6::MutableIpv6Packet; |
|
|
|
|
|
|
|
|
|
@ -14,6 +17,33 @@ use super::{Device, SIZE_MESSAGE_PREFIX};
|
|
|
|
|
|
|
|
|
|
extern crate test; |
|
|
|
|
|
|
|
|
|
/* Error implementation */ |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
enum BindError { |
|
|
|
|
Disconnected, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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 { |
|
|
|
|
match self { |
|
|
|
|
BindError::Disconnected => write!(f, "PairBind disconnected"), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* TUN implementation */ |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
enum TunError {} |
|
|
|
|
|
|
|
|
|
@ -33,6 +63,22 @@ impl fmt::Display for TunError {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Endpoint implementation */ |
|
|
|
|
|
|
|
|
|
struct UnitEndpoint {} |
|
|
|
|
|
|
|
|
|
impl From<SocketAddr> for UnitEndpoint { |
|
|
|
|
fn from(addr: SocketAddr) -> UnitEndpoint { |
|
|
|
|
UnitEndpoint {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Into<SocketAddr> for UnitEndpoint { |
|
|
|
|
fn into(self) -> SocketAddr { |
|
|
|
|
"127.0.0.1:8080".parse().unwrap() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct TunTest {} |
|
|
|
|
|
|
|
|
|
impl Tun for TunTest { |
|
|
|
|
@ -51,14 +97,16 @@ impl Tun for TunTest {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct BindTest {} |
|
|
|
|
/* Bind implemenentations */ |
|
|
|
|
|
|
|
|
|
struct VoidBind {} |
|
|
|
|
|
|
|
|
|
impl Bind for BindTest { |
|
|
|
|
impl Bind for VoidBind { |
|
|
|
|
type Error = BindError; |
|
|
|
|
type Endpoint = SocketAddr; |
|
|
|
|
type Endpoint = UnitEndpoint; |
|
|
|
|
|
|
|
|
|
fn new() -> BindTest { |
|
|
|
|
BindTest {} |
|
|
|
|
fn new() -> VoidBind { |
|
|
|
|
VoidBind {} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn set_port(&self, port: u16) -> Result<(), Self::Error> { |
|
|
|
|
@ -70,7 +118,7 @@ impl Bind for BindTest {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error> { |
|
|
|
|
Ok((0, "127.0.0.1:8080".parse().unwrap())) |
|
|
|
|
Ok((0, UnitEndpoint {})) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn send(&self, buf: &[u8], dst: &Self::Endpoint) -> Result<(), Self::Error> { |
|
|
|
|
@ -78,25 +126,61 @@ impl Bind for BindTest {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
enum BindError {} |
|
|
|
|
struct PairBind { |
|
|
|
|
send: Mutex<SyncSender<Vec<u8>>>, |
|
|
|
|
recv: Mutex<Receiver<Vec<u8>>>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Error for BindError { |
|
|
|
|
fn description(&self) -> &str { |
|
|
|
|
"Generic Bind Error" |
|
|
|
|
impl Bind for PairBind { |
|
|
|
|
type Error = BindError; |
|
|
|
|
type Endpoint = UnitEndpoint; |
|
|
|
|
|
|
|
|
|
fn new() -> PairBind { |
|
|
|
|
PairBind { |
|
|
|
|
send: Mutex::new(sync_channel(0).0), |
|
|
|
|
recv: Mutex::new(sync_channel(0).1), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn source(&self) -> Option<&(dyn Error + 'static)> { |
|
|
|
|
fn set_port(&self, port: u16) -> Result<(), Self::Error> { |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn get_port(&self) -> Option<u16> { |
|
|
|
|
None |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl fmt::Display for BindError { |
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
|
|
|
write!(f, "Not Possible") |
|
|
|
|
fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error> { |
|
|
|
|
let vec = self |
|
|
|
|
.recv |
|
|
|
|
.lock() |
|
|
|
|
.unwrap() |
|
|
|
|
.recv() |
|
|
|
|
.map_err(|_| BindError::Disconnected)?; |
|
|
|
|
buf.copy_from_slice(&vec[..]); |
|
|
|
|
Ok((vec.len(), UnitEndpoint {})) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn send(&self, buf: &[u8], dst: &Self::Endpoint) -> Result<(), Self::Error> { |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn bind_pair() -> (PairBind, PairBind) { |
|
|
|
|
let (tx1, rx1) = sync_channel(0); |
|
|
|
|
let (tx2, rx2) = sync_channel(0); |
|
|
|
|
( |
|
|
|
|
PairBind { |
|
|
|
|
send: Mutex::new(tx1), |
|
|
|
|
recv: Mutex::new(rx2), |
|
|
|
|
}, |
|
|
|
|
PairBind { |
|
|
|
|
send: Mutex::new(tx2), |
|
|
|
|
recv: Mutex::new(rx1), |
|
|
|
|
}, |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn dummy_keypair(initiator: bool) -> KeyPair { |
|
|
|
|
let k1 = Key { |
|
|
|
|
key: [0x53u8; 32], |
|
|
|
|
@ -131,6 +215,32 @@ mod tests {
|
|
|
|
|
use std::sync::atomic::AtomicU64; |
|
|
|
|
use test::Bencher; |
|
|
|
|
|
|
|
|
|
fn get_tests() -> Vec<(&'static str, u32, &'static str, bool)> { |
|
|
|
|
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, |
|
|
|
|
), |
|
|
|
|
] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn init() { |
|
|
|
|
let _ = env_logger::builder().is_test(true).try_init(); |
|
|
|
|
} |
|
|
|
|
@ -162,16 +272,15 @@ mod tests {
|
|
|
|
|
type Opaque = Arc<AtomicU64>; |
|
|
|
|
|
|
|
|
|
// create device
|
|
|
|
|
let workers = 4; |
|
|
|
|
let router = Device::new( |
|
|
|
|
workers, |
|
|
|
|
num_cpus::get(), |
|
|
|
|
TunTest {}, |
|
|
|
|
BindTest {}, |
|
|
|
|
VoidBind::new(), |
|
|
|
|
|t: &Opaque, _data: bool, _sent: bool| { |
|
|
|
|
t.fetch_add(1, Ordering::SeqCst); |
|
|
|
|
}, |
|
|
|
|
|t: &Opaque, _data: bool, _sent: bool| {}, |
|
|
|
|
|t: &Opaque| {}, |
|
|
|
|
|_t: &Opaque, _data: bool, _sent: bool| {}, |
|
|
|
|
|_t: &Opaque| {}, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// add new peer
|
|
|
|
|
@ -185,16 +294,10 @@ mod tests {
|
|
|
|
|
let ip: IpAddr = ip.parse().unwrap(); |
|
|
|
|
peer.add_subnet(mask, len); |
|
|
|
|
|
|
|
|
|
for _ in 0..1024 { |
|
|
|
|
let msg = make_packet(1024, ip); |
|
|
|
|
router.send(msg).unwrap(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// every iteration sends 10 MB
|
|
|
|
|
b.iter(|| { |
|
|
|
|
opaque.store(0, Ordering::SeqCst); |
|
|
|
|
// wait till 10 MB
|
|
|
|
|
while opaque.load(Ordering::Acquire) < 10 * 1024 { |
|
|
|
|
// create "IP packet"
|
|
|
|
|
let msg = make_packet(1024, ip); |
|
|
|
|
router.send(msg).unwrap(); |
|
|
|
|
} |
|
|
|
|
@ -214,40 +317,16 @@ mod tests {
|
|
|
|
|
type Opaque = Arc<Flags>; |
|
|
|
|
|
|
|
|
|
// create device
|
|
|
|
|
let workers = 4; |
|
|
|
|
let router = Device::new( |
|
|
|
|
workers, |
|
|
|
|
1, |
|
|
|
|
TunTest {}, |
|
|
|
|
BindTest {}, |
|
|
|
|
VoidBind::new(), |
|
|
|
|
|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), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
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, |
|
|
|
|
), |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
let tests = get_tests(); |
|
|
|
|
for (num, (mask, len, ip, okay)) in tests.iter().enumerate() { |
|
|
|
|
for set_key in vec![true, false] { |
|
|
|
|
debug!("index = {}, set_key = {}", num, set_key); |
|
|
|
|
@ -317,4 +396,60 @@ mod tests {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
fn test_outbound_inbound() { |
|
|
|
|
// type for tracking events inside the router module
|
|
|
|
|
|
|
|
|
|
struct Flags { |
|
|
|
|
send: AtomicBool, |
|
|
|
|
recv: AtomicBool, |
|
|
|
|
need_key: AtomicBool, |
|
|
|
|
} |
|
|
|
|
type Opaque = Arc<Flags>; |
|
|
|
|
|
|
|
|
|
let (bind1, bind2) = bind_pair(); |
|
|
|
|
|
|
|
|
|
// create matching devices
|
|
|
|
|
|
|
|
|
|
let router1 = Device::new( |
|
|
|
|
1, |
|
|
|
|
TunTest {}, |
|
|
|
|
bind1, |
|
|
|
|
|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), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
let router2 = Device::new( |
|
|
|
|
1, |
|
|
|
|
TunTest {}, |
|
|
|
|
bind2, |
|
|
|
|
|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 peers with matching keypairs
|
|
|
|
|
|
|
|
|
|
let opaq1 = Arc::new(Flags { |
|
|
|
|
send: AtomicBool::new(false), |
|
|
|
|
recv: AtomicBool::new(false), |
|
|
|
|
need_key: AtomicBool::new(false), |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
let opaq2 = Arc::new(Flags { |
|
|
|
|
send: AtomicBool::new(false), |
|
|
|
|
recv: AtomicBool::new(false), |
|
|
|
|
need_key: AtomicBool::new(false), |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
let peer1 = router1.new_peer(opaq1.clone()); |
|
|
|
|
peer1.set_endpoint("127.0.0.1:8080".parse().unwrap()); |
|
|
|
|
peer1.add_keypair(dummy_keypair(false)); |
|
|
|
|
|
|
|
|
|
let peer2 = router2.new_peer(opaq2.clone()); |
|
|
|
|
peer2.set_endpoint("127.0.0.1:8080".parse().unwrap()); |
|
|
|
|
peer2.add_keypair(dummy_keypair(true)); // this should cause an empty key-confirmation packet
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|