use serde::{Deserialize, Serialize};
use std::net::IpAddr;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct DhcpClientConfig {
pub enabled: bool,
pub interfaces: Vec<String>,
pub mock_mode: bool,
pub dhcpv4: Dhcpv4Config,
pub dhcpv6: Dhcpv6Config,
pub pxe: PxeConfigSettings,
pub ddns: DdnsConfig,
pub tftp: TftpConfig,
pub failover: FailoverConfig,
pub security: SecurityConfig,
pub wifi: WifiInterfaceConfig,
}
impl Default for DhcpClientConfig {
fn default() -> Self {
Self {
enabled: true,
interfaces: vec!["eth0".to_string()],
mock_mode: false,
dhcpv4: Dhcpv4Config::default(),
dhcpv6: Dhcpv6Config::default(),
pxe: PxeConfigSettings::default(),
ddns: DdnsConfig::default(),
tftp: TftpConfig::default(),
failover: FailoverConfig::default(),
security: SecurityConfig::default(),
wifi: WifiInterfaceConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Dhcpv4Config {
pub enabled: bool,
pub hostname: Option<String>,
pub send_hostname: bool,
pub vendor_class: Option<String>,
pub request_options: Vec<u8>,
pub timeout: u64, pub retry_count: u32,
}
impl Default for Dhcpv4Config {
fn default() -> Self {
Self {
enabled: true,
hostname: None,
send_hostname: true,
vendor_class: Some("crrouter-web".to_string()),
request_options: vec![1, 3, 6, 15, 28, 42], timeout: 10,
retry_count: 3,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Dhcpv6Config {
pub enabled: bool,
pub request_options: Vec<u16>,
pub prefix_delegation: bool,
pub rapid_commit: bool,
pub timeout: u64, pub retry_count: u32,
pub authentication: Dhcpv6AuthConfig,
pub tls: Dhcpv6TlsConfig,
}
impl Default for Dhcpv6Config {
fn default() -> Self {
Self {
enabled: false,
request_options: vec![23, 24], prefix_delegation: true,
rapid_commit: false,
timeout: 10,
retry_count: 3,
authentication: Dhcpv6AuthConfig::default(),
tls: Dhcpv6TlsConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Dhcpv6TlsConfig {
pub enabled: bool,
pub use_tcp: bool,
pub require_tls: bool,
pub verify_server: bool,
pub server_name: Option<String>,
pub ca_cert: Option<String>,
pub client_cert: Option<String>,
pub client_key: Option<String>,
pub min_version: String,
pub tcp_port: u16,
}
impl Default for Dhcpv6TlsConfig {
fn default() -> Self {
Self {
enabled: false,
use_tcp: false,
require_tls: false,
verify_server: true,
server_name: None,
ca_cert: None,
client_cert: None,
client_key: None,
min_version: "1.2".to_string(),
tcp_port: 547,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Dhcpv6AuthConfig {
pub enabled: bool,
pub protocol: String,
pub algorithm: String,
pub key: Option<String>,
pub key_id: Option<u32>,
pub realm: Option<String>,
pub require_server_auth: bool,
pub accept_unauthenticated: bool,
}
impl Default for Dhcpv6AuthConfig {
fn default() -> Self {
Self {
enabled: false,
protocol: "delayed".to_string(),
algorithm: "hmac-sha256".to_string(),
key: None,
key_id: None,
realm: None,
require_server_auth: false,
accept_unauthenticated: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct PxeConfigSettings {
pub enabled: bool,
pub vendor_class: String,
pub architecture: u16, }
impl Default for PxeConfigSettings {
fn default() -> Self {
Self {
enabled: false,
vendor_class: "PXEClient".to_string(),
architecture: 0x0007, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct DdnsConfig {
pub enabled: bool,
pub update_forward: bool,
pub update_reverse: bool,
pub ttl: u32,
pub server: Option<String>,
pub tsig_key_name: Option<String>,
pub tsig_key: Option<String>,
}
impl Default for DdnsConfig {
fn default() -> Self {
Self {
enabled: false,
update_forward: true,
update_reverse: true,
ttl: 3600,
server: None, tsig_key_name: None,
tsig_key: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct TftpConfig {
pub enabled: bool,
pub timeout: u64, pub max_retries: u32,
pub block_size: u16,
}
impl Default for TftpConfig {
fn default() -> Self {
Self {
enabled: false,
timeout: 5,
max_retries: 3,
block_size: 1468, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct FailoverConfig {
pub enabled: bool,
pub server_timeout: u64, pub health_check_interval: u64, pub allowed_servers: Vec<IpAddr>,
pub prefer_previous_server: bool,
}
impl Default for FailoverConfig {
fn default() -> Self {
Self {
enabled: false,
server_timeout: 5,
health_check_interval: 30,
allowed_servers: Vec::new(),
prefer_previous_server: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct WifiInterfaceConfig {
pub auto_connect: bool,
pub networks: std::collections::HashMap<String, WifiNetworkConfig>,
}
impl Default for WifiInterfaceConfig {
fn default() -> Self {
Self {
auto_connect: true,
networks: std::collections::HashMap::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct WifiNetworkConfig {
pub ssid: String,
pub security: String,
pub passphrase: Option<String>,
pub wep_key: Option<String>,
pub identity: Option<String>,
pub password: Option<String>,
pub ca_cert: Option<String>,
pub hidden: bool,
pub timeout: u64,
}
impl Default for WifiNetworkConfig {
fn default() -> Self {
Self {
ssid: String::new(),
security: "wpa2".to_string(),
passphrase: None,
wep_key: None,
identity: None,
password: None,
ca_cert: None,
hidden: false,
timeout: 30,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct SecurityConfig {
pub validate_messages: bool,
pub validate_options: bool,
pub validate_server: bool,
pub allowed_servers: Vec<IpAddr>,
pub max_request_rate: u32, pub enable_dhcp_snooping: bool,
pub min_lease_time: u32, pub max_lease_time: u32, }
impl Default for SecurityConfig {
fn default() -> Self {
Self {
validate_messages: true,
validate_options: true,
validate_server: false,
allowed_servers: Vec::new(),
max_request_rate: 10,
enable_dhcp_snooping: false,
min_lease_time: 300, max_lease_time: 86400 * 7, }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = DhcpClientConfig::default();
assert!(config.enabled);
assert!(config.dhcpv4.enabled);
assert!(!config.dhcpv6.enabled); assert!(!config.pxe.enabled);
assert!(!config.ddns.enabled); assert!(!config.tftp.enabled);
assert!(!config.failover.enabled); }
#[test]
fn test_security_config() {
let config = SecurityConfig::default();
assert!(config.validate_messages);
assert!(config.validate_options);
assert_eq!(config.max_request_rate, 10);
assert_eq!(config.min_lease_time, 300);
}
}