1
use std::{collections::HashSet, path::PathBuf, time::Duration};
2

            
3
use serde::{Deserialize, Serialize};
4

            
5
pub const DEFAULT_CONFIG_PATH: &str = "/etc/roowho2/config.toml";
6

            
7
/// Default interval between rwhod status packet broadcasts.
8
const DEFAULT_SEND_INTERVAL_SECONDS: u64 = 60;
9

            
10
/// Default maximum number of distinct hosts to keep rwhod status records for at the same time.
11
const DEFAULT_MAX_STATUS_ENTRIES: usize = 4096;
12

            
13
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14
pub struct Config {
15
    /// Logging level for the daemon.
16
    pub log_level: Option<LogLevel>,
17

            
18
    /// Configuration for the rwhod server.
19
    pub rwhod: RwhodConfig,
20

            
21
    /// Configuration for the fingerd server.
22
    pub fingerd: FingerdConfig,
23

            
24
    /// Configuration for the walld server.
25
    pub walld: WalldConfig,
26

            
27
    /// Path to the Unix domain socket for client-server communication.
28
    ///
29
    /// If left as `None`, the server expects to be served a file descriptor to the socket named 'client'.
30
    pub client_socket_path: Option<String>,
31
}
32

            
33
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
34
#[serde(rename_all = "lowercase")]
35
pub enum LogLevel {
36
    Info,
37
    Debug,
38
    Trace,
39
}
40

            
41
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
42
pub struct RwhodConfig {
43
    /// Enable or disable the rwhod server functionality.
44
    pub enable: bool,
45

            
46
    /// Path to the ignore list for users that should be hidden from rwhod.
47
    pub ignore_list_path: Option<PathBuf>,
48

            
49
    /// Network interfaces to send rwhod packets on (e.g., ["eth0", "wlan0"]).
50
    ///
51
    /// If left as `None`, the server will send on all relevant interfaces it can find.
52
    pub interfaces: Option<HashSet<String>>,
53

            
54
    /// Interval between rwhod status packet broadcasts.
55
    ///
56
    /// If left as `None`, defaults to 60 seconds.
57
    pub send_interval_seconds: Option<u64>,
58

            
59
    /// Maximum number of distinct hosts to keep rwhod status records for at
60
    /// the same time. Once at capacity, the least recently updated record
61
    /// is evicted to make room for a newly-seen host.
62
    ///
63
    /// If left as `None`, defaults to 4096.
64
    pub max_status_entries: Option<usize>,
65

            
66
    /// Whether to react to Linux audit log activity (e.g. logins/logouts)
67
    /// and push a status update immediately, instead of only on the
68
    /// regular `send_interval_seconds` interval.
69
    ///
70
    /// If left as `None`, defaults to `false`.
71
    pub realtime_updates: Option<bool>,
72
}
73

            
74
impl RwhodConfig {
75
    /// Resolves [`Self::send_interval_seconds`] into a concrete interval.
76
    pub fn send_interval(&self) -> Duration {
77
        let seconds = match self.send_interval_seconds {
78
            Some(0) => {
79
                tracing::warn!(
80
                    "rwhod.send_interval_seconds is set to 0, remapping to default value of {} seconds",
81
                    DEFAULT_SEND_INTERVAL_SECONDS
82
                );
83
                DEFAULT_SEND_INTERVAL_SECONDS
84
            }
85
            Some(seconds) => seconds,
86
            None => DEFAULT_SEND_INTERVAL_SECONDS,
87
        };
88

            
89
        Duration::from_secs(seconds)
90
    }
91

            
92
    /// Resolves [`Self::max_status_entries`] into a concrete limit.
93
    pub fn max_status_entries(&self) -> usize {
94
        match self.max_status_entries {
95
            Some(0) => {
96
                tracing::warn!(
97
                    "rwhod.max_status_entries is set to 0, remapping to default value of {}",
98
                    DEFAULT_MAX_STATUS_ENTRIES
99
                );
100
                DEFAULT_MAX_STATUS_ENTRIES
101
            }
102
            Some(max_status_entries) => max_status_entries,
103
            None => DEFAULT_MAX_STATUS_ENTRIES,
104
        }
105
    }
106

            
107
    /// Resolves [`Self::realtime_updates`] into a concrete flag.
108
    pub fn realtime_updates_enabled(&self) -> bool {
109
        self.realtime_updates.unwrap_or(false)
110
    }
111
}
112

            
113
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
114
pub struct FingerdConfig {
115
    /// Enable or disable the fingerd server functionality.
116
    pub enable: bool,
117

            
118
    /// Path to the ignore list for users that should be hidden from fingerd.
119
    pub ignore_list_path: Option<PathBuf>,
120
}
121

            
122
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
123
pub struct WalldConfig {
124
    /// Enable or disable the walld server functionality.
125
    pub enable: bool,
126
}