diff --git a/CHANGELOG.md b/CHANGELOG.md index df07a20..95ed804 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,10 @@ This project follows [semantic versioning](http://semver.org). - [added] Added crypto option AES128 - [added] Default port for peers - [changed] Updated dependencies +- [changed] Removed C code, now 100% Rust - [fixed] Fixed keepalive for small timeouts +- [fixed] Fixed problem with port forwarding +- [fixed] Fixed problem with TUN on dynamic host addresses ### v1.4.0 (2020-06-03) diff --git a/src/cloud.rs b/src/cloud.rs index bb354dd..e90ffd1 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -3,7 +3,7 @@ // This software is licensed under GPL-3 or newer (see LICENSE.md) use std::{ - cmp::{min, max}, + cmp::{max, min}, collections::HashMap, fmt, fs::{self, File}, @@ -109,7 +109,6 @@ impl PeerList { self.nodes.contains_key(node_id) } - #[inline] fn add(&mut self, node_id: NodeId, addr: SocketAddr, peer_timeout: u16) { if self.nodes.insert(node_id, addr).is_none() { @@ -366,7 +365,8 @@ impl GenericCloud GenericCloud GenericCloud GenericCloud Table for SwitchTable { /// Learns the given address, inserting it in the hash map #[inline] - fn learn(&mut self, key: Address, _prefix_len: Option, addr: SocketAddr) { + fn learn(&mut self, key: Address, _prefix_len: Option, _: NodeId, addr: SocketAddr) { let deadline = TS::now() + Time::from(self.timeout); match self.table.entry(key) { Entry::Vacant(entry) => { @@ -212,16 +212,17 @@ fn switch() { MockTimeSource::set_time(1000); let mut table = SwitchTable::::new(10, 1); let addr = Address::from_str("12:34:56:78:90:ab").unwrap(); + let node_id = [0; 16]; let peer = "1.2.3.4:5678".to_socket_addrs().unwrap().next().unwrap(); let peer2 = "1.2.3.5:7890".to_socket_addrs().unwrap().next().unwrap(); assert!(table.lookup(&addr).is_none()); MockTimeSource::set_time(1000); - table.learn(addr, None, peer); + table.learn(addr, None, node_id, peer); assert_eq!(table.lookup(&addr), Some(peer)); MockTimeSource::set_time(1000); - table.learn(addr, None, peer2); + table.learn(addr, None, node_id, peer2); assert_eq!(table.lookup(&addr), Some(peer)); MockTimeSource::set_time(1010); - table.learn(addr, None, peer2); + table.learn(addr, None, node_id, peer2); assert_eq!(table.lookup(&addr), Some(peer2)); } diff --git a/src/ip.rs b/src/ip.rs index 2c2db3d..e110cd6 100644 --- a/src/ip.rs +++ b/src/ip.rs @@ -12,7 +12,7 @@ use std::{ use fnv::FnvHasher; use super::{ - types::{Address, Error, Protocol, Table}, + types::{Address, Error, NodeId, Protocol, Table}, util::addr_nice }; @@ -59,6 +59,7 @@ impl Protocol for Packet { struct RoutingEntry { address: SocketAddr, + node_id: NodeId, bytes: Address, prefix_len: u8 } @@ -82,7 +83,7 @@ impl RoutingTable { impl Table for RoutingTable { /// Learns the given address, inserting it in the hash map - fn learn(&mut self, addr: Address, prefix_len: Option, address: SocketAddr) { + fn learn(&mut self, addr: Address, prefix_len: Option, node_id: NodeId, address: SocketAddr) { // If prefix length is not set, treat the whole address as significant let prefix_len = match prefix_len { Some(val) => val, @@ -96,10 +97,14 @@ impl Table for RoutingTable { let mut group_bytes = [0; 16]; group_bytes[..group_len].copy_from_slice(&addr.data[..group_len]); // Create an entry - let routing_entry = RoutingEntry { address, bytes: addr, prefix_len }; + let routing_entry = RoutingEntry { address, bytes: addr, node_id, prefix_len }; // Add the entry to the routing table, creating a new list if the prefix group is empty. match self.0.entry(group_bytes) { - hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry), + hash_map::Entry::Occupied(mut entry) => { + let list = entry.get_mut(); + list.retain(|e| e.node_id != routing_entry.node_id || e.address == routing_entry.address); + list.push(routing_entry) + } hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); } @@ -241,33 +246,36 @@ fn decode_invalid_packet() { fn routing_table_ipv4() { let mut table = RoutingTable::new(); let peer1 = "1.2.3.4:1".to_socket_addrs().unwrap().next().unwrap(); + let node1 = [1; 16]; let peer2 = "1.2.3.4:2".to_socket_addrs().unwrap().next().unwrap(); + let node2 = [2; 16]; let peer3 = "1.2.3.4:3".to_socket_addrs().unwrap().next().unwrap(); + let node3 = [3; 16]; assert!(table.lookup(&Address::from_str("192.168.1.1").unwrap()).is_none()); - table.learn(Address::from_str("192.168.1.1").unwrap(), Some(32), peer1); + table.learn(Address::from_str("192.168.1.1").unwrap(), Some(32), node1, peer1); assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1)); - table.learn(Address::from_str("192.168.1.2").unwrap(), None, peer2); + table.learn(Address::from_str("192.168.1.2").unwrap(), None, node2, peer2); assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2)); - table.learn(Address::from_str("192.168.1.0").unwrap(), Some(24), peer3); + table.learn(Address::from_str("192.168.1.0").unwrap(), Some(24), node3, peer3); assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("192.168.1.3").unwrap()), Some(peer3)); - table.learn(Address::from_str("192.168.0.0").unwrap(), Some(16), peer1); + table.learn(Address::from_str("192.168.0.0").unwrap(), Some(16), node1, peer1); assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("192.168.1.3").unwrap()), Some(peer3)); - table.learn(Address::from_str("0.0.0.0").unwrap(), Some(0), peer2); + table.learn(Address::from_str("0.0.0.0").unwrap(), Some(0), node2, peer2); assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("192.168.1.3").unwrap()), Some(peer3)); assert_eq!(table.lookup(&Address::from_str("1.2.3.4").unwrap()), Some(peer2)); - table.learn(Address::from_str("192.168.2.0").unwrap(), Some(27), peer3); + table.learn(Address::from_str("192.168.2.0").unwrap(), Some(27), node3, peer3); assert_eq!(table.lookup(&Address::from_str("192.168.2.31").unwrap()), Some(peer3)); assert_eq!(table.lookup(&Address::from_str("192.168.2.32").unwrap()), Some(peer1)); - table.learn(Address::from_str("192.168.2.0").unwrap(), Some(28), peer3); + table.learn(Address::from_str("192.168.2.0").unwrap(), Some(28), node3, peer3); assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer3)); } @@ -275,34 +283,37 @@ fn routing_table_ipv4() { fn routing_table_ipv6() { let mut table = RoutingTable::new(); let peer1 = "::1:1".to_socket_addrs().unwrap().next().unwrap(); + let node1 = [1; 16]; let peer2 = "::1:2".to_socket_addrs().unwrap().next().unwrap(); + let node2 = [2; 16]; let peer3 = "::1:3".to_socket_addrs().unwrap().next().unwrap(); + let node3 = [3; 16]; assert!(table.lookup(&Address::from_str("::1").unwrap()).is_none()); - table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap(), Some(128), peer1); + table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap(), Some(128), node1, peer1); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1)); - table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap(), None, peer2); + table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap(), None, node2, peer2); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2)); - table.learn(Address::from_str("dead:beef:dead:beef::").unwrap(), Some(64), peer3); + table.learn(Address::from_str("dead:beef:dead:beef::").unwrap(), Some(64), node3, peer3); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:3").unwrap()), Some(peer3)); - table.learn(Address::from_str("dead:beef:dead:be00::").unwrap(), Some(56), peer1); + table.learn(Address::from_str("dead:beef:dead:be00::").unwrap(), Some(56), node1, peer1); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:1::").unwrap()), Some(peer3)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:be01::").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:3").unwrap()), Some(peer3)); - table.learn(Address::from_str("::").unwrap(), Some(0), peer2); + table.learn(Address::from_str("::").unwrap(), Some(0), node2, peer2); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:1::").unwrap()), Some(peer3)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:be01::").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:3").unwrap()), Some(peer3)); assert_eq!(table.lookup(&Address::from_str("::1").unwrap()), Some(peer2)); - table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(123), peer2); + table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(123), node2, peer2); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:be1f").unwrap()), Some(peer2)); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:be20").unwrap()), Some(peer3)); - table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(124), peer3); + table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(124), node3, peer3); assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:be01").unwrap()), Some(peer3)); } diff --git a/src/types.rs b/src/types.rs index 27c19cd..61842fd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -221,7 +221,7 @@ impl FromStr for Mode { } pub trait Table { - fn learn(&mut self, _: Address, _: Option, _: SocketAddr); + fn learn(&mut self, _: Address, _: Option, _: NodeId, _: SocketAddr); fn lookup(&mut self, _: &Address) -> Option; fn housekeep(&mut self); fn write_out(&self, out: &mut W) -> Result<(), io::Error>;