toe_beans/v4/server/config/
mod.rs1mod lease_time;
2
3use super::RESOLVED_SERVER_PORT;
4use crate::v4::MessageOptions;
5use ip_network::Ipv4Network;
6pub use lease_time::LeaseTime;
7use log::{info, warn};
8use mac_address::MacAddress;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::fs::{read_to_string, OpenOptions};
12use std::io::Write;
13use std::net::{Ipv4Addr, SocketAddrV4};
14use std::os::unix::fs::OpenOptionsExt;
15use std::path::PathBuf;
16use toml;
17
18#[derive(Serialize, Deserialize, Debug)]
22pub struct Config {
23 #[serde(skip)]
25 pub path: PathBuf,
26 pub lease_time: LeaseTime,
28 pub rapid_commit: bool,
30 pub network_cidr: Ipv4Network,
32 pub listen_address: SocketAddrV4,
34 pub interface: Option<String>,
37 pub server_address: Option<Ipv4Addr>,
43 pub parameters: HashMap<String, MessageOptions>,
46 pub static_leases: HashMap<MacAddress, Ipv4Addr>,
48}
49
50impl Default for Config {
51 fn default() -> Self {
52 Self {
53 path: PathBuf::new(), lease_time: LeaseTime::new(86_400).unwrap(), rapid_commit: true,
56 network_cidr: Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 0), 16).unwrap(), listen_address: SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), RESOLVED_SERVER_PORT),
58 interface: None,
59 server_address: None,
60 parameters: HashMap::with_capacity(u8::MAX as usize),
61 static_leases: HashMap::new(),
62 }
63 }
64}
65
66impl Config {
67 pub const FILE_NAME: &'static str = "toe-beans.toml";
69
70 pub fn read(from_where: PathBuf) -> Self {
73 let read_result = read_to_string(from_where.join(Self::FILE_NAME));
74 if let Ok(config_string) = read_result {
75 let toml_result = toml::from_str(&config_string);
76 match toml_result {
77 Ok(config) => {
78 return Self {
79 path: from_where, ..config
81 };
82 }
83 Err(error) => {
84 warn!("{error}");
85 warn!(
86 "Warning: invalid {}. Using default values.",
87 Self::FILE_NAME
88 );
89 }
90 }
91 } else {
92 warn!(
93 "Warning: can't read {}. Using default values.",
94 Self::FILE_NAME
95 );
96 }
97
98 Self {
99 path: from_where,
100 ..Config::default()
101 }
102 }
103
104 pub fn write(&self) {
106 info!("Writing {}", Self::FILE_NAME);
107
108 let config_content = toml::to_string_pretty(self).expect("Failed to generate toml data");
109 let mode = 0o600;
110
111 let mut file = OpenOptions::new()
112 .read(false)
113 .write(true)
114 .create(true)
115 .truncate(true)
116 .mode(mode) .open(self.path.join(Self::FILE_NAME))
118 .unwrap_or_else(|_| panic!("Failed to open config {} for writing", Self::FILE_NAME));
119
120 file.write_all(config_content.as_bytes())
121 .unwrap_or_else(|_| panic!("Failed to write config to {}", Self::FILE_NAME));
122 }
123}