From 986641221dfb9f2978ae557e4dea76628b5ce3fd Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 3 Nov 2021 22:04:05 -0400 Subject: [PATCH] Remove locator, will simplify. --- PROTOCOL.md | 7 +- .../src/vl1/locator.rs | 188 ------------------ zerotier-network-hypervisor/src/vl1/mod.rs | 1 - zerotier-network-hypervisor/src/vl1/node.rs | 13 +- zerotier-network-hypervisor/src/vl1/peer.rs | 5 - .../src/vl1/protocol.rs | 4 +- zerotier-system-service/src/fastudpsocket.rs | 2 +- 7 files changed, 4 insertions(+), 216 deletions(-) delete mode 100644 zerotier-network-hypervisor/src/vl1/locator.rs diff --git a/PROTOCOL.md b/PROTOCOL.md index a78113a4e..aed05d856 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -99,9 +99,7 @@ The unencrypted dictionary is not currently used. The encrypted dictionary can c | -------------------- | --- | ------------ | ------------------------------------------------ | | INSTANCE_ID | `I` | u64 | Random integer generated at node startup | | CLOCK | `C` | u64 | Clock at sending node (milliseconds since epoch) | -| LOCATOR | `L` | Locator | Signed locator for sending node | -| EPHEMERAL_C25519 | `E0` | [u8; 32] | Curve25519 ECDH public key | -| EPHEMERAL_P521 | `E1` | [u8; 132] | NIST P-521 ECDH public key | +| EPHEMERAL_PUBLIC | `E` | [u8] | Ephemeral public key set | Dictionary fields that are only meaningful in OK(HELLO): @@ -156,9 +154,6 @@ OK(WHOIS) response payload: | [Size] Type | Description | | ------------- | ------------------------------------------------- | | Identity | Identity of address | -| [1] bool | If non-zero, a locator is included | -| Locator | Locator associated with node (if any) | -| ... | Additional tuples of identity, [locator] | #### 0x05 / RENDEZVOUS diff --git a/zerotier-network-hypervisor/src/vl1/locator.rs b/zerotier-network-hypervisor/src/vl1/locator.rs deleted file mode 100644 index d04a65143..000000000 --- a/zerotier-network-hypervisor/src/vl1/locator.rs +++ /dev/null @@ -1,188 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * (c)2021 ZeroTier, Inc. - * https://www.zerotier.com/ - */ - -use std::cmp::Ordering; -use std::hash::{Hash, Hasher}; - -use crate::vl1::{Address, Endpoint, Identity, Dictionary}; -use crate::vl1::buffer::Buffer; -use crate::vl1::protocol::PACKET_SIZE_MAX; - -/// A signed object generated by nodes to inform the network where they may be found. -/// -/// By default this will just enumerate the roots used by this node, but nodes with -/// static IPs can also list physical IP/port addresses where they can be reached with -/// no involvement from a root at all. -#[derive(Clone, PartialEq, Eq)] -pub struct Locator { - pub subject: Address, - pub signer: Address, - pub timestamp: i64, - pub metadata: Option, - pub endpoints: Vec, - pub signature: Vec, -} - -impl Locator { - /// Create and sign a new locator. - /// - /// If a node is creating its own locator the subject will be the address from the - /// signer identity. Proxy signing is when these do not match and is only done by - /// roots to create locators for old versions of ZeroTier that do not create their - /// own. Proxy locators are always superseded by self-signed locators. - /// - /// This returns None if an error occurs, which can only be something indicating a - /// bug like too many endpoints or the identity lacking its secret keys. - pub fn create(signer_identity: &Identity, subject: Address, ts: i64, endpoints: &[Endpoint]) -> Option { - let mut loc = Locator { - subject, - signer: signer_identity.address(), - timestamp: ts, - metadata: None, - endpoints: endpoints.to_vec(), - signature: Vec::new() - }; - loc.endpoints.sort_unstable(); - loc.endpoints.dedup(); - - let mut buf: Buffer<{ PACKET_SIZE_MAX }> = Buffer::new(); - if loc.marshal_internal(&mut buf, true).is_err() { - return None; - } - signer_identity.sign(buf.as_bytes()).map(|sig| { - loc.signature = sig; - loc - }) - } - - /// Check if this locator should replace one that is already known. - /// - /// Self-signed locators always replace proxy-signed locators. Otherwise locators - /// with later timestamps replace locators with earlier timestamps. - pub fn should_replace(&self, other: &Self) -> bool { - if self.is_proxy_signed() == other.is_proxy_signed() { - self.timestamp > other.timestamp - } else { - other.is_proxy_signed() - } - } - - #[inline(always)] - pub fn is_proxy_signed(&self) -> bool { self.subject != self.signer } - - pub fn verify_signature(&self, signer_identity: &Identity) -> bool { - let mut buf: Buffer<{ PACKET_SIZE_MAX }> = Buffer::new(); - if self.marshal_internal(&mut buf, true).is_ok() { - if signer_identity.address() == self.signer { - signer_identity.verify(buf.as_bytes(), self.signature.as_slice()) - } else { - false - } - } else { - false - } - } - - fn marshal_internal(&self, buf: &mut Buffer, exclude_signature: bool) -> std::io::Result<()> { - self.subject.marshal(buf)?; - self.signer.marshal(buf)?; - buf.append_varint(self.timestamp as u64)?; - if self.metadata.is_none() { - buf.append_varint(0)?; - } else { - let db = self.metadata.as_ref().unwrap().to_bytes(); - buf.append_varint(db.len() as u64)?; - buf.append_bytes(db.as_slice())?; - } - buf.append_varint(self.endpoints.len() as u64)?; - for e in self.endpoints.iter() { - e.marshal(buf)?; - } - if !exclude_signature { - buf.append_varint(self.signature.len() as u64)?; - buf.append_bytes(self.signature.as_slice())?; - } - Ok(()) - } - - #[inline(always)] - pub(crate) fn marshal(&self, buf: &mut Buffer) -> std::io::Result<()> { self.marshal_internal(buf, false) } - - pub(crate) fn unmarshal(buf: &Buffer, cursor: &mut usize) -> std::io::Result { - let subject = Address::unmarshal(buf, cursor)?; - let signer = Address::unmarshal(buf, cursor)?; - if subject.is_none() || signer.is_none() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid subject or signer address")); - } - let timestamp = buf.read_u64(cursor)? as i64; - let metadata_size = buf.read_varint(cursor)? as usize; - let metadata = if metadata_size > 0 { - let md = Dictionary::from_bytes(buf.read_bytes(metadata_size, cursor)?); - if md.is_none() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid meta-data")); - } - md - } else { None }; - let endpoint_count = buf.read_varint(cursor)? as usize; - let mut endpoints: Vec = Vec::new(); - for _ in 0..endpoint_count { - endpoints.push(Endpoint::unmarshal(buf, cursor)?); - } - let signature_len = buf.read_varint(cursor)? as usize; - let signature = buf.read_bytes(signature_len, cursor)?; - Ok(Locator { - subject: subject.unwrap(), - signer: signer.unwrap(), - timestamp, - metadata, - endpoints, - signature: signature.to_vec(), - }) - } -} - -impl Ord for Locator { - /// Natural sort order is in order of subject, then ascending order of timestamp, then signer, then endpoints. - fn cmp(&self, other: &Self) -> Ordering { - let a = self.subject.cmp(&other.subject); - if a == Ordering::Equal { - let b = self.timestamp.cmp(&other.timestamp); - if b == Ordering::Equal { - let c = self.signer.cmp(&other.signer); - if c == Ordering::Equal { - self.endpoints.cmp(&other.endpoints) - } else { - c - } - } else { - b - } - } else { - a - } - } -} - -impl PartialOrd for Locator { - #[inline(always)] - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } -} - -impl Hash for Locator { - fn hash(&self, state: &mut H) { - if !self.signature.is_empty() { - state.write(self.signature.as_slice()); - } else { - state.write_u64(self.signer.to_u64()); - state.write_i64(self.timestamp); - for e in self.endpoints.iter() { - e.hash(state); - } - } - } -} diff --git a/zerotier-network-hypervisor/src/vl1/mod.rs b/zerotier-network-hypervisor/src/vl1/mod.rs index 6fa6e7560..265cd9b15 100644 --- a/zerotier-network-hypervisor/src/vl1/mod.rs +++ b/zerotier-network-hypervisor/src/vl1/mod.rs @@ -9,7 +9,6 @@ pub mod identity; pub mod inetaddress; pub mod endpoint; -pub mod locator; pub mod rootset; #[allow(unused)] diff --git a/zerotier-network-hypervisor/src/vl1/node.rs b/zerotier-network-hypervisor/src/vl1/node.rs index d8d1ad6e7..8a197bb2d 100644 --- a/zerotier-network-hypervisor/src/vl1/node.rs +++ b/zerotier-network-hypervisor/src/vl1/node.rs @@ -18,7 +18,7 @@ use zerotier_core_crypto::random::{next_u64_secure, SecureRandom}; use crate::error::InvalidParameterError; use crate::util::gate::IntervalGate; use crate::util::pool::{Pool, Pooled}; -use crate::vl1::{Address, Endpoint, Identity, Locator}; +use crate::vl1::{Address, Endpoint, Identity}; use crate::vl1::buffer::{Buffer, PooledBufferFactory}; use crate::vl1::path::Path; use crate::vl1::peer::Peer; @@ -64,12 +64,6 @@ pub trait VL1CallerInterface { /// Note that this is only called on first startup (after up) and after identity_changed. fn save_node_identity(&self, id: &Identity, public: &[u8], secret: &[u8]); - /// Load this node's latest locator. - fn load_locator(&self) -> Option<&[u8]>; - - /// Save this node's latest locator. - fn save_locator(&self, locator: &[u8]); - /// Called to send a packet over the physical network (virtual -> physical). /// /// This may return false if the send definitely failed, and may return true if the send @@ -141,7 +135,6 @@ pub struct Node { pub(crate) instance_id: u64, identity: Identity, intervals: Mutex, - locator: Mutex>>, paths: DashMap>, peers: DashMap>, roots: Mutex>>, @@ -183,7 +176,6 @@ impl Node { instance_id: next_u64_secure(), identity: id, intervals: Mutex::new(BackgroundTaskIntervals::default()), - locator: Mutex::new(None), paths: DashMap::new(), peers: DashMap::new(), roots: Mutex::new(Vec::new()), @@ -207,9 +199,6 @@ impl Node { #[inline(always)] pub fn identity(&self) -> &Identity { &self.identity } - #[inline(always)] - pub fn locator(&self) -> Option> { self.locator.lock().clone() } - /// Get a peer by address. pub fn peer(&self, a: Address) -> Option> { self.peers.get(&a).map(|peer| peer.value().clone()) } diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index ad58dd216..51f488309 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -463,11 +463,6 @@ impl Peer { let mut dict = Dictionary::new(); dict.set_u64(HELLO_DICT_KEY_INSTANCE_ID, node.instance_id); dict.set_u64(HELLO_DICT_KEY_CLOCK, ci.time_clock() as u64); - let _ = node.locator().map(|loc| { - let mut tmp: Buffer<{ PACKET_SIZE_MAX }> = Buffer::new(); - debug_assert!(loc.marshal(&mut tmp).is_ok()); - dict.set_bytes(HELLO_DICT_KEY_LOCATOR, tmp.as_bytes().to_vec()); - }); let _ = self.ephemeral_pair.lock().as_ref().map(|ephemeral_pair| { dict.set_bytes(HELLO_DICT_KEY_EPHEMERAL_C25519, ephemeral_pair.c25519.public_bytes().to_vec()); dict.set_bytes(HELLO_DICT_KEY_EPHEMERAL_P521, ephemeral_pair.p521.public_key_bytes().to_vec()); diff --git a/zerotier-network-hypervisor/src/vl1/protocol.rs b/zerotier-network-hypervisor/src/vl1/protocol.rs index 35ec7942d..8eda057a6 100644 --- a/zerotier-network-hypervisor/src/vl1/protocol.rs +++ b/zerotier-network-hypervisor/src/vl1/protocol.rs @@ -23,9 +23,7 @@ pub const VERB_VL1_USER_MESSAGE: u8 = 0x14; pub const HELLO_DICT_KEY_INSTANCE_ID: &'static str = "I"; pub const HELLO_DICT_KEY_CLOCK: &'static str = "C"; -pub const HELLO_DICT_KEY_LOCATOR: &'static str = "L"; -pub const HELLO_DICT_KEY_EPHEMERAL_C25519: &'static str = "E0"; -pub const HELLO_DICT_KEY_EPHEMERAL_P521: &'static str = "E1"; +pub const HELLO_DICT_KEY_EPHEMERAL_PUBLIC: &'static str = "E"; pub const HELLO_DICT_KEY_EPHEMERAL_ACK: &'static str = "e"; pub const HELLO_DICT_KEY_HELLO_ORIGIN: &'static str = "@"; pub const HELLO_DICT_KEY_SYS_ARCH: &'static str = "Sa"; diff --git a/zerotier-system-service/src/fastudpsocket.rs b/zerotier-system-service/src/fastudpsocket.rs index c971a28f7..82f2dcfbc 100644 --- a/zerotier-system-service/src/fastudpsocket.rs +++ b/zerotier-system-service/src/fastudpsocket.rs @@ -181,7 +181,7 @@ fn fast_udp_socket_recvfrom(socket: &FastUDPRawOsSocket, buf: &mut PacketBuffer, impl FastUDPSocket { pub fn new(device_name: &str, address: &InetAddress, packet_buffer_pool: &Arc, handler: F) -> Result { - let thread_count = num_cpus::get_physical().max(1); + let thread_count = num_cpus::get_physical().clamp(1, 4); let mut s = Self { thread_run: Arc::new(AtomicBool::new(true)),