Some cleanup, move some more V1 only fields into V1 credentials struct.

This commit is contained in:
Adam Ierymenko 2022-11-11 16:11:02 -05:00
parent 5772a135f5
commit 6bf978d4de
8 changed files with 41 additions and 44 deletions

View file

@ -43,10 +43,6 @@ impl Cache {
Ok(())
}
pub fn list_cached_networks(&self) -> Vec<NetworkId> {
self.by_nwid.read().unwrap().keys().cloned().collect()
}
/// Update a network if changed, returning whether or not any update was made and the old version if any.
/// A value of (true, None) indicates that there was no network by that ID in which case it is added.
pub fn on_network_updated(&self, network: Network) -> (bool, Option<Network>) {

View file

@ -183,8 +183,8 @@ impl Controller {
}
}
/// Send one or more revocation object(s) to a peer (V1 protocol only).
fn v1_proto_send_revocations(&self, peer: &Peer, mut revocations: Vec<Revocation>) {
/// Send one or more revocation object(s) to a peer.
fn send_revocations(&self, peer: &Peer, mut revocations: Vec<Revocation>) {
if let Some(host_system) = self.service.read().unwrap().upgrade() {
let time_ticks = ms_monotonic();
while !revocations.is_empty() {
@ -336,11 +336,9 @@ impl Controller {
nc.name = network.name.clone();
nc.private = network.private;
nc.timestamp = now;
nc.credential_ttl = credential_ttl;
nc.revision = Some(now as u64);
nc.mtu = network.mtu.unwrap_or(ZEROTIER_VIRTUAL_NETWORK_DEFAULT_MTU as u16);
nc.multicast_limit = network.multicast_limit.unwrap_or(DEFAULT_MULTICAST_LIMIT as u32);
nc.multicast_like_expire = Some(protocol::VL2_DEFAULT_MULTICAST_LIKE_EXPIRE as u32);
nc.mtu = network.mtu.unwrap_or(ZEROTIER_VIRTUAL_NETWORK_DEFAULT_MTU as u16);
nc.routes = network.ip_routes;
nc.static_ips = member.ip_assignments.clone();
nc.rules = network.rules;
@ -354,6 +352,8 @@ impl Controller {
vl2::v1::CertificateOfMembership::new(&self.local_identity, network_id, &source_identity, now, credential_ttl)
{
let mut v1cred = V1Credentials {
revision: now as u64,
max_delta: credential_ttl,
certificate_of_membership: com,
certificates_of_ownership: Vec::new(),
tags: HashMap::new(),
@ -383,7 +383,7 @@ impl Controller {
// For anyone who has been deauthorized but is still in the window, send revocations.
if let Ok(deauthed_members_still_in_window) = self
.database
.list_members_deauthorized_after(network.id, now - credential_ttl)
.list_members_deauthorized_after(network.id, now - (credential_ttl as i64))
.await
{
if !deauthed_members_still_in_window.is_empty() {
@ -419,7 +419,7 @@ impl Controller {
.unwrap()
.entry(source_identity.fingerprint)
.or_default()
.insert(network_id, ms_monotonic() + nc.credential_ttl);
.insert(network_id, ms_monotonic() + (credential_ttl as i64));
network_config = Some(nc);
}
@ -497,7 +497,7 @@ impl InnerProtocol for Controller {
//println!("{}", serde_yaml::to_string(&config).unwrap());
self2.send_network_config(source.as_ref(), &config, Some(message_id));
if let Some(revocations) = revocations {
self2.v1_proto_send_revocations(source.as_ref(), revocations);
self2.send_revocations(source.as_ref(), revocations);
}
(result, Some(config))
}

View file

@ -74,6 +74,7 @@ impl FileDatabase {
if let Some((record_type, network_id, node_id)) =
Self::record_type_from_path(controller_address, path0.as_path())
{
// Paths to objects that were deleted or changed. Changed includes adding new objects.
let mut deleted = None;
let mut changed = None;
@ -117,6 +118,7 @@ impl FileDatabase {
}
if deleted.is_some() {
println!("DELETED: {}", deleted.unwrap().as_os_str().to_string_lossy());
match record_type {
RecordType::Network => {
if let Some((network, mut members)) = db.cache.on_network_deleted(network_id) {
@ -138,6 +140,7 @@ impl FileDatabase {
}
if let Some(changed) = changed {
println!("CHANGED: {}", changed.as_os_str().to_string_lossy());
match record_type {
RecordType::Network => {
if let Ok(Some(new_network)) = Self::get_network_internal(changed).await {
@ -375,6 +378,7 @@ impl Database for FileDatabase {
let mut member = Self::get_member_internal(&self.member_path(network_id, node_id)).await?;
if let Some(member) = member.as_mut() {
if member.network_id != network_id {
// Also auto-update member network IDs, see get_network().
member.network_id = network_id;
self.save_member(member.clone()).await?;
}
@ -385,7 +389,6 @@ impl Database for FileDatabase {
async fn save_member(&self, obj: Member) -> Result<(), Box<dyn Error + Send + Sync>> {
let base_member_path = self.member_path(obj.network_id, obj.node_id);
let _ = fs::create_dir_all(base_member_path.parent().unwrap()).await;
//let _ = fs::write(base_member_path, to_json_pretty(&obj).as_bytes()).await?;
let _ = fs::write(base_member_path, serde_yaml::to_string(&obj)?.as_bytes()).await?;
Ok(())
}

View file

@ -13,7 +13,7 @@ use zerotier_network_hypervisor::vl2::NetworkId;
use crate::database::Database;
use crate::model::Member;
pub const CREDENTIAL_WINDOW_SIZE_DEFAULT: i64 = 1000 * 60 * 60;
pub const CREDENTIAL_WINDOW_SIZE_DEFAULT: u64 = 1000 * 60 * 60;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Ipv4AssignMode {
@ -105,7 +105,7 @@ pub struct Network {
/// Usually this does not need to be changed.
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "credentialTtl")]
pub credential_ttl: Option<i64>,
pub credential_ttl: Option<u64>,
/// Minimum supported ZeroTier protocol version for this network (default: undefined, up to members)
#[serde(skip_serializing_if = "Option::is_none")]

View file

@ -41,17 +41,6 @@ pub struct NetworkConfig {
/// Network configuration timestamp
pub timestamp: i64,
/// TTL for credentials on this network (or window size for V1 nodes)
pub credential_ttl: i64,
/// Network configuration revision number (V1)
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub revision: Option<u64>,
/// L2 Ethernet MTU for this network.
pub mtu: u16,
/// Suggested horizon limit for multicast (not a hard limit, but 0 disables multicast)
pub multicast_limit: u32,
@ -60,6 +49,9 @@ pub struct NetworkConfig {
#[serde(default)]
pub multicast_like_expire: Option<u32>,
/// L2 Ethernet MTU for this network.
pub mtu: u16,
/// ZeroTier-assigned L3 routes for this node.
#[serde(skip_serializing_if = "HashSet::is_empty")]
#[serde(default)]
@ -105,8 +97,6 @@ impl NetworkConfig {
motd: String::new(),
private: true,
timestamp: 0,
credential_ttl: 0,
revision: None,
mtu: 0,
multicast_limit: 0,
multicast_like_expire: None,
@ -143,8 +133,6 @@ impl NetworkConfig {
},
);
d.set_u64(proto_v1_field_name::network_config::TIMESTAMP, self.timestamp as u64);
d.set_u64(proto_v1_field_name::network_config::MAX_DELTA, self.credential_ttl as u64);
d.set_u64(proto_v1_field_name::network_config::REVISION, self.revision.unwrap_or(0));
d.set_u64(proto_v1_field_name::network_config::MTU, self.mtu as u64);
d.set_u64(proto_v1_field_name::network_config::MULTICAST_LIMIT, self.multicast_limit as u64);
@ -193,6 +181,9 @@ impl NetworkConfig {
}
if let Some(v1cred) = self.v1_credentials.as_ref() {
d.set_u64(proto_v1_field_name::network_config::REVISION, v1cred.revision);
d.set_u64(proto_v1_field_name::network_config::MAX_DELTA, v1cred.max_delta);
d.set_bytes(
proto_v1_field_name::network_config::CERTIFICATE_OF_MEMBERSHIP,
v1cred
@ -268,8 +259,6 @@ impl NetworkConfig {
nc.timestamp = d
.get_i64(proto_v1_field_name::network_config::TIMESTAMP)
.ok_or(InvalidParameterError("missing timestamp"))?;
nc.credential_ttl = d.get_i64(proto_v1_field_name::network_config::MAX_DELTA).unwrap_or(0);
nc.revision = Some(d.get_u64(proto_v1_field_name::network_config::REVISION).unwrap_or(0));
nc.mtu = d
.get_u64(proto_v1_field_name::network_config::MTU)
.unwrap_or(crate::protocol::ZEROTIER_VIRTUAL_NETWORK_DEFAULT_MTU as u64) as u16;
@ -327,6 +316,8 @@ impl NetworkConfig {
}
let mut v1cred = V1Credentials {
revision: d.get_u64(proto_v1_field_name::network_config::REVISION).unwrap_or(0),
max_delta: d.get_u64(proto_v1_field_name::network_config::MAX_DELTA).unwrap_or(0),
certificate_of_membership: CertificateOfMembership::from_bytes(
d.get_bytes(proto_v1_field_name::network_config::CERTIFICATE_OF_MEMBERSHIP)
.ok_or(InvalidParameterError("missing certificate of membership"))?,
@ -446,6 +437,8 @@ pub struct SSOAuthConfiguration {
/// networks that support older protocol versions.
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct V1Credentials {
pub revision: u64,
pub max_delta: u64,
pub certificate_of_membership: CertificateOfMembership,
pub certificates_of_ownership: Vec<CertificateOfOwnership>,
#[serde(skip_serializing_if = "HashMap::is_empty")]

View file

@ -25,7 +25,7 @@ use zerotier_utils::memory;
pub struct CertificateOfMembership {
pub network_id: NetworkId,
pub timestamp: i64,
pub max_delta: i64,
pub max_delta: u64,
pub issued_to: Address,
pub issued_to_fingerprint: Blob<32>,
pub signature: ArrayVec<u8, { Identity::MAX_SIGNATURE_SIZE }>,
@ -34,7 +34,7 @@ pub struct CertificateOfMembership {
impl CertificateOfMembership {
/// Create a new signed certificate of membership.
/// None is returned if an error occurs, such as the issuer missing its secrets.
pub fn new(issuer: &Identity, network_id: NetworkId, issued_to: &Identity, timestamp: i64, max_delta: i64) -> Option<Self> {
pub fn new(issuer: &Identity, network_id: NetworkId, issued_to: &Identity, timestamp: i64, max_delta: u64) -> Option<Self> {
let mut com = CertificateOfMembership {
network_id,
timestamp,
@ -128,7 +128,7 @@ impl CertificateOfMembership {
match qt {
0 => {
timestamp = i64::from_be_bytes(q);
max_delta = qd as i64;
max_delta = qd;
}
1 => {
network_id = u64::from_be_bytes(q);

View file

@ -28,7 +28,7 @@ pub mod reaper;
pub use tokio;
/// A monotonic ticks value for "never happened" that should be lower than any initial value.
pub const NEVER_HAPPENED_TICKS: i64 = i64::MIN / 2;
pub const NEVER_HAPPENED_TICKS: i64 = i64::MIN;
/// Get milliseconds since unix epoch.
#[inline]
@ -44,15 +44,19 @@ pub fn ms_since_epoch() -> i64 {
pub fn ms_monotonic() -> i64 {
static STARTUP_INSTANT: std::sync::RwLock<Option<std::time::Instant>> = std::sync::RwLock::new(None);
let si = *STARTUP_INSTANT.read().unwrap();
let instant_zero = if let Some(si) = si {
si
if let Some(si) = si {
si.elapsed().as_millis() as i64
} else {
*STARTUP_INSTANT.write().unwrap().get_or_insert(std::time::Instant::now())
};
std::time::Instant::now().duration_since(instant_zero).as_millis() as i64
STARTUP_INSTANT
.write()
.unwrap()
.get_or_insert(std::time::Instant::now())
.elapsed()
.as_millis() as i64
}
}
/// Wait for a kill signal (e.g. SIGINT or OS-equivalent) and return when received.
/// Wait for a kill signal (e.g. SIGINT or OS-equivalent) sent to this process and return when received.
#[cfg(unix)]
pub fn wait_for_process_abort() {
if let Ok(mut signals) = signal_hook::iterator::Signals::new(&[libc::SIGINT, libc::SIGTERM, libc::SIGQUIT]) {
@ -65,10 +69,10 @@ pub fn wait_for_process_abort() {
_ => {}
}
}
std::thread::sleep(std::time::Duration::from_millis(500));
std::thread::sleep(std::time::Duration::from_millis(100));
}
} else {
panic!("unable to listen to OS signals");
panic!("unable to listen for OS signals");
}
}

View file

@ -13,6 +13,7 @@ use std::ptr::{drop_in_place, read, write};
/// This will panic if the capacity is too small. If that occurs, it must be enlarged. It will
/// also panic if any of the accessors (other than the try_ versions) are used to try to get
/// a type other than the one it was constructed with.
#[repr(C)]
pub struct Thing<const CAPACITY: usize> {
storage: [u8; CAPACITY],
dropper: fn(*mut u8),