src/config/network.rs: simplify code
This commit is contained in:
parent
f34d4401f7
commit
92310d585c
|
@ -4,7 +4,7 @@ use std::collections::{HashSet, HashMap};
|
||||||
use anyhow::{Error, bail};
|
use anyhow::{Error, bail};
|
||||||
|
|
||||||
mod helper;
|
mod helper;
|
||||||
//pub use helper::*;
|
pub use helper::*;
|
||||||
|
|
||||||
mod lexer;
|
mod lexer;
|
||||||
pub use lexer::*;
|
pub use lexer::*;
|
||||||
|
@ -12,19 +12,19 @@ pub use lexer::*;
|
||||||
mod parser;
|
mod parser;
|
||||||
pub use parser::*;
|
pub use parser::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum AddressFamily {
|
pub enum ConfigMethod {
|
||||||
Inet4and6, // both v4 and v6
|
Manual,
|
||||||
Inet, // v4
|
Static,
|
||||||
Inet6, // v6
|
DHCP,
|
||||||
|
Loopback,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Interface {
|
pub struct Interface {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub address_family: AddressFamily,
|
pub method_v4: Option<ConfigMethod>,
|
||||||
pub method_v4: Option<Token>,
|
pub method_v6: Option<ConfigMethod>,
|
||||||
pub method_v6: Option<Token>,
|
|
||||||
pub address_v4: Option<String>,
|
pub address_v4: Option<String>,
|
||||||
pub gateway_v4: Option<String>,
|
pub gateway_v4: Option<String>,
|
||||||
pub netmask_v4: Option<u8>,
|
pub netmask_v4: Option<u8>,
|
||||||
|
@ -37,25 +37,11 @@ pub struct Interface {
|
||||||
|
|
||||||
impl Interface {
|
impl Interface {
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(name: String) -> Self {
|
||||||
name: String,
|
Self {
|
||||||
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 {
|
|
||||||
name,
|
name,
|
||||||
address_family,
|
method_v4: None,
|
||||||
method_v4: config_method_v4,
|
method_v6: None,
|
||||||
method_v6: config_method_v6,
|
|
||||||
address_v4: None,
|
address_v4: None,
|
||||||
gateway_v4: None,
|
gateway_v4: None,
|
||||||
netmask_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> {
|
fn set_address_v4(&mut self, address: String) -> Result<(), Error> {
|
||||||
if self.address_v4.is_none() {
|
if self.address_v4.is_none() {
|
||||||
self.address_v4 = Some(address);
|
self.address_v4 = Some(address);
|
||||||
|
@ -130,12 +134,12 @@ impl Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_addon_option(&mut self, text: String) {
|
fn push_addon_option(&mut self, text: String) {
|
||||||
match self.address_family {
|
if self.method_v4.is_none() && self.method_v6.is_some() {
|
||||||
AddressFamily::Inet | AddressFamily::Inet4and6 => self.options_v4.push(text),
|
self.options_v6.push(text);
|
||||||
AddressFamily::Inet6 => self.options_v6.push(text),
|
} else {
|
||||||
|
self.options_v4.push(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -164,18 +168,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: &Option<Token>) -> &str {
|
fn method_to_str(method: ConfigMethod) -> &'static str {
|
||||||
match method {
|
match method {
|
||||||
None => "static",
|
ConfigMethod::Static => "static",
|
||||||
Some(method) => {
|
ConfigMethod::Loopback => "loopback",
|
||||||
match method {
|
ConfigMethod::Manual => "manual",
|
||||||
Token::Static => "static",
|
ConfigMethod::DHCP => "dhcp",
|
||||||
Token::Loopback => "loopback",
|
|
||||||
Token::Manual => "manual",
|
|
||||||
Token::DHCP => "dhcp",
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,28 +218,23 @@ impl NetworkConfig {
|
||||||
writeln!(w, "auto {}", name)?;
|
writeln!(w, "auto {}", name)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if interface.address_family == AddressFamily::Inet4and6 && interface.method_v4 == interface.method_v6 {
|
if interface.method_v4 == interface.method_v6 {
|
||||||
writeln!(w, "iface {} {}", name, method_to_str(&interface.method_v4))?;
|
let method = interface.method_v4.unwrap_or(ConfigMethod::Static);
|
||||||
|
writeln!(w, "iface {} {}", name, method_to_str(method))?;
|
||||||
write_attributes_v4(w, &interface)?;
|
write_attributes_v4(w, &interface)?;
|
||||||
write_attributes_v6(w, &interface)?;
|
write_attributes_v6(w, &interface)?;
|
||||||
writeln!(w)?;
|
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 {
|
} 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -286,4 +279,3 @@ impl NetworkConfig {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use proxmox::*; // for IP macros
|
||||||
use super::helper::*;
|
use super::helper::*;
|
||||||
use super::lexer::*;
|
use super::lexer::*;
|
||||||
|
|
||||||
use super::{NetworkConfig, NetworkOrderEntry, Interface, AddressFamily};
|
use super::{NetworkConfig, NetworkOrderEntry, Interface, ConfigMethod};
|
||||||
|
|
||||||
pub struct NetworkParser {
|
pub struct NetworkParser {
|
||||||
input: Peekable<Lexer<BufReader<File>>>,
|
input: Peekable<Lexer<BufReader<File>>>,
|
||||||
|
@ -206,67 +206,54 @@ impl NetworkParser {
|
||||||
self.eat(Token::Iface)?;
|
self.eat(Token::Iface)?;
|
||||||
let iface = self.next_text()?;
|
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;
|
let mut config_method = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (token, text) = self.next()?;
|
let (token, text) = self.next()?;
|
||||||
match token {
|
match token {
|
||||||
Token::Newline => break,
|
Token::Newline => break,
|
||||||
Token::Inet => {
|
Token::Inet => address_family_v4 = true,
|
||||||
address_family = Some(match address_family {
|
Token::Inet6 => address_family_v6 = true,
|
||||||
None => AddressFamily::Inet,
|
Token::Loopback => config_method = Some(ConfigMethod::Loopback),
|
||||||
Some(AddressFamily::Inet) => AddressFamily::Inet,
|
Token::Static => config_method = Some(ConfigMethod::Static),
|
||||||
Some(AddressFamily::Inet6) => AddressFamily::Inet4and6,
|
Token::Manual => config_method = Some(ConfigMethod::Manual),
|
||||||
Some(AddressFamily::Inet4and6) => AddressFamily::Inet4and6,
|
Token::DHCP => config_method = Some(ConfigMethod::DHCP),
|
||||||
});
|
|
||||||
}
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => bail!("unknown iface option {}", text),
|
_ => bail!("unknown iface option {}", text),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let address_family = address_family.unwrap_or(AddressFamily::Inet4and6);
|
|
||||||
|
|
||||||
let has_attributes = self.peek()? == Token::Attribute;
|
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) {
|
if let Some(mut interface) = config.interfaces.get_mut(&iface) {
|
||||||
let compatible = match interface.address_family {
|
if address_family_v4 {
|
||||||
AddressFamily::Inet => {
|
interface.set_method_v4(config_method)?;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
interface.address_family = AddressFamily::Inet4and6;
|
if address_family_v6 {
|
||||||
|
interface.set_method_v6(config_method)?;
|
||||||
|
}
|
||||||
|
|
||||||
if has_attributes { self.parse_iface_attributes(&mut interface)?; }
|
if has_attributes { self.parse_iface_attributes(&mut interface)?; }
|
||||||
} else {
|
} 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)?; }
|
if has_attributes { self.parse_iface_attributes(&mut interface)?; }
|
||||||
|
|
||||||
config.interfaces.insert(interface.name.clone(), interface);
|
config.interfaces.insert(interface.name.clone(), interface);
|
||||||
|
|
||||||
config.order.push(NetworkOrderEntry::Iface(iface));
|
config.order.push(NetworkOrderEntry::Iface(iface));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue