From 08e15bb92bb40c52311c425c0c282e37bfa1278d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Nov 2021 17:59:01 -0400 Subject: [PATCH] Docs, formatting. --- zerotier-core-crypto/Cargo.toml | 4 +- zerotier-core-crypto/src/c25519.rs | 6 - zerotier-core-crypto/src/hash.rs | 2 - zerotier-core-crypto/src/kbkdf.rs | 16 +- zerotier-core-crypto/src/poly1305.rs | 1 - zerotier-core-crypto/src/salsa.rs | 1 - zerotier-network-hypervisor/src/util/mod.rs | 20 +-- zerotier-network-hypervisor/src/vl1/buffer.rs | 10 ++ zerotier-network-hypervisor/src/vl1/mod.rs | 1 + zerotier-network-hypervisor/src/vl1/node.rs | 25 ++- zerotier-network-hypervisor/src/vl1/path.rs | 8 + zerotier-network-hypervisor/src/vl1/peer.rs | 10 +- .../src/vl1/protocol.rs | 8 + .../src/vl1/rootset.rs | 8 + .../src/vl1/whoisqueue.rs | 8 + zerotier-system-service/src/fastudpsocket.rs | 148 ++++++++---------- zerotier-system-service/src/getifaddrs.rs | 6 +- zerotier-system-service/src/httplistener.rs | 17 +- zerotier-system-service/src/localconfig.rs | 4 +- 19 files changed, 167 insertions(+), 136 deletions(-) diff --git a/zerotier-core-crypto/Cargo.toml b/zerotier-core-crypto/Cargo.toml index 5f75944b6..8d4f35455 100644 --- a/zerotier-core-crypto/Cargo.toml +++ b/zerotier-core-crypto/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" rand_core = "^0" aes-gmac-siv = { path = "../aes-gmac-siv" } gcrypt = "^0" -x25519-dalek = "^1" -ed25519-dalek = "^1" +x25519-dalek = { version = "^1", features = ["u64_backend"] } +ed25519-dalek = { version = "^1", features = ["u64_backend"] } diff --git a/zerotier-core-crypto/src/c25519.rs b/zerotier-core-crypto/src/c25519.rs index 704e0907c..07045975b 100644 --- a/zerotier-core-crypto/src/c25519.rs +++ b/zerotier-core-crypto/src/c25519.rs @@ -24,7 +24,6 @@ impl C25519KeyPair { C25519KeyPair(sk, pk) } - #[inline(always)] pub fn from_bytes(public_key: &[u8], secret_key: &[u8]) -> Option { if public_key.len() == 32 && secret_key.len() == 32 { let pk: [u8; 32] = public_key.try_into().unwrap(); @@ -44,7 +43,6 @@ impl C25519KeyPair { pub fn secret_bytes(&self) -> Secret<{ C25519_SECRET_KEY_SIZE }> { Secret(self.0.to_bytes()) } /// Execute ECDH agreement and return a raw (un-hashed) shared secret key. - #[inline(always)] pub fn agree(&self, their_public: &[u8]) -> Secret<{ C25519_SHARED_SECRET_SIZE }> { let pk: [u8; 32] = their_public.try_into().unwrap(); let pk = x25519_dalek::PublicKey::from(pk); @@ -63,7 +61,6 @@ impl Ed25519KeyPair { Ed25519KeyPair(ed25519_dalek::Keypair::generate(&mut rng)) } - #[inline(always)] pub fn from_bytes(public_bytes: &[u8], secret_bytes: &[u8]) -> Option { if public_bytes.len() == ED25519_PUBLIC_KEY_SIZE && secret_bytes.len() == ED25519_SECRET_KEY_SIZE { let pk = ed25519_dalek::PublicKey::from_bytes(public_bytes); @@ -87,7 +84,6 @@ impl Ed25519KeyPair { #[inline(always)] pub fn secret_bytes(&self) -> Secret<{ ED25519_SECRET_KEY_SIZE }> { Secret(self.0.secret.to_bytes()) } - #[inline(always)] pub fn sign(&self, msg: &[u8]) -> [u8; ED25519_SIGNATURE_SIZE] { let mut h = ed25519_dalek::Sha512::new(); let _ = h.write_all(msg); @@ -96,7 +92,6 @@ impl Ed25519KeyPair { /// Create a signature with the first 32 bytes of the SHA512 hash appended. /// ZeroTier does this for legacy reasons, but it's ignored in newer versions. - #[inline(always)] pub fn sign_zt(&self, msg: &[u8]) -> [u8; 96] { let mut h = ed25519_dalek::Sha512::new(); let _ = h.write_all(msg); @@ -110,7 +105,6 @@ impl Ed25519KeyPair { } } -#[inline(always)] pub fn ed25519_verify(public_key: &[u8], signature: &[u8], msg: &[u8]) -> bool { if public_key.len() == 32 && signature.len() >= 64 { ed25519_dalek::PublicKey::from_bytes(public_key).map_or(false, |pk| { diff --git a/zerotier-core-crypto/src/hash.rs b/zerotier-core-crypto/src/hash.rs index 562bab02f..bf9cfef64 100644 --- a/zerotier-core-crypto/src/hash.rs +++ b/zerotier-core-crypto/src/hash.rs @@ -15,7 +15,6 @@ impl SHA512 { h } - #[inline(always)] pub fn hmac(key: &[u8], msg: &[u8]) -> [u8; SHA512_HASH_SIZE] { let mut m = gcrypt::mac::Mac::new(gcrypt::mac::Algorithm::HmacSha512).unwrap(); let _ = m.set_key(key); @@ -68,7 +67,6 @@ impl SHA384 { h } - #[inline(always)] pub fn hmac(key: &[u8], msg: &[u8]) -> [u8; SHA384_HASH_SIZE] { let mut m = gcrypt::mac::Mac::new(gcrypt::mac::Algorithm::HmacSha384).unwrap(); let _ = m.set_key(key); diff --git a/zerotier-core-crypto/src/kbkdf.rs b/zerotier-core-crypto/src/kbkdf.rs index 99f5d7aed..bce63e163 100644 --- a/zerotier-core-crypto/src/kbkdf.rs +++ b/zerotier-core-crypto/src/kbkdf.rs @@ -11,5 +11,19 @@ pub fn zt_kbkdf_hmac_sha384(key: &[u8], label: u8, context: u8, iter: u32) -> Se // HMAC'd message is: preface | iteration[4], preface[2], label, 0x00, context, hash size[4] // See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-108.pdf - Secret(SHA384::hmac(key, &[(iter >> 24) as u8, (iter >> 16) as u8, (iter >> 8) as u8, iter as u8, b'Z', b'T', label, 0, context, 0, 0, 0x01, 0x80])) + Secret(SHA384::hmac(key, &[ + (iter >> 24) as u8, + (iter >> 16) as u8, + (iter >> 8) as u8, + iter as u8, + b'Z', + b'T', + label, + 0, + context, + 0, + 0, + 0x01, + 0x80 + ])) } diff --git a/zerotier-core-crypto/src/poly1305.rs b/zerotier-core-crypto/src/poly1305.rs index ae1108f5d..497ce4c96 100644 --- a/zerotier-core-crypto/src/poly1305.rs +++ b/zerotier-core-crypto/src/poly1305.rs @@ -5,7 +5,6 @@ pub const POLY1305_ONE_TIME_KEY_SIZE: usize = 32; pub const POLY1305_MAC_SIZE: usize = 16; impl Poly1305 { - #[inline(always)] pub fn new(key: &[u8]) -> Option { if key.len() == 32 { gcrypt::mac::Mac::new(gcrypt::mac::Algorithm::Poly1305).map_or(None, |mut poly| { diff --git a/zerotier-core-crypto/src/salsa.rs b/zerotier-core-crypto/src/salsa.rs index 5c22d202a..7ba8d8489 100644 --- a/zerotier-core-crypto/src/salsa.rs +++ b/zerotier-core-crypto/src/salsa.rs @@ -5,7 +5,6 @@ impl Salsa { /// Initialize Salsa cipher. /// Key must be 32 bytes and iv must be 8 bytes. If r12 is true the 12-round /// variant of Salsa will be used, otherwise 20 rounds are used. - #[inline(always)] pub fn new(key: &[u8], iv: &[u8], r12: bool) -> Option { if key.len() == 32 && iv.len() == 8 { gcrypt::cipher::Cipher::new(if r12 { gcrypt::cipher::Algorithm::Salsa20r12 } else { gcrypt::cipher::Algorithm::Salsa20 }, gcrypt::cipher::Mode::Stream).map_or(None, |mut salsa| { diff --git a/zerotier-network-hypervisor/src/util/mod.rs b/zerotier-network-hypervisor/src/util/mod.rs index 0cede85e8..09d9b2c24 100644 --- a/zerotier-network-hypervisor/src/util/mod.rs +++ b/zerotier-network-hypervisor/src/util/mod.rs @@ -128,16 +128,12 @@ pub(crate) struct U64PassThroughHasher(u64); impl U64PassThroughHasher { #[inline(always)] - pub fn new() -> Self { - Self(0) - } + pub fn new() -> Self { Self(0) } } impl std::hash::Hasher for U64PassThroughHasher { #[inline(always)] - fn finish(&self) -> u64 { - self.0 - } + fn finish(&self) -> u64 { self.0 } #[inline(always)] fn write(&mut self, _: &[u8]) { @@ -145,21 +141,15 @@ impl std::hash::Hasher for U64PassThroughHasher { } #[inline(always)] - fn write_u64(&mut self, i: u64) { - self.0 += i; - } + fn write_u64(&mut self, i: u64) { self.0 += i; } #[inline(always)] - fn write_i64(&mut self, i: i64) { - self.0 += i as u64; - } + fn write_i64(&mut self, i: i64) { self.0 += i as u64; } } impl std::hash::BuildHasher for U64PassThroughHasher { type Hasher = Self; #[inline(always)] - fn build_hasher(&self) -> Self::Hasher { - Self(0) - } + fn build_hasher(&self) -> Self::Hasher { Self(0) } } diff --git a/zerotier-network-hypervisor/src/vl1/buffer.rs b/zerotier-network-hypervisor/src/vl1/buffer.rs index bdf6ca66f..6f6923984 100644 --- a/zerotier-network-hypervisor/src/vl1/buffer.rs +++ b/zerotier-network-hypervisor/src/vl1/buffer.rs @@ -24,6 +24,10 @@ impl Default for Buffer { const OVERFLOW_ERR_MSG: &'static str = "overflow"; impl Buffer { + pub const CAPACITY: usize = L; + + pub const fn capacity(&self) -> usize { L } + #[inline(always)] pub fn new() -> Self { Self(0, [0_u8; L]) } @@ -47,6 +51,12 @@ impl Buffer { #[inline(always)] pub fn as_bytes_mut(&mut self) -> &mut [u8] { &mut self.1[0..self.0] } + #[inline(always)] + pub fn as_ptr(&self) -> *const u8 { self.1.as_ptr() } + + #[inline(always)] + pub fn as_mut_ptr(&mut self) -> *mut u8 { self.1.as_mut_ptr() } + /// Get all bytes after a given position. #[inline(always)] pub fn as_bytes_starting_at(&self, start: usize) -> std::io::Result<&[u8]> { diff --git a/zerotier-network-hypervisor/src/vl1/mod.rs b/zerotier-network-hypervisor/src/vl1/mod.rs index 3ab6f25ac..d5ccbad58 100644 --- a/zerotier-network-hypervisor/src/vl1/mod.rs +++ b/zerotier-network-hypervisor/src/vl1/mod.rs @@ -28,3 +28,4 @@ pub use inetaddress::InetAddress; pub use locator::Locator; pub use peer::Peer; pub use path::Path; +pub use node::{PacketBuffer, PacketBufferPool, PacketBufferFactory}; diff --git a/zerotier-network-hypervisor/src/vl1/node.rs b/zerotier-network-hypervisor/src/vl1/node.rs index 9db08f746..da2b2a039 100644 --- a/zerotier-network-hypervisor/src/vl1/node.rs +++ b/zerotier-network-hypervisor/src/vl1/node.rs @@ -5,7 +5,8 @@ use std::time::Duration; use dashmap::DashMap; use parking_lot::Mutex; -use zerotier_core_crypto::random::{SecureRandom, next_u64_secure}; +use zerotier_core_crypto::random::{next_u64_secure, SecureRandom}; + use crate::error::InvalidParameterError; use crate::util::gate::IntervalGate; use crate::util::pool::{Pool, Pooled}; @@ -14,12 +15,18 @@ use crate::vl1::buffer::{Buffer, PooledBufferFactory}; use crate::vl1::path::Path; use crate::vl1::peer::Peer; use crate::vl1::protocol::*; -use crate::vl1::whoisqueue::{WhoisQueue, QueuedPacket}; use crate::vl1::rootset::RootSet; +use crate::vl1::whoisqueue::{QueuedPacket, WhoisQueue}; /// Standard packet buffer type including pool container. pub type PacketBuffer = Pooled, PooledBufferFactory<{ PACKET_SIZE_MAX }>>; +/// Factory type to supply to a new PacketBufferPool. +pub type PacketBufferFactory = PooledBufferFactory<{ PACKET_SIZE_MAX }>; + +/// Source for instances of PacketBuffer +pub type PacketBufferPool = Pool, PacketBufferFactory>; + /// Callback interface and call context for calls to the node (for VL1). /// /// Every non-trivial call takes a reference to this, which it passes all the way through @@ -132,7 +139,7 @@ pub struct Node { roots: Mutex>>, root_sets: Mutex>, whois: WhoisQueue, - buffer_pool: Pool, PooledBufferFactory<{ PACKET_SIZE_MAX }>>, + buffer_pool: Arc, secure_prng: SecureRandom, fips_mode: bool, } @@ -174,12 +181,18 @@ impl Node { roots: Mutex::new(Vec::new()), root_sets: Mutex::new(Vec::new()), whois: WhoisQueue::new(), - buffer_pool: Pool::new(64, PooledBufferFactory), + buffer_pool: Arc::new(PacketBufferPool::new(64, PooledBufferFactory)), secure_prng: SecureRandom::get(), fips_mode: false, }) } + #[inline(always)] + pub fn get_packet_buffer(&self) -> PacketBuffer { self.buffer_pool.get() } + + #[inline(always)] + pub fn packet_buffer_pool(&self) -> &Arc { &self.buffer_pool } + #[inline(always)] pub fn address(&self) -> Address { self.identity.address() } @@ -189,10 +202,6 @@ impl Node { #[inline(always)] pub fn locator(&self) -> Option> { self.locator.lock().clone() } - /// Get a reusable packet buffer. - /// The buffer will automatically be returned to the pool if it is dropped. - pub fn get_packet_buffer(&self) -> PacketBuffer { self.buffer_pool.get() } - /// 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/path.rs b/zerotier-network-hypervisor/src/vl1/path.rs index a44e14669..a2aee47c7 100644 --- a/zerotier-network-hypervisor/src/vl1/path.rs +++ b/zerotier-network-hypervisor/src/vl1/path.rs @@ -1,3 +1,11 @@ +/* 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::collections::HashMap; use std::sync::atomic::{AtomicI64, Ordering}; diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index 0bee61f9c..a122c74ac 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -1,3 +1,11 @@ +/* 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::convert::TryInto; use std::mem::MaybeUninit; use std::ptr::copy_nonoverlapping; @@ -298,7 +306,7 @@ impl Peer { if (verb & VERB_FLAG_COMPRESSED) != 0 { let mut decompressed_payload = node.get_packet_buffer(); let _ = decompressed_payload.append_u8(verb); - let dlen = lz4_flex::block::decompress_into(&payload.as_bytes()[1..], &mut decompressed_payload.as_bytes_mut(), 1); + let dlen = lz4_flex::block::decompress_into(&payload.as_bytes()[1..], &mut decompressed_payload.as_bytes_mut()); if dlen.is_ok() { decompressed_payload.set_size(dlen.unwrap()); payload = decompressed_payload; diff --git a/zerotier-network-hypervisor/src/vl1/protocol.rs b/zerotier-network-hypervisor/src/vl1/protocol.rs index 1c0847b91..2b0534f3d 100644 --- a/zerotier-network-hypervisor/src/vl1/protocol.rs +++ b/zerotier-network-hypervisor/src/vl1/protocol.rs @@ -1,3 +1,11 @@ +/* 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::mem::MaybeUninit; use crate::vl1::Address; diff --git a/zerotier-network-hypervisor/src/vl1/rootset.rs b/zerotier-network-hypervisor/src/vl1/rootset.rs index 815df35a6..7b4bee2c2 100644 --- a/zerotier-network-hypervisor/src/vl1/rootset.rs +++ b/zerotier-network-hypervisor/src/vl1/rootset.rs @@ -1,3 +1,11 @@ +/* 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::hash::{Hash, Hasher}; use std::io::Write; diff --git a/zerotier-network-hypervisor/src/vl1/whoisqueue.rs b/zerotier-network-hypervisor/src/vl1/whoisqueue.rs index 7e4e7388e..9441b3765 100644 --- a/zerotier-network-hypervisor/src/vl1/whoisqueue.rs +++ b/zerotier-network-hypervisor/src/vl1/whoisqueue.rs @@ -1,3 +1,11 @@ +/* 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::collections::{HashMap, LinkedList}; use parking_lot::Mutex; diff --git a/zerotier-system-service/src/fastudpsocket.rs b/zerotier-system-service/src/fastudpsocket.rs index 62121ec05..41480d165 100644 --- a/zerotier-system-service/src/fastudpsocket.rs +++ b/zerotier-system-service/src/fastudpsocket.rs @@ -17,9 +17,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use num_traits::cast::AsPrimitive; -use zerotier_core::{Buffer, InetAddress, InetAddressFamily}; - -use crate::osdep as osdep; +use zerotier_network_hypervisor::vl1::{InetAddress, PacketBuffer, PacketBufferPool}; /* * This is a threaded UDP socket listener for high performance. The fastest way to receive UDP @@ -27,9 +25,6 @@ use crate::osdep as osdep; * for each thread using options like SO_REUSEPORT and concurrent packet listening. */ -#[cfg(windows)] -use winapi::um::winsock2 as winsock2; - #[cfg(windows)] pub(crate) type FastUDPRawOsSocket = winsock2::SOCKET; @@ -40,89 +35,85 @@ pub(crate) type FastUDPRawOsSocket = c_int; fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result { unsafe { let (af, sa_len) = match address.family() { - InetAddressFamily::IPv4 => (osdep::AF_INET, std::mem::size_of::() as osdep::socklen_t), - InetAddressFamily::IPv6 => (osdep::AF_INET6, std::mem::size_of::() as osdep::socklen_t), + InetAddressFamily::IPv4 => (libc::AF_INET, std::mem::size_of::() as libc::socklen_t), + InetAddressFamily::IPv6 => (libc::AF_INET6, std::mem::size_of::() as libc::socklen_t), _ => { return Err("unrecognized address family"); } }; - #[cfg(not(target_os = "linux"))] - let s = osdep::socket(af.as_(), osdep::SOCK_DGRAM.as_(), 0); - #[cfg(target_os = "linux")] - let s = osdep::socket(af.as_(), 2, 0); - + let s = libc::socket(af.as_(), libc::SOCK_DGRAM, 0); if s < 0 { return Err("unable to create socket"); } let mut fl: c_int; - let fl_size = std::mem::size_of::() as osdep::socklen_t; + let fl_size = std::mem::size_of::() as libc::socklen_t; let mut setsockopt_results: c_int = 0; fl = 1; - setsockopt_results |= osdep::setsockopt(s, osdep::SOL_SOCKET.as_(), osdep::SO_REUSEPORT.as_(), (&mut fl as *mut c_int).cast(), fl_size); + setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_REUSEPORT.as_(), (&mut fl as *mut c_int).cast(), fl_size); //fl = 1; - //setsockopt_results |= osdep::setsockopt(s, osdep::SOL_SOCKET, osdep::SO_REUSEADDR, (&mut fl as *mut c_int).cast(), fl_size); + //setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET, libc::SO_REUSEADDR, (&mut fl as *mut c_int).cast(), fl_size); fl = 1; - setsockopt_results |= osdep::setsockopt(s, osdep::SOL_SOCKET.as_(), osdep::SO_BROADCAST.as_(), (&mut fl as *mut c_int).cast(), fl_size); - if af == osdep::AF_INET6 { + setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_BROADCAST.as_(), (&mut fl as *mut c_int).cast(), fl_size); + if af == libc::AF_INET6 { fl = 1; - setsockopt_results |= osdep::setsockopt(s, osdep::IPPROTO_IPV6.as_(), osdep::IPV6_V6ONLY.as_(), (&mut fl as *mut c_int).cast(), fl_size); + setsockopt_results |= libc::setsockopt(s, libc::IPPROTO_IPV6.as_(), libc::IPV6_V6ONLY.as_(), (&mut fl as *mut c_int).cast(), fl_size); } #[cfg(any(target_os = "macos", target_os = "ios"))] { fl = 1; - setsockopt_results |= osdep::setsockopt(s, osdep::SOL_SOCKET.as_(), osdep::SO_NOSIGPIPE.as_(), (&mut fl as *mut c_int).cast(), fl_size) + setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_NOSIGPIPE.as_(), (&mut fl as *mut c_int).cast(), fl_size) } #[cfg(target_os = "linux")] { if !_device_name.is_empty() { let _ = std::ffi::CString::new(_device_name).map(|dn| { let dnb = dn.as_bytes_with_nul(); - let _ = osdep::setsockopt(s.as_(), osdep::SOL_SOCKET.as_(), osdep::SO_BINDTODEVICE.as_(), dnb.as_ptr().cast(), (dnb.len() - 1).as_()); + let _ = libc::setsockopt(s.as_(), libc::SOL_SOCKET.as_(), libc::SO_BINDTODEVICE.as_(), dnb.as_ptr().cast(), (dnb.len() - 1).as_()); }); } } if setsockopt_results != 0 { - osdep::close(s); + libc::close(s); return Err("setsockopt() failed"); } - if af == osdep::AF_INET { + if af == libc::AF_INET { #[cfg(not(target_os = "linux"))] { fl = 0; - osdep::setsockopt(s, osdep::IPPROTO_IP.as_(), osdep::IP_DF.as_(), (&mut fl as *mut c_int).cast(), fl_size); + libc::setsockopt(s, libc::IPPROTO_IP.as_(), libc::IP_DF.as_(), (&mut fl as *mut c_int).cast(), fl_size); } #[cfg(target_os = "linux")] { - fl = osdep::IP_PMTUDISC_DONT as c_int; - osdep::setsockopt(s, osdep::IPPROTO_IP.as_(), osdep::IP_MTU_DISCOVER.as_(), (&mut fl as *mut c_int).cast(), fl_size); + fl = libc::IP_PMTUDISC_DONT as c_int; + libc::setsockopt(s, libc::IPPROTO_IP.as_(), libc::IP_MTU_DISCOVER.as_(), (&mut fl as *mut c_int).cast(), fl_size); } } - if af == osdep::AF_INET6 { + if af == libc::AF_INET6 { fl = 0; - osdep::setsockopt(s, osdep::IPPROTO_IPV6.as_(), osdep::IPV6_DONTFRAG.as_(), (&mut fl as *mut c_int).cast(), fl_size); + libc::setsockopt(s, libc::IPPROTO_IPV6.as_(), libc::IPV6_DONTFRAG.as_(), (&mut fl as *mut c_int).cast(), fl_size); } fl = 1048576; while fl >= 131072 { - if osdep::setsockopt(s, osdep::SOL_SOCKET.as_(), osdep::SO_RCVBUF.as_(), (&mut fl as *mut c_int).cast(), fl_size) == 0 { + if libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_RCVBUF.as_(), (&mut fl as *mut c_int).cast(), fl_size) == 0 { break; } fl -= 65536; } fl = 1048576; while fl >= 131072 { - if osdep::setsockopt(s, osdep::SOL_SOCKET.as_(), osdep::SO_SNDBUF.as_(), (&mut fl as *mut c_int).cast(), fl_size) == 0 { + if libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_SNDBUF.as_(), (&mut fl as *mut c_int).cast(), fl_size) == 0 { break; } fl -= 65536; } - if osdep::bind(s, (address as *const InetAddress).cast(), sa_len) != 0 { - osdep::close(s); + if libc::bind(s, (address as *const InetAddress).cast(), sa_len) != 0 { + libc::close(s); return Err("bind to address failed"); } @@ -141,30 +132,19 @@ pub(crate) struct FastUDPSocket { #[cfg(unix)] #[inline(always)] fn fast_udp_socket_close(socket: &FastUDPRawOsSocket) { - unsafe { - osdep::close(*socket); - } -} - -#[cfg(windows)] -#[inline(always)] -fn fast_udp_socket_close(socket: &FastUDPRawOsSocket) { - unsafe { - osdep::close(*socket); - } + unsafe { libc::close(*socket); } } #[inline(always)] -pub(crate) fn fast_udp_socket_to_i64(socket: &FastUDPRawOsSocket) -> i64 { - (*socket) as i64 -} +pub(crate) fn fast_udp_socket_to_i64(socket: &FastUDPRawOsSocket) -> i64 { (*socket) as i64 } #[inline(always)] pub(crate) fn fast_udp_socket_from_i64(socket: i64) -> Option { if socket >= 0 { - return Some(socket as FastUDPRawOsSocket); + Some(socket as FastUDPRawOsSocket) + } else { + None } - None } /// Send to a raw UDP socket with optional packet TTL. @@ -172,38 +152,38 @@ pub(crate) fn fast_udp_socket_from_i64(socket: i64) -> Option().as_()); + libc::sendto(*socket, data.as_ptr().cast(), data.len().as_(), 0, (to_address as *const InetAddress).cast(), std::mem::size_of::().as_()); } else { let mut ttl = packet_ttl as c_int; - osdep::setsockopt(*socket, osdep::IPPROTO_IP.as_(), osdep::IP_TTL.as_(), (&mut ttl as *mut c_int).cast(), std::mem::size_of::().as_()); - osdep::sendto(*socket, data.cast(), len.as_(), 0, (to_address as *const InetAddress).cast(), std::mem::size_of::().as_()); + libc::setsockopt(*socket, libc::IPPROTO_IP.as_(), libc::IP_TTL.as_(), (&mut ttl as *mut c_int).cast(), std::mem::size_of::().as_()); + libc::sendto(*socket, data.as_ptr().cast(), data.len().as_(), 0, (to_address as *const InetAddress).cast(), std::mem::size_of::().as_()); ttl = 255; - osdep::setsockopt(*socket, osdep::IPPROTO_IP.as_(), osdep::IP_TTL.as_(), (&mut ttl as *mut c_int).cast(), std::mem::size_of::().as_()); + libc::setsockopt(*socket, libc::IPPROTO_IP.as_(), libc::IP_TTL.as_(), (&mut ttl as *mut c_int).cast(), std::mem::size_of::().as_()); } } } -#[cfg(windows)] -#[inline(always)] -pub(crate) fn fast_udp_socket_sendto(socket: &FastUDPRawOsSocket, to_address: &InetAddress, data: &[u8], packet_ttl: i32) {} - #[cfg(unix)] #[inline(always)] -fn fast_udp_socket_recvfrom(socket: &FastUDPRawOsSocket, buf: &mut Buffer, from_address: &mut InetAddress) -> i32 { +fn fast_udp_socket_recvfrom(socket: &FastUDPRawOsSocket, buf: &mut PacketBuffer, from_address: &mut InetAddress) -> isize { unsafe { - let mut addrlen = std::mem::size_of::() as osdep::socklen_t; - osdep::recvfrom(*socket, buf.as_mut_ptr().cast(), Buffer::CAPACITY.as_(), 0, (from_address as *mut InetAddress).cast(), &mut addrlen) as i32 + let mut addrlen = std::mem::size_of::() as libc::socklen_t; + let s = libc::recvfrom(*socket, buf.as_mut_ptr().cast(), buf.capacity().as_(), 0, (from_address as *mut InetAddress).cast(), &mut addrlen) as isize; + if s > 0 { + buf.set_size_unchecked(s as usize); + } + s } } impl FastUDPSocket { - pub fn new(device_name: &str, address: &InetAddress, handler: F) -> Result { - let thread_count = num_cpus::get_physical().min(num_cpus::get()); + 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 mut s = FastUDPSocket { + let mut s = Self { thread_run: Arc::new(AtomicBool::new(true)), threads: Vec::new(), sockets: Vec::new(), @@ -221,15 +201,15 @@ impl FastUDPSocket { let thread_run = s.thread_run.clone(); let handler_copy = handler.clone(); + let packet_buffer_pool_copy = packet_buffer_pool.clone(); s.threads.push(std::thread::Builder::new().stack_size(zerotier_core::RECOMMENDED_THREAD_STACK_SIZE).spawn(move || { let mut from_address = InetAddress::new(); while thread_run.load(Ordering::Relaxed) { - let mut buf = Buffer::new(); - let read_length = fast_udp_socket_recvfrom(&thread_socket, &mut buf, &mut from_address); - if read_length > 0 { - buf.set_len(read_length as usize); + let mut buf = packet_buffer_pool_copy.get_packet_buffer(); + let s = fast_udp_socket_recvfrom(&thread_socket, &mut buf, &mut from_address); + if s > 0 { handler_copy(&thread_socket, &from_address, buf); - } else if read_length < 0 { + } else if s < 0 { break; } } @@ -249,22 +229,16 @@ impl FastUDPSocket { Ok(s) } - /// Get a slice of all raw sockets used. #[inline(always)] pub fn all_sockets(&self) -> &[FastUDPRawOsSocket] { self.sockets.as_slice() } - /// Send from this socket. - /// This actually picks a thread's socket and sends from it. Since all - /// are bound to the same IP:port which one is chosen doesn't matter. - /// Sockets are thread safe. #[inline(always)] - pub fn send(&self, to_address: &InetAddress, data: *const u8, len: usize, packet_ttl: i32) { - fast_udp_socket_sendto(self.sockets.get(0).unwrap(), to_address, data, len, packet_ttl); + pub fn send(&self, to_address: &InetAddress, data: &[u8], packet_ttl: i32) { + fast_udp_socket_sendto(self.sockets.get(0).unwrap(), to_address, data, packet_ttl); } - /// Get a raw socket that can be used to send UDP packets. #[inline(always)] pub fn raw_socket(&self) -> FastUDPRawOsSocket { *self.sockets.get(0).unwrap() @@ -274,7 +248,7 @@ impl FastUDPSocket { impl Drop for FastUDPSocket { #[cfg(windows)] fn drop(&mut self) { - // TODO + todo!() } #[cfg(unix)] @@ -283,17 +257,17 @@ impl Drop for FastUDPSocket { self.thread_run.store(false, Ordering::Relaxed); for s in self.sockets.iter() { unsafe { - osdep::sendto(*s, tmp.as_ptr().cast(), 0, 0, (&self.bind_address as *const InetAddress).cast(), std::mem::size_of::() as osdep::socklen_t); + libc::sendto(*s, tmp.as_ptr().cast(), 0, 0, (&self.bind_address as *const InetAddress).cast(), std::mem::size_of::() as osdep::socklen_t); } } for s in self.sockets.iter() { unsafe { - osdep::shutdown(*s, osdep::SHUT_RDWR.as_()); + libc::shutdown(*s, libc::SHUT_RDWR.as_()); } } for s in self.sockets.iter() { unsafe { - osdep::close(*s); + libc::close(*s); } } while !self.threads.is_empty() { @@ -306,19 +280,21 @@ impl Drop for FastUDPSocket { mod tests { use std::sync::atomic::{AtomicU32, Ordering}; - use zerotier_core::{Buffer, InetAddress}; + use zerotier_network_hypervisor::vl1::{PacketBuffer, PacketBufferPool, PacketBufferFactory}; use crate::fastudpsocket::*; #[test] fn test_udp_bind_and_transfer() { { + let pool = Arc::new(PacketBufferPool::new(64, PacketBufferFactory)); + let ba0 = InetAddress::new_from_string("127.0.0.1/23333"); assert!(ba0.is_some()); let ba0 = ba0.unwrap(); let cnt0 = Arc::new(AtomicU32::new(0)); let cnt0c = cnt0.clone(); - let s0 = FastUDPSocket::new("", &ba0, move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: Buffer| { + let s0 = FastUDPSocket::new("", &ba0, &pool, move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: PacketBuffer| { cnt0c.fetch_add(1, Ordering::Relaxed); }); assert!(s0.is_ok()); @@ -329,7 +305,7 @@ mod tests { let ba1 = ba1.unwrap(); let cnt1 = Arc::new(AtomicU32::new(0)); let cnt1c = cnt1.clone(); - let s1 = FastUDPSocket::new("", &ba1, move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: Buffer| { + let s1 = FastUDPSocket::new("", &ba1, &pool, move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: PacketBuffer| { cnt1c.fetch_add(1, Ordering::Relaxed); }); assert!(s1.is_ok()); @@ -337,13 +313,13 @@ mod tests { let data_bytes = [0_u8; 1024]; loop { - s0.send(&ba1, data_bytes.as_ptr(), data_bytes.len(), 0); - s1.send(&ba0, data_bytes.as_ptr(), data_bytes.len(), 0); + s0.send(&ba1, &data_bytes, 0); + s1.send(&ba0, &data_bytes, 0); if cnt0.load(Ordering::Relaxed) > 10000 && cnt1.load(Ordering::Relaxed) > 10000 { break; } } } - //println!("FastUDPSocket shutdown successful"); + println!("FastUDPSocket shutdown successful"); } } diff --git a/zerotier-system-service/src/getifaddrs.rs b/zerotier-system-service/src/getifaddrs.rs index f95c7c044..2419efbaa 100644 --- a/zerotier-system-service/src/getifaddrs.rs +++ b/zerotier-system-service/src/getifaddrs.rs @@ -16,9 +16,9 @@ use std::ptr::{copy_nonoverlapping, null_mut}; use zerotier_network_hypervisor::vl1::InetAddress; -fn s6_addr_as_ptr(a: &A) -> *const A { - a as *const A -} +#[allow(unused)] +#[inline(always)] +fn s6_addr_as_ptr(a: &A) -> *const A { a as *const A } /// Call supplied function or closure for each physical IP address in the system. #[cfg(unix)] diff --git a/zerotier-system-service/src/httplistener.rs b/zerotier-system-service/src/httplistener.rs index 37da33536..e72612ce8 100644 --- a/zerotier-system-service/src/httplistener.rs +++ b/zerotier-system-service/src/httplistener.rs @@ -13,21 +13,20 @@ use std::cell::Cell; use std::convert::Infallible; -use std::sync::Arc; use std::net::SocketAddr; +#[cfg(target_os = "linux")] +use std::os::unix::io::AsRawFd; +use std::sync::Arc; -use hyper::{Body, Request, Response, StatusCode, Method}; +use digest_auth::{AuthContext, AuthorizationHeader, Charset, WwwAuthenticateHeader}; +use hyper::{Body, Method, Request, Response, StatusCode}; use hyper::server::Server; use hyper::service::{make_service_fn, service_fn}; use tokio::task::JoinHandle; -use digest_auth::{AuthContext, AuthorizationHeader, Charset, WwwAuthenticateHeader}; -use crate::service::Service; use crate::api; -use crate::utils::{decrypt_http_auth_nonce, ms_since_epoch, create_http_auth_nonce}; - -#[cfg(target_os = "linux")] -use std::os::unix::io::AsRawFd; +use crate::service::Service; +use crate::utils::{create_http_auth_nonce, decrypt_http_auth_nonce, ms_since_epoch}; const HTTP_MAX_NONCE_AGE_MS: i64 = 30000; @@ -158,7 +157,7 @@ impl HttpListener { unsafe { let _ = std::ffi::CString::new(_device_name).map(|dn| { let dnb = dn.as_bytes_with_nul(); - let _ = crate::osdep::setsockopt(sock as std::os::raw::c_int, crate::osdep::SOL_SOCKET as std::os::raw::c_int, crate::osdep::SO_BINDTODEVICE as std::os::raw::c_int, dnb.as_ptr().cast(), (dnb.len() - 1) as crate::osdep::socklen_t); + let _ = libc::setsockopt(sock as std::os::raw::c_int, libc::SOL_SOCKET as std::os::raw::c_int, libc::SO_BINDTODEVICE as std::os::raw::c_int, dnb.as_ptr().cast(), (dnb.len() - 1) as libc::socklen_t); }); } } diff --git a/zerotier-system-service/src/localconfig.rs b/zerotier-system-service/src/localconfig.rs index a1d2083a5..0dd45006c 100644 --- a/zerotier-system-service/src/localconfig.rs +++ b/zerotier-system-service/src/localconfig.rs @@ -12,9 +12,11 @@ /****/ use std::collections::BTreeMap; -use zerotier_core::{InetAddress, Address, NetworkId}; + use serde::{Deserialize, Serialize}; +use zerotier_network_hypervisor::vl1::{Address, InetAddress}; + pub const UNASSIGNED_PRIVILEGED_PORTS: [u16; 299] = [ 4, 6,