ntp_daemon/
lib.rs

1//! This crate contains the main ntp-daemon code for ntpd-rs and is not intended as
2//! a public interface at this time. It follows the same version as the main ntpd-rs
3//! crate, but that version is not intended to give any stability guarantee. Use at
4//! your own risk.
5//!
6//! Please visit the [ntpd-rs](https://github.com/pendulum-project/ntpd-rs) project
7//! for more information.
8#![forbid(unsafe_code)]
9
10pub mod config;
11mod ipfilter;
12pub mod keyexchange;
13pub mod nts_key_provider;
14pub mod observer;
15mod peer;
16mod server;
17pub mod sockets;
18pub mod spawn;
19mod system;
20pub mod tracing;
21
22use std::{error::Error, sync::Arc};
23
24use clap::Parser;
25pub use config::dynamic::ConfigUpdate;
26pub use config::Config;
27pub use observer::{ObservablePeerState, ObservableState};
28pub use system::spawn;
29//#[cfg(fuzz)]
30pub use ipfilter::fuzz::fuzz_ipfilter;
31use tracing_subscriber::EnvFilter;
32
33use crate::config::CmdArgs;
34
35pub async fn main() -> Result<(), Box<dyn Error>> {
36    let args = CmdArgs::parse();
37    let has_log_override = args.log_filter.is_some();
38    let has_format_override = args.log_format.is_some();
39    let log_filter = args
40        .log_filter
41        // asserts that the arc is not shared. There is no reason it would be,
42        // we just use Arc to work around EnvFilter not implementing Clone
43        .map(|this| Arc::try_unwrap(this).unwrap())
44        .unwrap_or_else(|| EnvFilter::new("info"));
45
46    // Setup some basic tracing now so we are able
47    // to log errors when loading the full configuration.
48    let finish_tracing_init = crate::tracing::init(log_filter, args.log_format.unwrap_or_default());
49
50    let mut config = match Config::from_args(args.config, args.peers, args.servers).await {
51        Ok(c) => c,
52        Err(e) => {
53            // print to stderr because tracing is not yet setup
54            eprintln!("There was an error loading the config: {e}");
55            std::process::exit(exitcode::CONFIG);
56        }
57    };
58
59    // Sentry has a guard we need to keep alive, so store it.
60    // The compiler will optimize this away when not using sentry.
61    let tracing_state =
62        match finish_tracing_init(&mut config, has_log_override, has_format_override) {
63            Ok(s) => s,
64            Err(e) => {
65                // print to stderr because tracing was not correctly initialized
66                eprintln!("Failed to complete logging setup: {e}");
67                std::process::exit(exitcode::CONFIG);
68            }
69        };
70
71    // Warn/error if the config is unreasonable. We do this after finishing
72    // tracing setup to ensure logging is fully configured.
73    config.check();
74
75    // we always generate the keyset (even if NTS is not used)
76    let keyset = crate::nts_key_provider::spawn(config.keyset).await;
77
78    ::tracing::debug!("Configuration loaded, spawning daemon jobs");
79    let (main_loop_handle, channels) = crate::spawn(
80        config.system,
81        config.clock,
82        &config.peers,
83        &config.servers,
84        keyset.clone(),
85    )
86    .await?;
87
88    if let Some(nts_ke_config) = config.nts_ke {
89        let _join_handle = crate::keyexchange::spawn(nts_ke_config, keyset);
90    }
91
92    crate::observer::spawn(
93        &config.observe,
94        channels.peer_snapshots_receiver,
95        channels.server_data_receiver,
96        channels.system_snapshot_receiver,
97    )
98    .await;
99
100    crate::config::dynamic::spawn(
101        config.configure,
102        channels.config_sender,
103        tracing_state.reload_handle,
104    )
105    .await;
106
107    Ok(main_loop_handle.await??)
108}
109
110pub(crate) mod exitcode {
111    /// An internal software error has been detected.  This
112    /// should be limited to non-operating system related
113    /// errors as possible.
114    pub const SOFTWARE: i32 = 70;
115
116    /// You did not have sufficient permission to perform
117    /// the operation.  This is not intended for file system
118    /// problems, which should use `NOINPUT` or `CANTCREAT`,
119    /// but rather for higher level permissions.
120    pub const NOPERM: i32 = 77;
121
122    /// Something was found in an unconfigured or misconfigured state.
123    pub const CONFIG: i32 = 78;
124}