src/config/network.rs: cleanup autostart flag handling
This commit is contained in:
		@ -22,6 +22,7 @@ pub enum ConfigMethod {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct Interface {
 | 
					pub struct Interface {
 | 
				
			||||||
 | 
					    pub autostart: bool,
 | 
				
			||||||
    pub name: String,
 | 
					    pub name: String,
 | 
				
			||||||
    pub method_v4: Option<ConfigMethod>,
 | 
					    pub method_v4: Option<ConfigMethod>,
 | 
				
			||||||
    pub method_v6: Option<ConfigMethod>,
 | 
					    pub method_v6: Option<ConfigMethod>,
 | 
				
			||||||
@ -38,8 +39,9 @@ pub struct Interface {
 | 
				
			|||||||
impl Interface {
 | 
					impl Interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new(name: String) -> Self {
 | 
					    pub fn new(name: String) -> Self {
 | 
				
			||||||
         Self {
 | 
					        Self {
 | 
				
			||||||
            name,
 | 
					            name,
 | 
				
			||||||
 | 
					            autostart: false,
 | 
				
			||||||
            method_v4: None,
 | 
					            method_v4: None,
 | 
				
			||||||
            method_v6: None,
 | 
					            method_v6: None,
 | 
				
			||||||
            address_v4: None,
 | 
					            address_v4: None,
 | 
				
			||||||
@ -140,6 +142,78 @@ impl Interface {
 | 
				
			|||||||
            self.options_v4.push(text);
 | 
					            self.options_v4.push(text);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn write_iface_attributes_v4(&self, w: &mut dyn Write) -> Result<(), Error> {
 | 
				
			||||||
 | 
					        if let Some(address) = &self.address_v4 {
 | 
				
			||||||
 | 
					            if let Some(netmask) = self.netmask_v4 {
 | 
				
			||||||
 | 
					                writeln!(w, "    address {}/{}", address, netmask)?;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                writeln!(w, "    address {}", address)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if let Some(gateway) = &self.gateway_v4 {
 | 
				
			||||||
 | 
					            writeln!(w, "    gateway {}", gateway)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for option in &self.options_v4 {
 | 
				
			||||||
 | 
					            writeln!(w, "    {}", option)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn write_iface_attributes_v6(&self, w: &mut dyn Write) -> Result<(), Error> {
 | 
				
			||||||
 | 
					        if let Some(address) = &self.address_v6 {
 | 
				
			||||||
 | 
					            if let Some(netmask) = self.netmask_v6 {
 | 
				
			||||||
 | 
					                writeln!(w, "    address {}/{}", address, netmask)?;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                writeln!(w, "    address {}", address)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if let Some(gateway) = &self.gateway_v6 {
 | 
				
			||||||
 | 
					            writeln!(w, "    gateway {}", gateway)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for option in &self.options_v6 {
 | 
				
			||||||
 | 
					            writeln!(w, "    {}", option)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn write_iface(&self, w: &mut dyn Write) -> Result<(), Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fn method_to_str(method: ConfigMethod) -> &'static str {
 | 
				
			||||||
 | 
					            match method {
 | 
				
			||||||
 | 
					                ConfigMethod::Static => "static",
 | 
				
			||||||
 | 
					                ConfigMethod::Loopback => "loopback",
 | 
				
			||||||
 | 
					                ConfigMethod::Manual => "manual",
 | 
				
			||||||
 | 
					                ConfigMethod::DHCP => "dhcp",
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.autostart {
 | 
				
			||||||
 | 
					            writeln!(w, "auto {}", self.name)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.method_v4 == self.method_v6 {
 | 
				
			||||||
 | 
					            let method = self.method_v4.unwrap_or(ConfigMethod::Static);
 | 
				
			||||||
 | 
					            writeln!(w, "iface {} {}", self.name, method_to_str(method))?;
 | 
				
			||||||
 | 
					            self.write_iface_attributes_v4(w)?;
 | 
				
			||||||
 | 
					            self.write_iface_attributes_v6(w)?;
 | 
				
			||||||
 | 
					            writeln!(w)?;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if let Some(method) = self.method_v4 {
 | 
				
			||||||
 | 
					                writeln!(w, "iface {} inet {}", self.name, method_to_str(method))?;
 | 
				
			||||||
 | 
					                self.write_iface_attributes_v4(w)?;
 | 
				
			||||||
 | 
					                writeln!(w)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if let Some(method) = self.method_v6 {
 | 
				
			||||||
 | 
					                writeln!(w, "iface {} inet6 {}", self.name, method_to_str(method))?;
 | 
				
			||||||
 | 
					                self.write_iface_attributes_v6(w)?;
 | 
				
			||||||
 | 
					                writeln!(w)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
@ -151,7 +225,6 @@ enum NetworkOrderEntry {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct NetworkConfig {
 | 
					pub struct NetworkConfig {
 | 
				
			||||||
    pub auto_flag: HashSet<String>,
 | 
					 | 
				
			||||||
    interfaces: HashMap<String, Interface>,
 | 
					    interfaces: HashMap<String, Interface>,
 | 
				
			||||||
    order: Vec<NetworkOrderEntry>,
 | 
					    order: Vec<NetworkOrderEntry>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -160,7 +233,6 @@ impl NetworkConfig {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            auto_flag: HashSet::new(),
 | 
					 | 
				
			||||||
            interfaces: HashMap::new(),
 | 
					            interfaces: HashMap::new(),
 | 
				
			||||||
            order: Vec::new(),
 | 
					            order: Vec::new(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -168,83 +240,12 @@ impl NetworkConfig {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn write_config(&self, w: &mut dyn Write) -> Result<(), Error> {
 | 
					    pub fn write_config(&self, w: &mut dyn Write) -> Result<(), Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn method_to_str(method: ConfigMethod) -> &'static str {
 | 
					 | 
				
			||||||
            match method {
 | 
					 | 
				
			||||||
                ConfigMethod::Static => "static",
 | 
					 | 
				
			||||||
                ConfigMethod::Loopback => "loopback",
 | 
					 | 
				
			||||||
                ConfigMethod::Manual => "manual",
 | 
					 | 
				
			||||||
                ConfigMethod::DHCP => "dhcp",
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fn write_attributes_v4(w: &mut dyn Write, interface: &Interface) -> Result<(), Error> {
 | 
					 | 
				
			||||||
            if let Some(address) = &interface.address_v4 {
 | 
					 | 
				
			||||||
                if let Some(netmask) = interface.netmask_v4 {
 | 
					 | 
				
			||||||
                    writeln!(w, "    address {}/{}", address, netmask)?;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    writeln!(w, "    address {}", address)?;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if let Some(gateway) = &interface.gateway_v4 {
 | 
					 | 
				
			||||||
                writeln!(w, "    gateway {}", gateway)?;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            for option in &interface.options_v4 {
 | 
					 | 
				
			||||||
                writeln!(w, "    {}", option)?;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Ok(())
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fn write_attributes_v6(w: &mut dyn Write, interface: &Interface) -> Result<(), Error> {
 | 
					 | 
				
			||||||
            if let Some(address) = &interface.address_v6 {
 | 
					 | 
				
			||||||
                if let Some(netmask) = interface.netmask_v6 {
 | 
					 | 
				
			||||||
                    writeln!(w, "    address {}/{}", address, netmask)?;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    writeln!(w, "    address {}", address)?;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if let Some(gateway) = &interface.gateway_v6 {
 | 
					 | 
				
			||||||
                writeln!(w, "    gateway {}", gateway)?;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            for option in &interface.options_v6 {
 | 
					 | 
				
			||||||
                writeln!(w, "    {}", option)?;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Ok(())
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fn write_interface(w: &mut dyn Write, config: &NetworkConfig, name: &str, interface: &Interface) -> Result<(), Error> {
 | 
					 | 
				
			||||||
            if config.auto_flag.contains(name) {
 | 
					 | 
				
			||||||
                writeln!(w, "auto {}", name)?;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            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 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(())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut done = HashSet::new();
 | 
					        let mut done = HashSet::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut last_entry_was_comment = false;
 | 
					        let mut last_entry_was_comment = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for entry in self.order.iter() {
 | 
					        for entry in self.order.iter() {
 | 
				
			||||||
            match entry {
 | 
					             match entry {
 | 
				
			||||||
                NetworkOrderEntry::Comment(comment) => {
 | 
					                NetworkOrderEntry::Comment(comment) => {
 | 
				
			||||||
                    writeln!(w, "#{}", comment)?;
 | 
					                    writeln!(w, "#{}", comment)?;
 | 
				
			||||||
                    last_entry_was_comment = true;
 | 
					                    last_entry_was_comment = true;
 | 
				
			||||||
@ -267,14 +268,14 @@ impl NetworkConfig {
 | 
				
			|||||||
                    if done.contains(name) { continue; }
 | 
					                    if done.contains(name) { continue; }
 | 
				
			||||||
                    done.insert(name);
 | 
					                    done.insert(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    write_interface(w, self, name, interface)?;
 | 
					                    interface.write_iface(w)?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (name, interface) in &self.interfaces {
 | 
					        for (name, interface) in &self.interfaces {
 | 
				
			||||||
            if done.contains(name) { continue; }
 | 
					            if done.contains(name) { continue; }
 | 
				
			||||||
            write_interface(w, self, name, interface)?;
 | 
					            interface.write_iface(w)?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
use std::io::{BufReader};
 | 
					use std::io::{BufReader};
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::iter::{Peekable, Iterator};
 | 
					use std::iter::{Peekable, Iterator};
 | 
				
			||||||
 | 
					use std::collections::HashSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use anyhow::{Error, bail, format_err};
 | 
					use anyhow::{Error, bail, format_err};
 | 
				
			||||||
use lazy_static::lazy_static;
 | 
					use lazy_static::lazy_static;
 | 
				
			||||||
@ -70,15 +71,22 @@ impl NetworkParser {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn parse_auto(&mut self, config: &mut NetworkConfig) -> Result<(), Error> {
 | 
					    fn parse_auto(&mut self, auto_flag: &mut HashSet<String>) -> Result<(), Error> {
 | 
				
			||||||
        self.eat(Token::Auto)?;
 | 
					        self.eat(Token::Auto)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let iface = self.next_text()?;
 | 
					        loop {
 | 
				
			||||||
        println!("AUTO {}", iface);
 | 
					            match self.next()? {
 | 
				
			||||||
 | 
					                (Token::Text, iface) => {
 | 
				
			||||||
 | 
					                    println!("AUTO {}", iface);
 | 
				
			||||||
 | 
					                    auto_flag.insert(iface.to_string());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                (Token::Newline, _) => break,
 | 
				
			||||||
 | 
					                unexpected => {
 | 
				
			||||||
 | 
					                    bail!("expected {:?}, got {:?}", Token::Text, unexpected);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.eat(Token::Newline)?;
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        config.auto_flag.insert(iface.to_string());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -268,13 +276,15 @@ impl NetworkParser {
 | 
				
			|||||||
    pub fn _parse_interfaces(&mut self) -> Result<NetworkConfig, Error> {
 | 
					    pub fn _parse_interfaces(&mut self) -> Result<NetworkConfig, Error> {
 | 
				
			||||||
        let mut config = NetworkConfig::new();
 | 
					        let mut config = NetworkConfig::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut auto_flag: HashSet<String> = HashSet::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let peek = self.peek()?;
 | 
					            let peek = self.peek()?;
 | 
				
			||||||
            println!("TOKEN: {:?}", peek);
 | 
					            println!("TOKEN: {:?}", peek);
 | 
				
			||||||
            match peek {
 | 
					            match peek {
 | 
				
			||||||
                Token::EOF => {
 | 
					                Token::EOF => {
 | 
				
			||||||
                    // fixme: trailing comments
 | 
					                    // fixme: trailing comments
 | 
				
			||||||
                    return Ok(config);
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Token::Newline => {
 | 
					                Token::Newline => {
 | 
				
			||||||
                    self.eat(Token::Newline)?;
 | 
					                    self.eat(Token::Newline)?;
 | 
				
			||||||
@ -287,7 +297,7 @@ impl NetworkParser {
 | 
				
			|||||||
                    self.eat(Token::Newline)?;
 | 
					                    self.eat(Token::Newline)?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Token::Auto => {
 | 
					                Token::Auto => {
 | 
				
			||||||
                    self.parse_auto(&mut config)?;
 | 
					                    self.parse_auto(&mut auto_flag)?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Token::Iface => {
 | 
					                Token::Iface => {
 | 
				
			||||||
                    self.parse_iface(&mut config)?;
 | 
					                    self.parse_iface(&mut config)?;
 | 
				
			||||||
@ -300,5 +310,13 @@ impl NetworkParser {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for iface in auto_flag.iter() {
 | 
				
			||||||
 | 
					            if let Some(interface) = config.interfaces.get_mut(iface) {
 | 
				
			||||||
 | 
					                interface.autostart = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(config)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user