src/config/network.rs: simplify code
This commit is contained in:
		@ -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<Token>,
 | 
			
		||||
    pub method_v6: Option<Token>,
 | 
			
		||||
    pub method_v4: Option<ConfigMethod>,
 | 
			
		||||
    pub method_v6: Option<ConfigMethod>,
 | 
			
		||||
    pub address_v4: Option<String>,
 | 
			
		||||
    pub gateway_v4: Option<String>,
 | 
			
		||||
    pub netmask_v4: Option<u8>,
 | 
			
		||||
@ -37,25 +37,11 @@ pub struct Interface {
 | 
			
		||||
 | 
			
		||||
impl Interface {
 | 
			
		||||
 | 
			
		||||
    pub fn new(
 | 
			
		||||
        name: String,
 | 
			
		||||
        address_family: AddressFamily,
 | 
			
		||||
        config_method: Option<Token>,
 | 
			
		||||
    ) -> 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<Token>) -> &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(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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<Lexer<BufReader<File>>>,
 | 
			
		||||
@ -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));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user