mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-12 07:23:45 +02:00
Add a bunch of stuff to InetAddress, clean up, fix some build errors in service.
This commit is contained in:
parent
6d59dd77c4
commit
3bdefc1d83
20 changed files with 355 additions and 1526 deletions
|
@ -76,9 +76,16 @@ impl P384PublicKey {
|
|||
let r = BigNum::from_slice(&signature[0..48]);
|
||||
let s = BigNum::from_slice(&signature[48..96]);
|
||||
if r.is_ok() && s.is_ok() {
|
||||
let sig = EcdsaSig::from_private_components(r.unwrap(), s.unwrap());
|
||||
if sig.is_ok() {
|
||||
return sig.unwrap().verify(&SHA384::hash(msg), self.key.as_ref()).unwrap_or(false);
|
||||
let r = r.unwrap();
|
||||
let s = s.unwrap();
|
||||
let z = BigNum::from_u32(0).unwrap();
|
||||
// Check that r and s are >=1 just in case the OpenSSL version or an OpenSSL API lookalike is
|
||||
// vulnerable to this, since a bunch of vulnerabilities involving zero r/s just made the rounds.
|
||||
if r.gt(&z) && s.gt(&z) {
|
||||
let sig = EcdsaSig::from_private_components(r, s);
|
||||
if sig.is_ok() {
|
||||
return sig.unwrap().verify(&SHA384::hash(msg), self.key.as_ref()).unwrap_or(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ lz4_flex = { version = "^0", features = ["safe-encode", "safe-decode", "checked-
|
|||
dashmap = "^4"
|
||||
parking_lot = "^0"
|
||||
lazy_static = "^1"
|
||||
highway = "^0"
|
||||
serde = "^1"
|
||||
serde_derive = "^1"
|
||||
serde_json = "^1"
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* https://www.zerotier.com/
|
||||
*/
|
||||
|
||||
use crate::util::{array_range, array_range_mut};
|
||||
use std::io::Write;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
|
||||
|
@ -77,7 +76,7 @@ impl<const L: usize> Buffer<L> {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn as_range_fixed<const START: usize, const LEN: usize>(&self) -> &[u8; LEN] {
|
||||
array_range::<u8, L, START, LEN>(&self.1)
|
||||
crate::util::byte_array_range::<L, START, LEN>(&self.1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -92,7 +91,7 @@ impl<const L: usize> Buffer<L> {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn as_mut_range_fixed<const START: usize, const LEN: usize>(&mut self) -> &mut [u8; LEN] {
|
||||
array_range_mut::<u8, L, START, LEN>(&mut self.1)
|
||||
crate::util::byte_array_range_mut::<L, START, LEN>(&mut self.1)
|
||||
}
|
||||
|
||||
/// Get all bytes after a given position.
|
||||
|
|
|
@ -15,35 +15,18 @@ pub use zerotier_core_crypto::varint;
|
|||
|
||||
pub(crate) const ZEROES: [u8; 64] = [0_u8; 64];
|
||||
|
||||
/// Obtain a reference to a sub-array within an existing array.
|
||||
/// Obtain a reference to a sub-array within an existing byte array.
|
||||
#[inline(always)]
|
||||
pub(crate) fn array_range<T, const A: usize, const START: usize, const LEN: usize>(a: &[T; A]) -> &[T; LEN] {
|
||||
pub(crate) fn byte_array_range<const A: usize, const START: usize, const LEN: usize>(a: &[u8; A]) -> &[u8; LEN] {
|
||||
assert!((START + LEN) <= A);
|
||||
unsafe { &*a.as_ptr().add(START).cast::<[T; LEN]>() }
|
||||
unsafe { &*a.as_ptr().add(START).cast::<[u8; LEN]>() }
|
||||
}
|
||||
|
||||
/// Obtain a reference to a sub-array within an existing array.
|
||||
/// Obtain a reference to a sub-array within an existing byte array.
|
||||
#[inline(always)]
|
||||
pub(crate) fn array_range_mut<T, const A: usize, const START: usize, const LEN: usize>(a: &mut [T; A]) -> &mut [T; LEN] {
|
||||
pub(crate) fn byte_array_range_mut<const A: usize, const START: usize, const LEN: usize>(a: &mut [u8; A]) -> &mut [u8; LEN] {
|
||||
assert!((START + LEN) <= A);
|
||||
unsafe { &mut *a.as_mut_ptr().add(START).cast::<[T; LEN]>() }
|
||||
}
|
||||
|
||||
/// Cast a u64 to a byte array.
|
||||
#[inline(always)]
|
||||
pub(crate) fn u64_as_bytes(i: &u64) -> &[u8; 8] {
|
||||
unsafe { &*(i as *const u64).cast() }
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref HIGHWAYHASHER_KEY: [u64; 4] = [zerotier_core_crypto::random::next_u64_secure(), zerotier_core_crypto::random::next_u64_secure(), zerotier_core_crypto::random::next_u64_secure(), zerotier_core_crypto::random::next_u64_secure()];
|
||||
}
|
||||
|
||||
/// Get an instance of HighwayHasher initialized with a secret per-process random salt.
|
||||
/// The random salt is generated at process start and so will differ for each invocation of whatever process this is inside.
|
||||
#[inline(always)]
|
||||
pub(crate) fn highwayhasher() -> highway::HighwayHasher {
|
||||
highway::HighwayHasher::new(highway::Key(HIGHWAYHASHER_KEY.clone()))
|
||||
unsafe { &mut *a.as_mut_ptr().add(START).cast::<[u8; LEN]>() }
|
||||
}
|
||||
|
||||
/// Non-cryptographic 64-bit bit mixer for things like local hashing.
|
||||
|
@ -56,7 +39,8 @@ pub(crate) fn hash64_noncrypt(mut x: u64) -> u64 {
|
|||
x ^ x.wrapping_shr(31)
|
||||
}
|
||||
|
||||
/// A hasher for maps that just returns u64 values as-is.
|
||||
/// A hasher for u64 maps that just returns u64 values as-is.
|
||||
///
|
||||
/// Used with things like ZeroTier addresses and network IDs that are already randomly distributed.
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct U64NoOpHasher(u64);
|
||||
|
|
|
@ -56,14 +56,7 @@ impl Address {
|
|||
|
||||
#[inline(always)]
|
||||
pub(crate) fn marshal<const BL: usize>(&self, buf: &mut Buffer<BL>) -> std::io::Result<()> {
|
||||
let b = buf.append_bytes_fixed_get_mut::<ADDRESS_SIZE>()?;
|
||||
let i = self.0.get();
|
||||
(*b)[0] = (i >> 32) as u8;
|
||||
(*b)[1] = (i >> 24) as u8;
|
||||
(*b)[2] = (i >> 16) as u8;
|
||||
(*b)[3] = (i >> 8) as u8;
|
||||
(*b)[4] = i as u8;
|
||||
Ok(())
|
||||
buf.append_bytes(&self.0.get().to_be_bytes()[8 - ADDRESS_SIZE..])
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -20,7 +20,7 @@ use lazy_static::lazy_static;
|
|||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use zerotier_core_crypto::c25519::*;
|
||||
use zerotier_core_crypto::hash::{hmac_sha512, SHA384, SHA384_HASH_SIZE, SHA512, SHA512_HASH_SIZE};
|
||||
use zerotier_core_crypto::hash::*;
|
||||
use zerotier_core_crypto::hex;
|
||||
use zerotier_core_crypto::p384::*;
|
||||
use zerotier_core_crypto::salsa::Salsa;
|
||||
|
@ -811,6 +811,7 @@ mod tests {
|
|||
use crate::vl1::identity::{Identity, IDENTITY_ALGORITHM_ALL};
|
||||
use std::str::FromStr;
|
||||
use std::time::{Duration, SystemTime};
|
||||
#[allow(unused_imports)]
|
||||
use zerotier_core_crypto::hex;
|
||||
|
||||
const GOOD_V0_IDENTITIES: [&'static str; 10] = [
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem::{size_of, transmute_copy, zeroed, MaybeUninit};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
use std::ptr::{copy_nonoverlapping, null, slice_from_raw_parts, write_bytes};
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[cfg(windows)]
|
||||
use winapi::um::winsock2;
|
||||
|
||||
|
@ -62,6 +64,10 @@ pub enum IpScope {
|
|||
/// The ZeroTier core uses this in preference to std::net stuff so this can be
|
||||
/// directly used via the C API or with C socket I/O functions.
|
||||
///
|
||||
/// This supports into() and from() the std::net types and also has a custom
|
||||
/// serde serializer that serializes it in ZT protocol binary form for binary
|
||||
/// formats and canonical ZT string form for string formats.
|
||||
///
|
||||
/// Unfortunately this is full of unsafe because it's a union, but the code is
|
||||
/// not complex and doesn't allocate anything.
|
||||
#[repr(C)]
|
||||
|
@ -72,16 +78,168 @@ pub union InetAddress {
|
|||
ss: sockaddr_storage, // some external code may expect the struct to be this full length
|
||||
}
|
||||
|
||||
impl Into<IpAddr> for InetAddress {
|
||||
fn into(self) -> IpAddr {
|
||||
if self.is_ipv4() {
|
||||
IpAddr::V4(Ipv4Addr::from(self.to_bytes::<4>()))
|
||||
} else {
|
||||
IpAddr::V6(Ipv6Addr::from(self.to_bytes::<16>()))
|
||||
impl TryInto<IpAddr> for InetAddress {
|
||||
type Error = crate::error::InvalidParameterError;
|
||||
|
||||
fn try_into(self) -> Result<IpAddr, Self::Error> {
|
||||
match unsafe { self.sa.sa_family } {
|
||||
AF_INET => Ok(IpAddr::V4(Ipv4Addr::from(unsafe { self.sin.sin_addr.s_addr.to_ne_bytes() }))),
|
||||
AF_INET6 => Ok(IpAddr::V6(Ipv6Addr::from(unsafe { self.sin6.sin6_addr.s6_addr }))),
|
||||
_ => Err(crate::error::InvalidParameterError("not an IP address")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<Ipv4Addr> for InetAddress {
|
||||
type Error = crate::error::InvalidParameterError;
|
||||
|
||||
fn try_into(self) -> Result<Ipv4Addr, Self::Error> {
|
||||
match unsafe { self.sa.sa_family } {
|
||||
AF_INET => Ok(Ipv4Addr::from(unsafe { self.sin.sin_addr.s_addr.to_ne_bytes() })),
|
||||
_ => Err(crate::error::InvalidParameterError("not an IPv4 address")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<Ipv6Addr> for InetAddress {
|
||||
type Error = crate::error::InvalidParameterError;
|
||||
|
||||
fn try_into(self) -> Result<Ipv6Addr, Self::Error> {
|
||||
match unsafe { self.sa.sa_family } {
|
||||
AF_INET6 => Ok(Ipv6Addr::from(unsafe { self.sin6.sin6_addr.s6_addr })),
|
||||
_ => Err(crate::error::InvalidParameterError("not an IPv6 address")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<SocketAddr> for InetAddress {
|
||||
type Error = crate::error::InvalidParameterError;
|
||||
|
||||
fn try_into(self) -> Result<SocketAddr, Self::Error> {
|
||||
unsafe {
|
||||
match self.sa.sa_family {
|
||||
AF_INET => Ok(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(self.sin.sin_addr.s_addr.to_ne_bytes()), u16::from_be(self.sin.sin_port as u16)))),
|
||||
AF_INET6 => Ok(SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(self.sin6.sin6_addr.s6_addr), u16::from_be(self.sin6.sin6_port as u16), 0, 0))),
|
||||
_ => Err(crate::error::InvalidParameterError("not an IP address")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<SocketAddrV4> for InetAddress {
|
||||
type Error = crate::error::InvalidParameterError;
|
||||
|
||||
fn try_into(self) -> Result<SocketAddrV4, Self::Error> {
|
||||
unsafe {
|
||||
match self.sa.sa_family {
|
||||
AF_INET => Ok(SocketAddrV4::new(Ipv4Addr::from(self.sin.sin_addr.s_addr.to_ne_bytes()), u16::from_be(self.sin.sin_port as u16))),
|
||||
_ => Err(crate::error::InvalidParameterError("not an IPv4 address")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<SocketAddrV6> for InetAddress {
|
||||
type Error = crate::error::InvalidParameterError;
|
||||
|
||||
fn try_into(self) -> Result<SocketAddrV6, Self::Error> {
|
||||
unsafe {
|
||||
match self.sa.sa_family {
|
||||
AF_INET6 => Ok(SocketAddrV6::new(Ipv6Addr::from(self.sin6.sin6_addr.s6_addr), u16::from_be(self.sin6.sin6_port as u16), 0, 0)),
|
||||
_ => Err(crate::error::InvalidParameterError("not an IPv6 address")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&IpAddr> for InetAddress {
|
||||
fn from(ip: &IpAddr) -> Self {
|
||||
match ip {
|
||||
IpAddr::V4(ip4) => Self::from(ip4),
|
||||
IpAddr::V6(ip6) => Self::from(ip6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpAddr> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(ip: IpAddr) -> Self {
|
||||
Self::from(&ip)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Ipv4Addr> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(ip4: &Ipv4Addr) -> Self {
|
||||
Self::from_ip_port(&ip4.octets(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ipv4Addr> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(ip4: Ipv4Addr) -> Self {
|
||||
Self::from_ip_port(&ip4.octets(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Ipv6Addr> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(ip6: &Ipv6Addr) -> Self {
|
||||
Self::from_ip_port(&ip6.octets(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ipv6Addr> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(ip6: Ipv6Addr) -> Self {
|
||||
Self::from_ip_port(&ip6.octets(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&SocketAddr> for InetAddress {
|
||||
fn from(sa: &SocketAddr) -> Self {
|
||||
match sa {
|
||||
SocketAddr::V4(sa4) => Self::from(sa4),
|
||||
SocketAddr::V6(sa6) => Self::from(sa6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SocketAddr> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(sa: SocketAddr) -> Self {
|
||||
Self::from(&sa)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&SocketAddrV4> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(sa: &SocketAddrV4) -> Self {
|
||||
Self::from_ip_port(&sa.ip().octets(), sa.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SocketAddrV4> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(sa: SocketAddrV4) -> Self {
|
||||
Self::from_ip_port(&sa.ip().octets(), sa.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&SocketAddrV6> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(sa: &SocketAddrV6) -> Self {
|
||||
Self::from_ip_port(&sa.ip().octets(), sa.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SocketAddrV6> for InetAddress {
|
||||
#[inline(always)]
|
||||
fn from(sa: SocketAddrV6) -> Self {
|
||||
Self::from_ip_port(&sa.ip().octets(), sa.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for InetAddress {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
|
@ -91,8 +249,8 @@ impl Clone for InetAddress {
|
|||
|
||||
impl Default for InetAddress {
|
||||
#[inline(always)]
|
||||
fn default() -> InetAddress {
|
||||
unsafe { zeroed() }
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +260,68 @@ impl std::fmt::Debug for InetAddress {
|
|||
}
|
||||
}
|
||||
|
||||
// Just has to be large enough to store any binary marshalled InetAddress
|
||||
const TEMP_SERIALIZE_BUFFER_SIZE: usize = 24;
|
||||
|
||||
impl Serialize for InetAddress {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
serializer.serialize_str(self.to_string().as_str())
|
||||
} else {
|
||||
let mut tmp: Buffer<TEMP_SERIALIZE_BUFFER_SIZE> = Buffer::new();
|
||||
assert!(self.marshal(&mut tmp).is_ok());
|
||||
serializer.serialize_bytes(tmp.as_bytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InetAddressVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for InetAddressVisitor {
|
||||
type Value = InetAddress;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("an InetAddress")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
if v.len() <= TEMP_SERIALIZE_BUFFER_SIZE {
|
||||
let mut tmp: Buffer<TEMP_SERIALIZE_BUFFER_SIZE> = Buffer::new();
|
||||
let _ = tmp.append_bytes(v);
|
||||
let mut cursor = 0;
|
||||
InetAddress::unmarshal(&tmp, &mut cursor).map_err(|e| E::custom(e.to_string()))
|
||||
} else {
|
||||
Err(E::custom("object too large"))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
InetAddress::from_str(v).map_err(|e| E::custom(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for InetAddress {
|
||||
fn deserialize<D>(deserializer: D) -> Result<InetAddress, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
deserializer.deserialize_str(InetAddressVisitor)
|
||||
} else {
|
||||
deserializer.deserialize_bytes(InetAddressVisitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InetAddress {
|
||||
/// Get a new zero/nil InetAddress.
|
||||
#[inline(always)]
|
||||
|
@ -114,7 +334,7 @@ impl InetAddress {
|
|||
#[inline(always)]
|
||||
pub fn from_ip_port(ip: &[u8], port: u16) -> InetAddress {
|
||||
unsafe {
|
||||
let mut c = MaybeUninit::<InetAddress>::uninit().assume_init();
|
||||
let mut c = MaybeUninit::<InetAddress>::uninit().assume_init(); // gets zeroed in set()
|
||||
c.set(ip, port);
|
||||
c
|
||||
}
|
||||
|
@ -178,6 +398,13 @@ impl InetAddress {
|
|||
unsafe { self.sa.sa_family as u8 == AF_INET6 }
|
||||
}
|
||||
|
||||
/// Check if this is either an IPv4 or an IPv6 address.
|
||||
#[inline(always)]
|
||||
pub fn is_ip(&self) -> bool {
|
||||
let family = unsafe { self.sa.sa_family };
|
||||
family == AF_INET || family == AF_INET6
|
||||
}
|
||||
|
||||
/// Get the address family of this InetAddress: AF_INET, AF_INET6, or 0 if uninitialized.
|
||||
#[inline(always)]
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
@ -242,21 +469,6 @@ impl InetAddress {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes<const LEN: usize>(&self) -> [u8; LEN] {
|
||||
if LEN != 4 && LEN != 16 {
|
||||
panic!("LEN was not 4 or 16, cannot convert");
|
||||
}
|
||||
|
||||
let mut res = [0u8; LEN];
|
||||
|
||||
if LEN == 4 && !self.is_ipv4() {
|
||||
panic!("Non-IPv4 address expected for 4 byte array");
|
||||
}
|
||||
|
||||
res.copy_from_slice(&self.ip_bytes()[0..LEN]);
|
||||
res
|
||||
}
|
||||
|
||||
/// Get raw IP bytes packed into a u128.
|
||||
/// Bytes are packed in native endian so the resulting u128 may not be the same between systems.
|
||||
/// This value is intended for local lookup use only.
|
||||
|
@ -499,39 +711,44 @@ impl ToString for InetAddress {
|
|||
impl FromStr for InetAddress {
|
||||
type Err = InvalidFormatError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
fn from_str(ip_string: &str) -> Result<Self, Self::Err> {
|
||||
let mut addr = InetAddress::new();
|
||||
let (ip_str, port) = s.find('/').map_or_else(
|
||||
|| (s, 0),
|
||||
|pos| {
|
||||
let ss = s.split_at(pos);
|
||||
let mut port_str = ss.1;
|
||||
if port_str.starts_with('/') {
|
||||
port_str = &port_str[1..];
|
||||
}
|
||||
(ss.0, u16::from_str_radix(port_str, 10).unwrap_or(0).to_be())
|
||||
},
|
||||
);
|
||||
IpAddr::from_str(ip_str).map_or_else(
|
||||
|_| Err(InvalidFormatError),
|
||||
|ip| {
|
||||
unsafe {
|
||||
match ip {
|
||||
IpAddr::V4(v4) => {
|
||||
addr.sin.sin_family = AF_INET.into();
|
||||
addr.sin.sin_port = port.into();
|
||||
copy_nonoverlapping(v4.octets().as_ptr(), (&mut (addr.sin.sin_addr.s_addr) as *mut u32).cast(), 4);
|
||||
}
|
||||
IpAddr::V6(v6) => {
|
||||
addr.sin6.sin6_family = AF_INET6.into();
|
||||
addr.sin6.sin6_port = port.into();
|
||||
copy_nonoverlapping(v6.octets().as_ptr(), (&mut (addr.sin6.sin6_addr) as *mut in6_addr).cast(), 16);
|
||||
let s = ip_string.trim();
|
||||
if !s.is_empty() {
|
||||
let (ip_str, port) = s.find('/').map_or_else(
|
||||
|| (s, 0),
|
||||
|pos| {
|
||||
let ss = s.split_at(pos);
|
||||
let mut port_str = ss.1;
|
||||
if port_str.starts_with('/') {
|
||||
port_str = &port_str[1..];
|
||||
}
|
||||
(ss.0, u16::from_str_radix(port_str, 10).unwrap_or(0).to_be())
|
||||
},
|
||||
);
|
||||
IpAddr::from_str(ip_str).map_or_else(
|
||||
|_| Err(InvalidFormatError),
|
||||
|ip| {
|
||||
unsafe {
|
||||
match ip {
|
||||
IpAddr::V4(v4) => {
|
||||
addr.sin.sin_family = AF_INET.into();
|
||||
addr.sin.sin_port = port.into();
|
||||
copy_nonoverlapping(v4.octets().as_ptr(), (&mut (addr.sin.sin_addr.s_addr) as *mut u32).cast(), 4);
|
||||
}
|
||||
IpAddr::V6(v6) => {
|
||||
addr.sin6.sin6_family = AF_INET6.into();
|
||||
addr.sin6.sin6_port = port.into();
|
||||
copy_nonoverlapping(v6.octets().as_ptr(), (&mut (addr.sin6.sin6_addr) as *mut in6_addr).cast(), 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(addr)
|
||||
},
|
||||
)
|
||||
Ok(addr)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Ok(addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,6 +860,8 @@ impl Hash for InetAddress {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for InetAddress {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::mem::size_of;
|
||||
|
|
|
@ -57,15 +57,7 @@ impl MAC {
|
|||
|
||||
#[inline(always)]
|
||||
pub(crate) fn marshal<const BL: usize>(&self, buf: &mut Buffer<BL>) -> std::io::Result<()> {
|
||||
let b = buf.append_bytes_fixed_get_mut::<6>()?;
|
||||
let i = self.0.get();
|
||||
(*b)[0] = (i >> 40) as u8;
|
||||
(*b)[1] = (i >> 32) as u8;
|
||||
(*b)[2] = (i >> 24) as u8;
|
||||
(*b)[3] = (i >> 16) as u8;
|
||||
(*b)[4] = (i >> 8) as u8;
|
||||
(*b)[5] = i as u8;
|
||||
Ok(())
|
||||
buf.append_bytes(&self.0.get().to_be_bytes()[2..])
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -21,7 +21,6 @@ pub(crate) mod peer;
|
|||
#[allow(unused)]
|
||||
pub(crate) mod protocol;
|
||||
pub(crate) mod symmetricsecret;
|
||||
pub(crate) mod system_interface;
|
||||
pub(crate) mod whoisqueue;
|
||||
|
||||
pub use address::Address;
|
||||
|
@ -33,6 +32,5 @@ pub use mac::MAC;
|
|||
pub use node::{Node, SystemInterface};
|
||||
pub use path::Path;
|
||||
pub use peer::Peer;
|
||||
pub use system_interface::VL1SystemInterface;
|
||||
|
||||
pub use protocol::{PACKET_FRAGMENT_COUNT_MAX, PACKET_SIZE_MAX};
|
||||
|
|
|
@ -82,8 +82,8 @@ pub trait SystemInterface: Sync + Send {
|
|||
/// Interface between VL1 and higher/inner protocol layers.
|
||||
///
|
||||
/// This is implemented by Switch in VL2. It's usually not used outside of VL2 in the core but
|
||||
/// it could also be implemented for testing or "off label" use of VL1.
|
||||
pub trait VL1VirtualInterface: Sync + Send {
|
||||
/// it could also be implemented for testing or "off label" use of VL1 to carry different protocols.
|
||||
pub trait InnerProtocolInterface: Sync + Send {
|
||||
/// Handle a packet, returning true if it was handled by the next layer.
|
||||
///
|
||||
/// Do not attempt to handle OK or ERROR. Instead implement handle_ok() and handle_error().
|
||||
|
@ -232,7 +232,7 @@ impl Node {
|
|||
}
|
||||
|
||||
/// Called when a packet is received on the physical wire.
|
||||
pub fn wire_receive<SI: SystemInterface, PH: VL1VirtualInterface>(&self, si: &SI, ph: &PH, source_endpoint: &Endpoint, source_local_socket: Option<NonZeroI64>, source_local_interface: Option<NonZeroI64>, mut data: PacketBuffer) {
|
||||
pub fn wire_receive<SI: SystemInterface, PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, source_endpoint: &Endpoint, source_local_socket: Option<NonZeroI64>, source_local_interface: Option<NonZeroI64>, mut data: PacketBuffer) {
|
||||
if let Ok(fragment_header) = data.struct_mut_at::<FragmentHeader>(0) {
|
||||
if let Some(dest) = Address::from_bytes(&fragment_header.dest) {
|
||||
let time_ticks = si.time_ticks();
|
||||
|
|
|
@ -8,16 +8,14 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hasher;
|
||||
use std::io::Write;
|
||||
use std::num::NonZeroI64;
|
||||
use std::sync::atomic::{AtomicI64, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use highway::HighwayHash;
|
||||
use parking_lot::Mutex;
|
||||
use zerotier_core_crypto::hash::SHA384_HASH_SIZE;
|
||||
|
||||
use crate::util::{array_range, highwayhasher, U64NoOpHasher};
|
||||
use crate::util::*;
|
||||
use crate::vl1::fragmentedpacket::FragmentedPacket;
|
||||
use crate::vl1::node::SystemInterface;
|
||||
use crate::vl1::protocol::*;
|
||||
|
@ -27,10 +25,13 @@ use crate::PacketBuffer;
|
|||
/// Keepalive interval for paths in milliseconds.
|
||||
pub(crate) const PATH_KEEPALIVE_INTERVAL: i64 = 20000;
|
||||
|
||||
// A bunch of random values used to randomize the local_lookup_key() function's mappings of addresses to 128-bit internal keys.
|
||||
lazy_static! {
|
||||
static ref RANDOM_64BIT_SALT_0: u64 = zerotier_core_crypto::random::next_u64_secure();
|
||||
static ref RANDOM_64BIT_SALT_1: u64 = zerotier_core_crypto::random::next_u64_secure();
|
||||
static ref RANDOM_64BIT_SALT_2: u64 = zerotier_core_crypto::random::next_u64_secure();
|
||||
static ref RANDOM_128BIT_SALT_0: u128 = (zerotier_core_crypto::random::next_u64_secure().wrapping_shl(64) as u128) ^ (zerotier_core_crypto::random::next_u64_secure() as u128);
|
||||
static ref RANDOM_128BIT_SALT_1: u128 = (zerotier_core_crypto::random::next_u64_secure().wrapping_shl(64) as u128) ^ (zerotier_core_crypto::random::next_u64_secure() as u128);
|
||||
}
|
||||
|
||||
/// A remote endpoint paired with a local socket and a local interface.
|
||||
|
@ -55,7 +56,7 @@ impl Path {
|
|||
let lsi = (local_socket as u128).wrapping_shl(64) | (local_interface as u128);
|
||||
match endpoint {
|
||||
Endpoint::Nil => 0,
|
||||
Endpoint::ZeroTier(_, h) => u128::from_ne_bytes(*array_range::<u8, SHA384_HASH_SIZE, 0, 16>(h)),
|
||||
Endpoint::ZeroTier(_, h) => u128::from_ne_bytes(*byte_array_range::<SHA384_HASH_SIZE, 0, 16>(h)),
|
||||
Endpoint::Ethernet(m) => (m.to_u64() | 0x0100000000000000) as u128 ^ lsi,
|
||||
Endpoint::WifiDirect(m) => (m.to_u64() | 0x0200000000000000) as u128 ^ lsi,
|
||||
Endpoint::Bluetooth(m) => (m.to_u64() | 0x0400000000000000) as u128 ^ lsi,
|
||||
|
@ -63,24 +64,23 @@ impl Path {
|
|||
Endpoint::IpUdp(ip) => ip.ip_as_native_u128().wrapping_add(lsi), // UDP maintains one path per IP but merely learns the most recent port
|
||||
Endpoint::IpTcp(ip) => ip.ip_as_native_u128().wrapping_sub(crate::util::hash64_noncrypt((ip.port() as u64).wrapping_add(*RANDOM_64BIT_SALT_2)) as u128).wrapping_sub(lsi),
|
||||
Endpoint::Http(s) => {
|
||||
let mut hh = highwayhasher();
|
||||
let _ = hh.write_all(s.as_bytes());
|
||||
let _ = hh.write_u64(local_socket);
|
||||
let _ = hh.write_u64(local_interface);
|
||||
u128::from_ne_bytes(unsafe { *hh.finalize128().as_ptr().cast() })
|
||||
let mut hh = std::collections::hash_map::DefaultHasher::new();
|
||||
hh.write_u64(local_socket);
|
||||
hh.write_u64(local_interface);
|
||||
hh.write(s.as_bytes());
|
||||
RANDOM_128BIT_SALT_0.wrapping_add(hh.finish() as u128)
|
||||
}
|
||||
Endpoint::WebRTC(b) => {
|
||||
let mut hh = highwayhasher();
|
||||
let _ = hh.write_u64(local_socket);
|
||||
let _ = hh.write_u64(local_interface);
|
||||
let _ = hh.write_all(b.as_slice());
|
||||
u128::from_ne_bytes(unsafe { *hh.finalize128().as_ptr().cast() })
|
||||
let mut hh = std::collections::hash_map::DefaultHasher::new();
|
||||
hh.write_u64(local_socket);
|
||||
hh.write_u64(local_interface);
|
||||
hh.write(b.as_slice());
|
||||
RANDOM_128BIT_SALT_1.wrapping_add(hh.finish() as u128)
|
||||
}
|
||||
Endpoint::ZeroTierEncap(_, h) => u128::from_ne_bytes(*array_range::<u8, SHA384_HASH_SIZE, 16, 16>(h)),
|
||||
Endpoint::ZeroTierEncap(_, h) => u128::from_ne_bytes(*byte_array_range::<SHA384_HASH_SIZE, 16, 16>(h)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn new(endpoint: Endpoint, local_socket: Option<NonZeroI64>, local_interface: Option<NonZeroI64>) -> Self {
|
||||
Self {
|
||||
endpoint: Mutex::new(Arc::new(endpoint)),
|
||||
|
@ -119,7 +119,6 @@ impl Path {
|
|||
|
||||
/// Receive a fragment and return a FragmentedPacket if the entire packet was assembled.
|
||||
/// This returns None if more fragments are needed to assemble the packet.
|
||||
#[inline(always)]
|
||||
pub(crate) fn receive_fragment(&self, packet_id: u64, fragment_no: u8, fragment_expecting_count: u8, packet: PacketBuffer, time_ticks: i64) -> Option<FragmentedPacket> {
|
||||
let mut fp = self.fragmented_packets.lock();
|
||||
|
||||
|
@ -150,7 +149,6 @@ impl Path {
|
|||
self.last_receive_time_ticks.store(time_ticks, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn log_receive_authenticated_packet(&self, _bytes: usize, source_endpoint: &Endpoint) {
|
||||
let mut replace = false;
|
||||
match source_endpoint {
|
||||
|
@ -180,7 +178,6 @@ impl Path {
|
|||
|
||||
pub(crate) const CALL_EVERY_INTERVAL_MS: i64 = PATH_KEEPALIVE_INTERVAL;
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn call_every_interval<SI: SystemInterface>(&self, _si: &SI, time_ticks: i64) {
|
||||
self.fragmented_packets.lock().retain(|_, frag| (time_ticks - frag.ts_ticks) < PACKET_FRAGMENT_EXPIRATION);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ use zerotier_core_crypto::aes_gmac_siv::AesCtr;
|
|||
use zerotier_core_crypto::hash::*;
|
||||
use zerotier_core_crypto::kbkdf::zt_kbkdf_hmac_sha384;
|
||||
use zerotier_core_crypto::poly1305::Poly1305;
|
||||
use zerotier_core_crypto::random::{fill_bytes_secure, get_bytes_secure, next_u64_secure};
|
||||
use zerotier_core_crypto::random::{get_bytes_secure, next_u64_secure};
|
||||
use zerotier_core_crypto::salsa::Salsa;
|
||||
use zerotier_core_crypto::secret::Secret;
|
||||
|
||||
use crate::util::buffer::Buffer;
|
||||
use crate::util::{array_range, u64_as_bytes};
|
||||
use crate::vl1::hybridkey::{HybridKeyPair, HybridPublicKey};
|
||||
use crate::util::byte_array_range;
|
||||
use crate::vl1::hybridkey::HybridKeyPair;
|
||||
use crate::vl1::identity::{IDENTITY_ALGORITHM_ALL, IDENTITY_ALGORITHM_X25519};
|
||||
use crate::vl1::node::*;
|
||||
use crate::vl1::protocol::*;
|
||||
|
@ -172,7 +172,7 @@ fn try_aead_decrypt(secret: &SymmetricSecret, packet_frag0_payload_bytes: &[u8],
|
|||
// AES-GMAC-SIV encrypts the packet ID too as part of its computation of a single
|
||||
// opaque 128-bit tag, so to get the original packet ID we have to grab it from the
|
||||
// decrypted tag.
|
||||
Some(u64::from_ne_bytes(*array_range::<u8, 16, 0, 8>(tag)))
|
||||
Some(u64::from_ne_bytes(*byte_array_range::<16, 0, 8>(tag)))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ impl Peer {
|
|||
///
|
||||
/// If the packet comes in multiple fragments, the fragments slice should contain all
|
||||
/// those fragments after the main packet header and first chunk.
|
||||
pub(crate) fn receive<SI: SystemInterface, VI: VL1VirtualInterface>(&self, node: &Node, si: &SI, vi: &VI, time_ticks: i64, source_endpoint: &Endpoint, source_path: &Arc<Path>, header: &PacketHeader, frag0: &Buffer<{ PACKET_SIZE_MAX }>, fragments: &[Option<PacketBuffer>]) {
|
||||
pub(crate) fn receive<SI: SystemInterface, VI: InnerProtocolInterface>(&self, node: &Node, si: &SI, vi: &VI, time_ticks: i64, source_endpoint: &Endpoint, source_path: &Arc<Path>, header: &PacketHeader, frag0: &Buffer<{ PACKET_SIZE_MAX }>, fragments: &[Option<PacketBuffer>]) {
|
||||
let _ = frag0.as_bytes_starting_at(PACKET_VERB_INDEX).map(|packet_frag0_payload_bytes| {
|
||||
let mut payload: Buffer<PACKET_SIZE_MAX> = unsafe { Buffer::new_without_memzero() };
|
||||
|
||||
|
@ -502,7 +502,7 @@ impl Peer {
|
|||
|
||||
// Add extended HMAC-SHA512 authentication.
|
||||
let mut hmac = HMACSHA512::new(self.identity_symmetric_key.packet_hmac_key.as_bytes());
|
||||
hmac.update(u64_as_bytes(&message_id));
|
||||
hmac.update(&message_id.to_ne_bytes());
|
||||
hmac.update(&packet.as_bytes()[PACKET_HEADER_SIZE..]);
|
||||
assert!(packet.append_bytes_fixed(&hmac.finish()).is_ok());
|
||||
|
||||
|
@ -537,7 +537,7 @@ impl Peer {
|
|||
fn receive_hello<SI: SystemInterface>(&self, si: &SI, node: &Node, time_ticks: i64, source_path: &Arc<Path>, payload: &Buffer<{ PACKET_SIZE_MAX }>) {}
|
||||
|
||||
#[inline(always)]
|
||||
fn receive_error<SI: SystemInterface, PH: VL1VirtualInterface>(&self, si: &SI, ph: &PH, node: &Node, time_ticks: i64, source_path: &Arc<Path>, forward_secrecy: bool, extended_authentication: bool, payload: &Buffer<{ PACKET_SIZE_MAX }>) {
|
||||
fn receive_error<SI: SystemInterface, PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node, time_ticks: i64, source_path: &Arc<Path>, forward_secrecy: bool, extended_authentication: bool, payload: &Buffer<{ PACKET_SIZE_MAX }>) {
|
||||
let mut cursor: usize = 0;
|
||||
let _ = payload.read_struct::<message_component_structs::ErrorHeader>(&mut cursor).map(|error_header| {
|
||||
let in_re_message_id = u64::from_ne_bytes(error_header.in_re_message_id);
|
||||
|
@ -553,7 +553,7 @@ impl Peer {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn receive_ok<SI: SystemInterface, PH: VL1VirtualInterface>(&self, si: &SI, ph: &PH, node: &Node, time_ticks: i64, source_path: &Arc<Path>, forward_secrecy: bool, extended_authentication: bool, payload: &Buffer<{ PACKET_SIZE_MAX }>) {
|
||||
fn receive_ok<SI: SystemInterface, PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node, time_ticks: i64, source_path: &Arc<Path>, forward_secrecy: bool, extended_authentication: bool, payload: &Buffer<{ PACKET_SIZE_MAX }>) {
|
||||
let mut cursor: usize = 0;
|
||||
let _ = payload.read_struct::<message_component_structs::OkHeader>(&mut cursor).map(|ok_header| {
|
||||
let in_re_message_id = u64::from_ne_bytes(ok_header.in_re_message_id);
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
use super::{Endpoint, Identity};
|
||||
use std::num::NonZeroI64;
|
||||
|
||||
pub trait VL1SystemInterface {
|
||||
fn event_node_is_up(&self);
|
||||
fn event_node_is_down(&self);
|
||||
fn event_identity_collision(&self);
|
||||
fn event_online_status_change(&self, online: bool);
|
||||
fn event_user_message(&self, source: &Identity, message_type: u64, message: &[u8]);
|
||||
fn load_node_identity(&self) -> Option<Vec<u8>>;
|
||||
fn save_node_identity(&self, _: &Identity, public: &[u8], secret: &[u8]);
|
||||
fn wire_send(&self, endpoint: &Endpoint, local_socket: Option<NonZeroI64>, local_interface: Option<NonZeroI64>, data: &[&[u8]], packet_ttl: u8) -> bool;
|
||||
fn check_path(&self, id: &Identity, endpoint: &Endpoint, local_socket: Option<NonZeroI64>, local_interface: Option<NonZeroI64>) -> bool;
|
||||
fn get_path_hints(&self, id: &Identity) -> Option<&[(&Endpoint, Option<NonZeroI64>, Option<NonZeroI64>)]>;
|
||||
fn time_ticks(&self) -> i64;
|
||||
fn time_clock(&self) -> i64;
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::util::buffer::Buffer;
|
||||
use crate::vl1::node::VL1VirtualInterface;
|
||||
use crate::vl1::node::InnerProtocolInterface;
|
||||
use crate::vl1::protocol::*;
|
||||
use crate::vl1::{Identity, Path, Peer};
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub trait SwitchInterface: Sync + Send {}
|
|||
|
||||
pub struct Switch {}
|
||||
|
||||
impl VL1VirtualInterface for Switch {
|
||||
impl InnerProtocolInterface for Switch {
|
||||
fn handle_packet(&self, peer: &Peer, source_path: &Arc<Path>, forward_secrecy: bool, extended_authentication: bool, verb: u8, payload: &Buffer<{ PACKET_SIZE_MAX }>) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
1345
zerotier-system-service/Cargo.lock
generated
1345
zerotier-system-service/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -17,22 +17,12 @@ zerotier-network-hypervisor = { path = "../zerotier-network-hypervisor" }
|
|||
zerotier-core-crypto = { path = "../zerotier-core-crypto" }
|
||||
serde = { version = "^1", features = ["derive"], default-features = false }
|
||||
serde_json = { version = "^1", features = [], default-features = false }
|
||||
clap = { version = "^2", features = ["suggestions", "wrap_help"] }
|
||||
colored = "^2"
|
||||
num_cpus = "^1"
|
||||
parking_lot = "^0"
|
||||
smol = "^1"
|
||||
tide = { version = "^0", features = ["h1-server"], default-features = false }
|
||||
digest_auth = "^0"
|
||||
chrono = "^0"
|
||||
hex = "^0"
|
||||
rand = "^0"
|
||||
lazy_static = "^1"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
winapi = { version = "^0", features = ["handleapi", "ws2ipdef", "ws2tcpip"] }
|
||||
|
||||
[target."cfg(not(windows))".dependencies]
|
||||
libc = "^0"
|
||||
|
||||
[target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies]
|
||||
mach = "^0"
|
||||
|
|
|
@ -128,7 +128,7 @@ impl Store {
|
|||
if token2.is_empty() {
|
||||
if generate_if_missing {
|
||||
let mut rb = [0_u8; 32];
|
||||
unsafe { rb.fill_with(rand::random) };
|
||||
zerotier_core_crypto::random::fill_bytes_secure(&mut rb);
|
||||
token.reserve(rb.len());
|
||||
for b in rb.iter() {
|
||||
if *b > 127_u8 {
|
||||
|
|
|
@ -25,24 +25,7 @@ pub fn ms_since_epoch() -> i64 {
|
|||
std::time::SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as i64
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
pub fn ms_monotonic() -> i64 {
|
||||
unsafe {
|
||||
let mut tb: mach::mach_time::mach_timebase_info_data_t = std::mem::zeroed();
|
||||
if mach::mach_time::mach_timebase_info(&mut tb) == 0 {
|
||||
let mt = mach::mach_time::mach_continuous_approximate_time(); // ZT doesn't need it to be *that* exact, and this is faster
|
||||
(((mt as u128) * tb.numer as u128 * 1000000_u128) / (tb.denom as u128)) as i64
|
||||
// milliseconds since X
|
||||
} else {
|
||||
panic!("FATAL: mach_timebase_info() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||
pub fn ms_monotonic() -> i64 {
|
||||
std::time::SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as i64
|
||||
}
|
||||
pub fn ms_monotonic() -> i64 {}
|
||||
|
||||
pub fn parse_bool(v: &str) -> Result<bool, String> {
|
||||
if !v.is_empty() {
|
||||
|
|
|
@ -43,7 +43,7 @@ pub fn get_l2_multicast_subscriptions(dev: &str) -> HashSet<MAC> {
|
|||
if !(*i).ifma_name.is_null() && !(*i).ifma_addr.is_null() && (*(*i).ifma_addr).sa_family as i32 == libc::AF_LINK as i32 {
|
||||
let in_: &libc::sockaddr_dl = &*((*i).ifma_name.cast());
|
||||
let la: &libc::sockaddr_dl = &*((*i).ifma_addr.cast());
|
||||
if la.sdl_alen == 6 && in_.sdl_nlen <= dev.len().as_() && crate::libc::memcmp(dev.as_ptr().cast(), in_.sdl_data.as_ptr().cast(), in_.sdl_nlen.as_()) == 0 {
|
||||
if la.sdl_alen == 6 && in_.sdl_nlen <= dev.len().as_() && libc::memcmp(dev.as_ptr().cast(), in_.sdl_data.as_ptr().cast(), in_.sdl_nlen.as_()) == 0 {
|
||||
let mi = la.sdl_nlen as usize;
|
||||
MAC::from_u64((la.sdl_data[mi] as u64) << 40 | (la.sdl_data[mi + 1] as u64) << 32 | (la.sdl_data[mi + 2] as u64) << 24 | (la.sdl_data[mi + 3] as u64) << 16 | (la.sdl_data[mi + 4] as u64) << 8 | la.sdl_data[mi + 5] as u64).map(|mac| groups.insert(mac));
|
||||
}
|
||||
|
|
|
@ -31,18 +31,16 @@
|
|||
*/
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use std::error::Error;
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::ffi::CString;
|
||||
use std::mem::{transmute, zeroed};
|
||||
use std::os::raw::{c_char, c_int, c_short, c_uchar, c_uint, c_void};
|
||||
use std::process::Command;
|
||||
use std::ptr::{copy_nonoverlapping, null_mut};
|
||||
use std::sync::Mutex;
|
||||
use std::ptr::copy_nonoverlapping;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use num_traits::cast::AsPrimitive;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use zerotier_network_hypervisor::vl1::{InetAddress, MAC};
|
||||
|
||||
|
@ -178,6 +176,7 @@ struct in6_ifreq {
|
|||
*/
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct icmp6_ifstat {
|
||||
ifs6_in_msg: u64,
|
||||
|
@ -217,6 +216,7 @@ struct icmp6_ifstat {
|
|||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct in6_ifstat {
|
||||
ifs6_in_receive: u64,
|
||||
|
@ -247,6 +247,7 @@ struct in6_ifstat {
|
|||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct in6_addrlifetime {
|
||||
ia6t_expire: libc::time_t,
|
||||
|
@ -422,6 +423,7 @@ struct sockaddr_ndrv {
|
|||
*/
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct ifkpi {
|
||||
ifk_module_id: c_uint,
|
||||
|
@ -430,6 +432,7 @@ struct ifkpi {
|
|||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct ifdevmtu {
|
||||
ifdm_current: c_int,
|
||||
|
@ -480,7 +483,7 @@ impl MacFethTap {
|
|||
/// given will not remain valid after it returns. Also note that F will be called
|
||||
/// from another thread that is spawned here, so all its bound references must
|
||||
/// be "Send" and "Sync" e.g. Arc<>.
|
||||
pub fn new<F: Fn(&[u8]) + Send + Sync + 'static>(nwid: &NetworkId, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result<MacFethTap, String> {
|
||||
pub fn new<F: Fn(&[u8]) + Send + Sync + 'static>(nwid: u64, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result<MacFethTap, String> {
|
||||
// This tracks BPF devices we are using so we don't try to reopen them, and also
|
||||
// doubles as a global lock to ensure that only one feth tap is created at once per
|
||||
// ZeroTier process per system.
|
||||
|
@ -668,7 +671,7 @@ impl MacFethTap {
|
|||
}
|
||||
|
||||
// Create BPF listener thread, which calls the supplied function on each incoming packet.
|
||||
let t = std::thread::Builder::new().stack_size(zerotier_core::RECOMMENDED_THREAD_STACK_SIZE).spawn(move || {
|
||||
let t = std::thread::Builder::new().stack_size(524288).spawn(move || {
|
||||
let mut buf: [u8; BPF_BUFFER_SIZE] = [0_u8; BPF_BUFFER_SIZE];
|
||||
let hdr_struct_size = std::mem::size_of::<libc::bpf_hdr>() as isize;
|
||||
loop {
|
||||
|
@ -808,7 +811,7 @@ impl VNIC for MacFethTap {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn put(&self, source_mac: &zerotier_core::MAC, dest_mac: &zerotier_core::MAC, ethertype: u16, _vlan_id: u16, data: *const u8, len: usize) -> bool {
|
||||
fn put(&self, source_mac: &zerotier_network_hypervisor::vl1::MAC, dest_mac: &zerotier_network_hypervisor::vl1::MAC, ethertype: u16, _vlan_id: u16, data: *const u8, len: usize) -> bool {
|
||||
let dm = dest_mac.0;
|
||||
let sm = source_mac.0;
|
||||
let mut hdr: [u8; 14] = [(dm >> 40) as u8, (dm >> 32) as u8, (dm >> 24) as u8, (dm >> 16) as u8, (dm >> 8) as u8, dm as u8, (sm >> 40) as u8, (sm >> 32) as u8, (sm >> 24) as u8, (sm >> 16) as u8, (sm >> 8) as u8, sm as u8, (ethertype >> 8) as u8, ethertype as u8];
|
||||
|
|
Loading…
Add table
Reference in a new issue