From e732c3569cfae95420bcbb3917189ede270eda11 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 5 Nov 2021 21:38:35 -0400 Subject: [PATCH] Docs, stub out VL2, create root level Node that is a composition of VL1 and VL2. --- zerotier-network-hypervisor/src/lib.rs | 2 + zerotier-network-hypervisor/src/node.rs | 62 +++++++++++++++++++ .../src/vl1/endpoint.rs | 8 ++- .../src/vl1/ephemeral.rs | 0 zerotier-network-hypervisor/src/vl1/mod.rs | 1 + zerotier-network-hypervisor/src/vl1/node.rs | 22 +++---- zerotier-network-hypervisor/src/vl1/path.rs | 2 +- zerotier-network-hypervisor/src/vl1/peer.rs | 2 +- .../src/vl1/whoisqueue.rs | 2 +- zerotier-network-hypervisor/src/vl2/mod.rs | 1 + zerotier-network-hypervisor/src/vl2/switch.rs | 37 +++++++++++ .../src/commands/identity.rs | 4 +- zerotier-system-service/src/service.rs | 7 ++- zerotier-system-service/src/utils.rs | 4 +- 14 files changed, 128 insertions(+), 26 deletions(-) create mode 100644 zerotier-network-hypervisor/src/node.rs create mode 100644 zerotier-network-hypervisor/src/vl1/ephemeral.rs create mode 100644 zerotier-network-hypervisor/src/vl2/switch.rs diff --git a/zerotier-network-hypervisor/src/lib.rs b/zerotier-network-hypervisor/src/lib.rs index 91bdd0ab8..f77882b15 100644 --- a/zerotier-network-hypervisor/src/lib.rs +++ b/zerotier-network-hypervisor/src/lib.rs @@ -12,6 +12,8 @@ pub mod vl1; pub mod vl2; pub mod defaults; +mod node; + pub const VERSION_MAJOR: u8 = 1; pub const VERSION_MINOR: u8 = 99; pub const VERSION_REVISION: u8 = 1; diff --git a/zerotier-network-hypervisor/src/node.rs b/zerotier-network-hypervisor/src/node.rs new file mode 100644 index 000000000..6d2a07cc3 --- /dev/null +++ b/zerotier-network-hypervisor/src/node.rs @@ -0,0 +1,62 @@ +/* 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::sync::Arc; +use std::time::Duration; + +use crate::vl1::node::VL1CallerInterface; +use crate::error::InvalidParameterError; +use crate::vl1::{PacketBuffer, PacketBufferPool, Address, Identity, Endpoint}; + +pub trait CallerInterface: VL1CallerInterface { +} + +/// A complete ZeroTier node. +/// +/// This is a composition of the VL1 node and the VL2 virtual switch. +pub struct Node { + vl1: crate::vl1::node::Node, + vl2: crate::vl2::switch::Switch, +} + +impl Node { + pub fn new(ci: &CI, auto_generate_identity_type: Option) -> Result { + Ok(Node { + vl1: crate::vl1::node::Node::new(ci, auto_generate_identity_type)?, + vl2: crate::vl2::switch::Switch::new(), + }) + } + + /// Obtain a new packet buffer from the buffer pool. + /// + /// The returned object is a Pooled> instance. The buffer is returned to the pool when the container is destroyed. + #[inline(always)] + pub fn get_packet_buffer(&self) -> PacketBuffer { self.vl1.get_packet_buffer() } + + /// Get a direct reference to the packet buffer pool. + #[inline(always)] + pub fn packet_buffer_pool(&self) -> &Arc { self.vl1.packet_buffer_pool() } + + #[inline(always)] + pub fn address(&self) -> Address { self.vl1.address() } + + #[inline(always)] + pub fn identity(&self) -> &Identity { self.vl1.identity() } + + #[inline(always)] + pub fn fips_mode(&self) -> bool { self.vl1.fips_mode() } + + pub fn do_background_tasks(&self, ci: &CI) -> Duration { + self.vl1.do_background_tasks(ci) + } + + #[inline(always)] + pub fn wire_receive(&self, ci: &CI, source_endpoint: &Endpoint, source_local_socket: i64, source_local_interface: i64, mut data: PacketBuffer) { + self.vl1.wire_receive(ci, &self.vl2, source_endpoint, source_local_socket, source_local_interface, data) + } +} diff --git a/zerotier-network-hypervisor/src/vl1/endpoint.rs b/zerotier-network-hypervisor/src/vl1/endpoint.rs index da144bf83..d86151a81 100644 --- a/zerotier-network-hypervisor/src/vl1/endpoint.rs +++ b/zerotier-network-hypervisor/src/vl1/endpoint.rs @@ -111,9 +111,11 @@ impl Endpoint { ip.marshal(buf) } Endpoint::IpUdp(ip) => { - // IP/UDP endpoints are marshaled as naked InetAddress objects for backward - // compatibility. This is why 16 is added to all the other type IDs. Naked - // InetAddress objects always start with either 4 or 6. + // Wire encoding of IP/UDP type endpoints is the same as naked InetAddress + // objects for backward compatibility. That way a naked InetAddress unmarshals + // here as an IP/UDP Endpoint and vice versa. Supporting this is why 16 is added + // to all Endpoint type IDs for wire encoding so that values of 4 or 6 can be + // interpreted as IP/UDP InetAddress. ip.marshal(buf) } Endpoint::IpTcp(ip) => { diff --git a/zerotier-network-hypervisor/src/vl1/ephemeral.rs b/zerotier-network-hypervisor/src/vl1/ephemeral.rs new file mode 100644 index 000000000..e69de29bb diff --git a/zerotier-network-hypervisor/src/vl1/mod.rs b/zerotier-network-hypervisor/src/vl1/mod.rs index 6a9f6130c..bd2728964 100644 --- a/zerotier-network-hypervisor/src/vl1/mod.rs +++ b/zerotier-network-hypervisor/src/vl1/mod.rs @@ -22,6 +22,7 @@ pub(crate) mod address; pub(crate) mod mac; pub(crate) mod fragmentedpacket; pub(crate) mod whoisqueue; +pub(crate) mod ephemeral; pub use address::Address; pub use mac::MAC; diff --git a/zerotier-network-hypervisor/src/vl1/node.rs b/zerotier-network-hypervisor/src/vl1/node.rs index 8a197bb2d..7be27a290 100644 --- a/zerotier-network-hypervisor/src/vl1/node.rs +++ b/zerotier-network-hypervisor/src/vl1/node.rs @@ -142,7 +142,6 @@ pub struct Node { whois: WhoisQueue, buffer_pool: Arc, secure_prng: SecureRandom, - fips_mode: bool, } impl Node { @@ -183,7 +182,6 @@ impl Node { whois: WhoisQueue::new(), buffer_pool: Arc::new(PacketBufferPool::new(64, PooledBufferFactory)), secure_prng: SecureRandom::get(), - fips_mode: false, }) } @@ -202,9 +200,6 @@ impl Node { /// Get a peer by address. pub fn peer(&self, a: Address) -> Option> { self.peers.get(&a).map(|peer| peer.value().clone()) } - #[inline(always)] - pub fn fips_mode(&self) -> bool { self.fips_mode } - /// Get all peers currently in the peer cache. pub fn peers(&self) -> Vec> { let mut v: Vec> = Vec::new(); @@ -215,21 +210,20 @@ impl Node { v } + pub fn fips_mode(&self) -> bool { false } + /// Run background tasks and return desired delay until next call in milliseconds. - /// - /// This should only be called once at a time. It technically won't hurt anything to - /// call concurrently but it will waste CPU cycles. pub fn do_background_tasks(&self, ci: &CI) -> Duration { let mut intervals = self.intervals.lock(); let tt = ci.time_ticks(); if intervals.whois.gate(tt) { - self.whois.on_interval(self, ci, tt); + self.whois.call_every_interval(self, ci, tt); } if intervals.paths.gate(tt) { self.paths.retain(|_, path| { - path.on_interval(ci, tt); + path.call_every_interval(ci, tt); todo!(); true }); @@ -237,7 +231,7 @@ impl Node { if intervals.peers.gate(tt) { self.peers.retain(|_, peer| { - peer.on_interval(ci, tt); + peer.call_every_interval(ci, tt); todo!(); true }); @@ -251,14 +245,16 @@ impl Node { let fragment_header = data.struct_mut_at::(0); if fragment_header.is_ok() { let fragment_header = fragment_header.unwrap(); - let time_ticks = ci.time_ticks(); let dest = Address::from_bytes(&fragment_header.dest); if dest.is_some() { + let time_ticks = ci.time_ticks(); let dest = dest.unwrap(); if dest == self.identity.address() { + // Handle packets addressed to this node. let path = self.path(source_endpoint, source_local_socket, source_local_interface); path.log_receive(time_ticks); + if fragment_header.is_fragment() { let _ = path.receive_fragment(fragment_header.id, fragment_header.fragment_no(), fragment_header.total_fragments(), data, time_ticks).map(|assembled_packet| { @@ -301,6 +297,8 @@ impl Node { } } else { + // Forward packets not destined for this node. + // TODO: need to add check for whether this node should forward. Regular nodes should only forward if a trust relationship exists. if fragment_header.is_fragment() { if fragment_header.increment_hops() > FORWARD_MAX_HOPS { diff --git a/zerotier-network-hypervisor/src/vl1/path.rs b/zerotier-network-hypervisor/src/vl1/path.rs index a2aee47c7..7da15fafb 100644 --- a/zerotier-network-hypervisor/src/vl1/path.rs +++ b/zerotier-network-hypervisor/src/vl1/path.rs @@ -103,7 +103,7 @@ impl Path { /// Called every INTERVAL during background tasks. #[inline(always)] - pub(crate) fn on_interval(&self, ct: &CI, time_ticks: i64) { + pub(crate) fn call_every_interval(&self, ct: &CI, time_ticks: i64) { self.fragmented_packets.lock().retain(|packet_id, frag| (time_ticks - frag.ts_ticks) < FRAGMENT_EXPIRATION); } } diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index 9e0f1dd89..8f7cee3fd 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -504,7 +504,7 @@ impl Peer { /// Called every INTERVAL during background tasks. #[inline(always)] - pub(crate) fn on_interval(&self, ct: &CI, time_ticks: i64) {} + pub(crate) fn call_every_interval(&self, ct: &CI, time_ticks: i64) {} #[inline(always)] fn receive_hello(&self, ci: &CI, node: &Node, time_ticks: i64, source_path: &Arc, payload: &Buffer<{ PACKET_SIZE_MAX }>) {} diff --git a/zerotier-network-hypervisor/src/vl1/whoisqueue.rs b/zerotier-network-hypervisor/src/vl1/whoisqueue.rs index 9441b3765..844917b29 100644 --- a/zerotier-network-hypervisor/src/vl1/whoisqueue.rs +++ b/zerotier-network-hypervisor/src/vl1/whoisqueue.rs @@ -63,7 +63,7 @@ impl WhoisQueue { } /// Called every INTERVAL during background tasks. - pub fn on_interval(&self, node: &Node, ci: &CI, time_ticks: i64) { + pub fn call_every_interval(&self, node: &Node, ci: &CI, time_ticks: i64) { let mut targets: Vec
= Vec::new(); self.0.lock().retain(|target, qi| { if qi.retry_count < WHOIS_RETRY_MAX { diff --git a/zerotier-network-hypervisor/src/vl2/mod.rs b/zerotier-network-hypervisor/src/vl2/mod.rs index 28c2202a7..0d1c4ccbf 100644 --- a/zerotier-network-hypervisor/src/vl2/mod.rs +++ b/zerotier-network-hypervisor/src/vl2/mod.rs @@ -6,6 +6,7 @@ * https://www.zerotier.com/ */ +pub mod switch; mod multicastgroup; pub use multicastgroup::MulticastGroup; diff --git a/zerotier-network-hypervisor/src/vl2/switch.rs b/zerotier-network-hypervisor/src/vl2/switch.rs new file mode 100644 index 000000000..f2ad20d81 --- /dev/null +++ b/zerotier-network-hypervisor/src/vl2/switch.rs @@ -0,0 +1,37 @@ +/* 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::sync::Arc; + +use crate::vl1::node::VL1PacketHandler; +use crate::vl1::{Peer, Path}; +use crate::vl1::buffer::Buffer; +use crate::vl1::protocol::{PACKET_SIZE_MAX, PacketID}; + +pub struct Switch { +} + +impl VL1PacketHandler for Switch { + fn handle_packet(&self, peer: &Peer, source_path: &Arc, forward_secrecy: bool, extended_authentication: bool, verb: u8, payload: &Buffer<{ PACKET_SIZE_MAX }>) -> bool { + false + } + + fn handle_error(&self, peer: &Peer, source_path: &Arc, forward_secrecy: bool, extended_authentication: bool, in_re_verb: u8, in_re_packet_id: PacketID, error_code: u8, payload: &Buffer<{ PACKET_SIZE_MAX }>, cursor: &mut usize) -> bool { + false + } + + fn handle_ok(&self, peer: &Peer, source_path: &Arc, forward_secrecy: bool, extended_authentication: bool, in_re_verb: u8, in_re_packet_id: PacketID, payload: &Buffer<{ PACKET_SIZE_MAX }>, cursor: &mut usize) -> bool { + false + } +} + +impl Switch { + pub fn new() -> Self { + Self + } +} diff --git a/zerotier-system-service/src/commands/identity.rs b/zerotier-system-service/src/commands/identity.rs index 4ce357e93..00c9643b4 100644 --- a/zerotier-system-service/src/commands/identity.rs +++ b/zerotier-system-service/src/commands/identity.rs @@ -8,8 +8,6 @@ use clap::ArgMatches; -use zerotier_core::{Identity, IdentityType}; - fn new_(cli_args: &ArgMatches) -> i32 { let id_type = cli_args.value_of("type").map_or(IdentityType::Curve25519, |idt| { match idt { @@ -53,7 +51,7 @@ fn validate(cli_args: &ArgMatches) -> i32 { println!("FAILED"); 1 }, |id| { - if id.validate() { + if id.locally_validate() { println!("OK"); 0 } else { diff --git a/zerotier-system-service/src/service.rs b/zerotier-system-service/src/service.rs index 93364ff1c..efc564233 100644 --- a/zerotier-system-service/src/service.rs +++ b/zerotier-system-service/src/service.rs @@ -13,8 +13,8 @@ use std::sync::{Arc, Mutex, Weak}; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; -use zerotier_core::*; -use zerotier_core::trace::{TraceEvent, TraceEventLayer}; +use zerotier_network_hypervisor::vl1::{Address, Identity, InetAddress, MAC, PacketBuffer}; + use futures::StreamExt; use serde::{Serialize, Deserialize}; @@ -26,6 +26,7 @@ use crate::network::Network; use crate::store::Store; use crate::utils::{ms_since_epoch, ms_monotonic}; use crate::httplistener::HttpListener; +use zerotier_network_hypervisor::vl1::inetaddress::IpScope; /// How often to check for major configuration changes. This shouldn't happen /// too often since it uses a bit of CPU. @@ -362,7 +363,7 @@ async fn run_async(store: Arc, local_config: Arc) -> i32 { } for a in system_addrs.iter() { if !udp_sockets.contains_key(a.0) { - let _ = FastUDPSocket::new(a.1.as_str(), a.0, |raw_socket: &FastUDPRawOsSocket, from_address: &InetAddress, data: Buffer| { + let _ = FastUDPSocket::new(a.1.as_str(), a.0, |raw_socket: &FastUDPRawOsSocket, from_address: &InetAddress, data: PacketBuffer| { // TODO: incoming packet handler }).map_or_else(|e| { l!(service.log, "error binding UDP socket to {}: {}", a.0.to_string(), e.to_string()); diff --git a/zerotier-system-service/src/utils.rs b/zerotier-system-service/src/utils.rs index becd5de99..8f59255cd 100644 --- a/zerotier-system-service/src/utils.rs +++ b/zerotier-system-service/src/utils.rs @@ -11,11 +11,11 @@ use std::fs::File; use std::io::Read; use std::path::Path; -use zerotier_core::{Identity, Locator}; - use serde::Serialize; use serde::de::DeserializeOwned; +use zerotier_network_hypervisor::vl1::Identity; + use crate::osdep; #[inline(always)]