diff --git a/src/config/network.rs b/src/config/network.rs index 37512771..9130555d 100644 --- a/src/config/network.rs +++ b/src/config/network.rs @@ -4,7 +4,7 @@ use std::collections::{HashSet, HashMap}; use anyhow::{Error, bail}; mod helper; -//pub use helper::*; +pub use helper::*; mod lexer; pub use lexer::*; @@ -12,19 +12,19 @@ pub use lexer::*; mod parser; pub use parser::*; -#[derive(Debug, PartialEq)] -pub enum AddressFamily { - Inet4and6, // both v4 and v6 - Inet, // v4 - Inet6, // v6 +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum ConfigMethod { + Manual, + Static, + DHCP, + Loopback, } #[derive(Debug)] pub struct Interface { pub name: String, - pub address_family: AddressFamily, - pub method_v4: Option, - pub method_v6: Option, + pub method_v4: Option, + pub method_v6: Option, pub address_v4: Option, pub gateway_v4: Option, pub netmask_v4: Option, @@ -37,25 +37,11 @@ pub struct Interface { impl Interface { - pub fn new( - name: String, - address_family: AddressFamily, - config_method: Option, - ) -> Self { - let config_method_v4 = match address_family { - AddressFamily::Inet | AddressFamily::Inet4and6 => Some(config_method.unwrap_or(Token::Static)), - _ => None, - }; - let config_method_v6 = match address_family { - AddressFamily::Inet6 | AddressFamily::Inet4and6 => Some(config_method.unwrap_or(Token::Static)), - _ => None, - }; - - Self { + pub fn new(name: String) -> Self { + Self { name, - address_family, - method_v4: config_method_v4, - method_v6: config_method_v6, + method_v4: None, + method_v6: None, address_v4: None, gateway_v4: None, netmask_v4: None, @@ -67,6 +53,24 @@ impl Interface { } } + fn set_method_v4(&mut self, method: ConfigMethod) -> Result<(), Error> { + if self.method_v4.is_none() { + self.method_v4 = Some(method); + } else { + bail!("inet configuration method already set."); + } + Ok(()) + } + + fn set_method_v6(&mut self, method: ConfigMethod) -> Result<(), Error> { + if self.method_v6.is_none() { + self.method_v6 = Some(method); + } else { + bail!("inet6 configuration method already set."); + } + Ok(()) + } + fn set_address_v4(&mut self, address: String) -> Result<(), Error> { if self.address_v4.is_none() { self.address_v4 = Some(address); @@ -130,12 +134,12 @@ impl Interface { } fn push_addon_option(&mut self, text: String) { - match self.address_family { - AddressFamily::Inet | AddressFamily::Inet4and6 => self.options_v4.push(text), - AddressFamily::Inet6 => self.options_v6.push(text), + if self.method_v4.is_none() && self.method_v6.is_some() { + self.options_v6.push(text); + } else { + self.options_v4.push(text); } } - } #[derive(Debug)] @@ -164,18 +168,12 @@ impl NetworkConfig { pub fn write_config(&self, w: &mut dyn Write) -> Result<(), Error> { - fn method_to_str(method: &Option) -> &str { + fn method_to_str(method: ConfigMethod) -> &'static str { match method { - None => "static", - Some(method) => { - match method { - Token::Static => "static", - Token::Loopback => "loopback", - Token::Manual => "manual", - Token::DHCP => "dhcp", - _ => unreachable!(), - } - } + ConfigMethod::Static => "static", + ConfigMethod::Loopback => "loopback", + ConfigMethod::Manual => "manual", + ConfigMethod::DHCP => "dhcp", } } @@ -220,28 +218,23 @@ impl NetworkConfig { writeln!(w, "auto {}", name)?; } - if interface.address_family == AddressFamily::Inet4and6 && interface.method_v4 == interface.method_v6 { - writeln!(w, "iface {} {}", name, method_to_str(&interface.method_v4))?; + if interface.method_v4 == interface.method_v6 { + let method = interface.method_v4.unwrap_or(ConfigMethod::Static); + writeln!(w, "iface {} {}", name, method_to_str(method))?; write_attributes_v4(w, &interface)?; write_attributes_v6(w, &interface)?; writeln!(w)?; - } else if interface.address_family == AddressFamily::Inet4and6 { - writeln!(w, "iface {} inet {}", name, method_to_str(&interface.method_v4))?; - write_attributes_v4(w, &interface)?; - writeln!(w)?; - writeln!(w, "iface {} inet6 {}", name, method_to_str(&interface.method_v6))?; - write_attributes_v6(w, &interface)?; - writeln!(w)?; - } else if interface.address_family == AddressFamily::Inet { - writeln!(w, "iface {} inet {}", name, method_to_str(&interface.method_v4))?; - write_attributes_v4(w, &interface)?; - writeln!(w)?; - } else if interface.address_family == AddressFamily::Inet6 { - writeln!(w, "iface {} inet {}", name, method_to_str(&interface.method_v6))?; - write_attributes_v6(w, &interface)?; - writeln!(w)?; } else { - unreachable!(); + if let Some(method) = interface.method_v4 { + writeln!(w, "iface {} inet {}", name, method_to_str(method))?; + write_attributes_v4(w, &interface)?; + writeln!(w)?; + } + if let Some(method) = interface.method_v6 { + writeln!(w, "iface {} inet6 {}", name, method_to_str(method))?; + write_attributes_v6(w, &interface)?; + writeln!(w)?; + } } Ok(()) } @@ -286,4 +279,3 @@ impl NetworkConfig { Ok(()) } } - diff --git a/src/config/network/parser.rs b/src/config/network/parser.rs index 63c819f3..25c8508a 100644 --- a/src/config/network/parser.rs +++ b/src/config/network/parser.rs @@ -11,7 +11,7 @@ use proxmox::*; // for IP macros use super::helper::*; use super::lexer::*; -use super::{NetworkConfig, NetworkOrderEntry, Interface, AddressFamily}; +use super::{NetworkConfig, NetworkOrderEntry, Interface, ConfigMethod}; pub struct NetworkParser { input: Peekable>>, @@ -206,67 +206,54 @@ impl NetworkParser { self.eat(Token::Iface)?; let iface = self.next_text()?; - let mut address_family = None; + let mut address_family_v4 = false; + let mut address_family_v6 = false; let mut config_method = None; loop { let (token, text) = self.next()?; match token { Token::Newline => break, - Token::Inet => { - address_family = Some(match address_family { - None => AddressFamily::Inet, - Some(AddressFamily::Inet) => AddressFamily::Inet, - Some(AddressFamily::Inet6) => AddressFamily::Inet4and6, - Some(AddressFamily::Inet4and6) => AddressFamily::Inet4and6, - }); - } - Token::Inet6 => { - address_family = Some(match address_family { - None => AddressFamily::Inet6, - Some(AddressFamily::Inet) => AddressFamily::Inet4and6, - Some(AddressFamily::Inet6) => AddressFamily::Inet6, - Some(AddressFamily::Inet4and6) => AddressFamily::Inet4and6, - }); - } - Token::Loopback | Token::Static | Token::Manual | Token::DHCP => { - if config_method.is_none() { - config_method = Some(token); - } else { - bail!("multiple configuration method definitions"); - } - } + Token::Inet => address_family_v4 = true, + Token::Inet6 => address_family_v6 = true, + Token::Loopback => config_method = Some(ConfigMethod::Loopback), + Token::Static => config_method = Some(ConfigMethod::Static), + Token::Manual => config_method = Some(ConfigMethod::Manual), + Token::DHCP => config_method = Some(ConfigMethod::DHCP), _ => bail!("unknown iface option {}", text), } } - let address_family = address_family.unwrap_or(AddressFamily::Inet4and6); - let has_attributes = self.peek()? == Token::Attribute; + let config_method = config_method.unwrap_or(ConfigMethod::Static); + + if !(address_family_v4 || address_family_v6) { + address_family_v4 = true; + address_family_v6 = true; + } if let Some(mut interface) = config.interfaces.get_mut(&iface) { - let compatible = match interface.address_family { - AddressFamily::Inet => { - interface.method_v6 = config_method; - address_family == AddressFamily::Inet6 - } - AddressFamily::Inet6 => { - interface.method_v4 = config_method; - address_family == AddressFamily::Inet - } - _ => false, - }; - if !compatible { - bail!("duplicate config for iface '{}'", iface); + if address_family_v4 { + interface.set_method_v4(config_method)?; } - interface.address_family = AddressFamily::Inet4and6; + if address_family_v6 { + interface.set_method_v6(config_method)?; + } + if has_attributes { self.parse_iface_attributes(&mut interface)?; } } else { - let mut interface = Interface::new(iface.clone(), address_family, config_method); + let mut interface = Interface::new(iface.clone()); + if address_family_v4 { + interface.set_method_v4(config_method)?; + } + if address_family_v6 { + interface.set_method_v6(config_method)?; + } if has_attributes { self.parse_iface_attributes(&mut interface)?; } config.interfaces.insert(interface.name.clone(), interface); + config.order.push(NetworkOrderEntry::Iface(iface)); }