forked from NationTech/harmony
wip(opnsense-config): Refactoring to improve usability and features
This commit is contained in:
parent
85786cf648
commit
65c395aeae
14
harmony-rs/Cargo.lock
generated
14
harmony-rs/Cargo.lock
generated
@ -1248,12 +1248,26 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
|
"opnsense-config-xml",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"russh",
|
"russh",
|
||||||
"russh-keys",
|
"russh-keys",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opnsense-config-xml"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
"pretty_assertions",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
"xml-rs",
|
"xml-rs",
|
||||||
"yaserde",
|
"yaserde",
|
||||||
"yaserde_derive",
|
"yaserde_derive",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ resolver = "2"
|
|||||||
members = [
|
members = [
|
||||||
"private_repos/*",
|
"private_repos/*",
|
||||||
"harmony",
|
"harmony",
|
||||||
"opnsense-config",
|
"opnsense-config", "opnsense-config-xml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
|||||||
22
harmony-rs/opnsense-config-xml/Cargo.toml
Normal file
22
harmony-rs/opnsense-config-xml/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "opnsense-config-xml"
|
||||||
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0.123", features = [ "derive" ] }
|
||||||
|
log = { workspace = true }
|
||||||
|
env_logger = { workspace = true }
|
||||||
|
#yaserde = { git = "https://git.nationtech.io/NationTech/yaserde" }
|
||||||
|
#yaserde_derive = { git = "https://git.nationtech.io/NationTech/yaserde" }
|
||||||
|
yaserde = { path = "../../../../github/yaserde/yaserde" }
|
||||||
|
yaserde_derive = { path = "../../../../github/yaserde/yaserde_derive" }
|
||||||
|
xml-rs = "0.8"
|
||||||
|
thiserror = "1.0"
|
||||||
|
async-trait = { workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
pretty_assertions = "1.4.1"
|
||||||
116
harmony-rs/opnsense-config-xml/src/data/dhcpd.rs
Normal file
116
harmony-rs/opnsense-config-xml/src/data/dhcpd.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
use yaserde_derive::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
use crate::xml_utils::MaybeString;
|
||||||
|
|
||||||
|
use super::opnsense::{NumberOption, Range, StaticMap};
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
#[yaserde(rename = "dhcpd")]
|
||||||
|
pub struct Dhcpd {
|
||||||
|
#[yaserde(rename = "lan")]
|
||||||
|
pub lan: DhcpInterface,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
pub struct DhcpInterface {
|
||||||
|
pub enable: i32,
|
||||||
|
pub gateway: String,
|
||||||
|
pub domain: String,
|
||||||
|
#[yaserde(rename = "ddnsdomainalgorithm")]
|
||||||
|
pub ddns_domain_algorithm: String,
|
||||||
|
#[yaserde(rename = "numberoptions")]
|
||||||
|
pub number_options: Vec<NumberOption>,
|
||||||
|
#[yaserde(rename = "range")]
|
||||||
|
pub range: Range,
|
||||||
|
pub winsserver: MaybeString,
|
||||||
|
pub dnsserver: MaybeString,
|
||||||
|
pub ntpserver: MaybeString,
|
||||||
|
#[yaserde(rename = "staticmap")]
|
||||||
|
pub staticmaps: Vec<StaticMap>,
|
||||||
|
pub pool: MaybeString,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
pub struct DhcpRange {
|
||||||
|
#[yaserde(rename = "from")]
|
||||||
|
pub from: String,
|
||||||
|
#[yaserde(rename = "to")]
|
||||||
|
pub to: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
|
use crate::xml_utils::to_xml_str;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dhcpd_should_deserialize_serialize_identical() {
|
||||||
|
let dhcpd: Dhcpd =
|
||||||
|
yaserde::de::from_str(SERIALIZED_DHCPD).expect("Deserialize Dhcpd failed");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
to_xml_str(&dhcpd).expect("Serialize Dhcpd failed"),
|
||||||
|
SERIALIZED_DHCPD
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SERIALIZED_DHCPD: &str = "<?xml version=\"1.0\"?>
|
||||||
|
<dhcpd>
|
||||||
|
<lan>
|
||||||
|
<enable>1</enable>
|
||||||
|
<gateway>192.168.20.1</gateway>
|
||||||
|
<domain>somedomain.yourlocal.mcd</domain>
|
||||||
|
<ddnsdomainalgorithm>hmac-md5</ddnsdomainalgorithm>
|
||||||
|
<numberoptions>
|
||||||
|
<item/>
|
||||||
|
</numberoptions>
|
||||||
|
<range>
|
||||||
|
<from>192.168.20.50</from>
|
||||||
|
<to>192.168.20.200</to>
|
||||||
|
</range>
|
||||||
|
<winsserver/>
|
||||||
|
<dnsserver>192.168.20.1</dnsserver>
|
||||||
|
<ntpserver/>
|
||||||
|
<staticmap>
|
||||||
|
<mac>55:55:55:55:55:1c</mac>
|
||||||
|
<ipaddr>192.168.20.160</ipaddr>
|
||||||
|
<hostname>somehost983</hostname>
|
||||||
|
<descr>someservire8</descr>
|
||||||
|
<winsserver/>
|
||||||
|
<dnsserver/>
|
||||||
|
<ntpserver/>
|
||||||
|
</staticmap>
|
||||||
|
<staticmap>
|
||||||
|
<mac>55:55:55:55:55:1c</mac>
|
||||||
|
<ipaddr>192.168.20.155</ipaddr>
|
||||||
|
<hostname>somehost893</hostname>
|
||||||
|
<winsserver/>
|
||||||
|
<dnsserver/>
|
||||||
|
<ntpserver/>
|
||||||
|
</staticmap>
|
||||||
|
<staticmap>
|
||||||
|
<mac>55:55:55:55:55:1c</mac>
|
||||||
|
<ipaddr>192.168.20.165</ipaddr>
|
||||||
|
<hostname>somehost893</hostname>
|
||||||
|
<descr/>
|
||||||
|
<winsserver/>
|
||||||
|
<dnsserver/>
|
||||||
|
<ntpserver/>
|
||||||
|
</staticmap>
|
||||||
|
<staticmap>
|
||||||
|
<mac>55:55:55:55:55:1c</mac>
|
||||||
|
<ipaddr>192.168.20.50</ipaddr>
|
||||||
|
<hostname>hostswitch2</hostname>
|
||||||
|
<descr>switch-2 (bottom)</descr>
|
||||||
|
<winsserver/>
|
||||||
|
<dnsserver/>
|
||||||
|
<ntpserver/>
|
||||||
|
</staticmap>
|
||||||
|
<pool/>
|
||||||
|
</lan>
|
||||||
|
</dhcpd>\n";
|
||||||
|
}
|
||||||
229
harmony-rs/opnsense-config-xml/src/data/interfaces.rs
Normal file
229
harmony-rs/opnsense-config-xml/src/data/interfaces.rs
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
use xml::reader::XmlEvent;
|
||||||
|
use yaserde::{YaDeserialize as YaDeserializeTrait, YaSerialize as YaSerializeTrait};
|
||||||
|
use yaserde_derive::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::xml_utils::MaybeString;
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
pub struct Interfaces {
|
||||||
|
pub interfaces: HashMap<String, Interface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
|
pub struct Interface {
|
||||||
|
#[yaserde(rename = "if")]
|
||||||
|
pub physical_interface_name: String,
|
||||||
|
pub descr: String,
|
||||||
|
pub enable: MaybeString,
|
||||||
|
#[yaserde(rename = "spoofmac")]
|
||||||
|
pub spoof_mac: Option<MaybeString>,
|
||||||
|
pub internal_dynamic: Option<MaybeString>,
|
||||||
|
pub ipaddr: Option<MaybeString>,
|
||||||
|
#[yaserde(rename = "blockpriv")]
|
||||||
|
pub block_priv: Option<MaybeString>,
|
||||||
|
#[yaserde(rename = "blockbogons")]
|
||||||
|
pub block_bogons: Option<MaybeString>,
|
||||||
|
pub lock: Option<MaybeString>,
|
||||||
|
#[yaserde(rename = "type")]
|
||||||
|
pub r#type: Option<MaybeString>,
|
||||||
|
#[yaserde(rename = "virtual")]
|
||||||
|
pub r#virtual: Option<MaybeString>,
|
||||||
|
pub subnet: Option<MaybeString>,
|
||||||
|
pub networks: Option<MaybeString>,
|
||||||
|
pub subnetv6: Option<MaybeString>,
|
||||||
|
pub ipaddrv6: Option<MaybeString>,
|
||||||
|
#[yaserde(rename = "track6-interface")]
|
||||||
|
pub track6_interface: Option<MaybeString>,
|
||||||
|
#[yaserde(rename = "track6-prefix-id")]
|
||||||
|
pub track6_prefix_id: Option<MaybeString>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MyDeserialize : YaDeserializeTrait {}
|
||||||
|
pub trait MySerialize : YaSerializeTrait {}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_deserialize_interfaces() {
|
||||||
|
let interfaces = yaserde::de::from_str::<Interfaces>(FULL_INTERFACES_XML).unwrap();
|
||||||
|
assert_eq!(interfaces.interfaces.len(), 6)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const FULL_INTERFACES_XML: &str = "<interfaces>
|
||||||
|
<wan>
|
||||||
|
<if>pppoe0</if>
|
||||||
|
<descr>WAN</descr>
|
||||||
|
<enable>1</enable>
|
||||||
|
<lock>1</lock>
|
||||||
|
<spoofmac/>
|
||||||
|
<blockpriv>1</blockpriv>
|
||||||
|
<blockbogons>1</blockbogons>
|
||||||
|
<ipaddr>pppoe</ipaddr>
|
||||||
|
</wan>
|
||||||
|
<lan>
|
||||||
|
<if>em1</if>
|
||||||
|
<descr>LAN</descr>
|
||||||
|
<enable>1</enable>
|
||||||
|
<spoofmac/>
|
||||||
|
<ipaddr>192.168.20.1</ipaddr>
|
||||||
|
<subnet>24</subnet>
|
||||||
|
<ipaddrv6>track6</ipaddrv6>
|
||||||
|
<track6-interface/>
|
||||||
|
<track6-prefix-id>0</track6-prefix-id>
|
||||||
|
</lan>
|
||||||
|
<lo0>
|
||||||
|
<internal_dynamic>1</internal_dynamic>
|
||||||
|
<descr>Loopback</descr>
|
||||||
|
<enable>1</enable>
|
||||||
|
<if>lo0</if>
|
||||||
|
<ipaddr>127.0.0.1</ipaddr>
|
||||||
|
<ipaddrv6>::1</ipaddrv6>
|
||||||
|
<subnet>8</subnet>
|
||||||
|
<subnetv6>128</subnetv6>
|
||||||
|
<type>none</type>
|
||||||
|
<virtual>1</virtual>
|
||||||
|
</lo0>
|
||||||
|
<opt1>
|
||||||
|
<if>em5</if>
|
||||||
|
<descr>backup_sync</descr>
|
||||||
|
<enable>1</enable>
|
||||||
|
<lock>1</lock>
|
||||||
|
<spoofmac/>
|
||||||
|
<ipaddr>10.10.5.1</ipaddr>
|
||||||
|
<subnet>24</subnet>
|
||||||
|
</opt1>
|
||||||
|
<wireguard>
|
||||||
|
<internal_dynamic>1</internal_dynamic>
|
||||||
|
<descr>WireGuard (Group)</descr>
|
||||||
|
<if>wireguard</if>
|
||||||
|
<virtual>1</virtual>
|
||||||
|
<enable>1</enable>
|
||||||
|
<type>group</type>
|
||||||
|
<networks/>
|
||||||
|
</wireguard>
|
||||||
|
<openvpn>
|
||||||
|
<internal_dynamic>1</internal_dynamic>
|
||||||
|
<enable>1</enable>
|
||||||
|
<if>openvpn</if>
|
||||||
|
<descr>OpenVPN</descr>
|
||||||
|
<type>group</type>
|
||||||
|
<virtual>1</virtual>
|
||||||
|
<networks/>
|
||||||
|
</openvpn>
|
||||||
|
</interfaces>";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// impl YaSerializeTrait for Interfaces {
|
||||||
|
// fn serialize<W: std::io::Write>(
|
||||||
|
// &self,
|
||||||
|
// writer: &mut yaserde::ser::Serializer<W>,
|
||||||
|
// ) -> Result<(), String> {
|
||||||
|
// writer.write("Interfaces serializer TODO").map_err(|e| e.to_string())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn serialize_attributes(
|
||||||
|
// &self,
|
||||||
|
// attributes: Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
// namespace: xml::namespace::Namespace,
|
||||||
|
// ) -> Result<
|
||||||
|
// (
|
||||||
|
// Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
// xml::namespace::Namespace,
|
||||||
|
// ),
|
||||||
|
// String,
|
||||||
|
// > {
|
||||||
|
// todo!()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// impl YaDeserializeTrait for Interfaces {
|
||||||
|
// fn deserialize<R: std::io::Read>(
|
||||||
|
// reader: &mut yaserde::de::Deserializer<R>,
|
||||||
|
// ) -> Result<Self, String> {
|
||||||
|
// let mut interfaces = Interfaces::default();
|
||||||
|
// let mut current_interface_name = String::new();
|
||||||
|
// let mut current_interface = Interface::default();
|
||||||
|
//
|
||||||
|
// let mut event = reader.next_event()?;
|
||||||
|
// loop {
|
||||||
|
// match event {
|
||||||
|
// xml::reader::XmlEvent::EndElement { name } => {
|
||||||
|
// println!(
|
||||||
|
// "Handling EndElement {}, current_interface_name: {}",
|
||||||
|
// name.local_name, current_interface_name
|
||||||
|
// );
|
||||||
|
// println!("Peeking after EndElement {:?}", reader.peek()?);
|
||||||
|
// if name.local_name == "interfaces" {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// todo!("Should not hit here");
|
||||||
|
// }
|
||||||
|
// xml::reader::XmlEvent::StartElement { ref name, .. } => {
|
||||||
|
// println!("Got start Element {:?}", name);
|
||||||
|
// current_interface_name = name.local_name.clone();
|
||||||
|
// println!("About to deserialize interface from name {:?}", name);
|
||||||
|
// // TODO store names
|
||||||
|
// 'inner_iface: loop {
|
||||||
|
// let peek = reader.peek()?;
|
||||||
|
// println!("Peeking before forcing next event {:?}", peek);
|
||||||
|
//
|
||||||
|
// if let XmlEvent::EndElement { name } = peek {
|
||||||
|
// // TODO save the interface name and struct in the hashmap
|
||||||
|
// println!("Forcing next_event");
|
||||||
|
// reader.next_event()?;
|
||||||
|
//
|
||||||
|
// let peek = reader.peek()?;
|
||||||
|
// println!("Peeking after next event deserializing {:?}", peek);
|
||||||
|
// if let XmlEvent::EndElement { name } = peek {
|
||||||
|
// println!("Got two EndElement in a row, breaking out of loop");
|
||||||
|
// break 'inner_iface;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// println!("Peeking before deserializing {:?}", reader.peek()?);
|
||||||
|
// let interface = <Interface as yaserde::YaDeserialize>::deserialize(reader)?;
|
||||||
|
// println!("Interface deserialized {:?}", interface);
|
||||||
|
// println!("Peeking after deserializing {:?}", reader.peek()?);
|
||||||
|
// }
|
||||||
|
// println!(
|
||||||
|
// "Done with inner interface, loop completed {:?}",
|
||||||
|
// reader.peek()?
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// xml::reader::XmlEvent::EndDocument => break,
|
||||||
|
// _ => {
|
||||||
|
// return Err(
|
||||||
|
// "This Interfaces Deserializer does not support all XmlEvent types".into(),
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// let peek = reader.peek()?;
|
||||||
|
//
|
||||||
|
// let read_next = true;
|
||||||
|
// if let XmlEvent::EndElement { name } = peek {
|
||||||
|
// if name.local_name == "interfaces" {
|
||||||
|
// println!("Got endElement interfaces, not reading next event");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if read_next {
|
||||||
|
// event = reader.next_event()?;
|
||||||
|
// }
|
||||||
|
// println!("Outer loop got event {:?}", event);
|
||||||
|
// println!("Outer loop got peek {:?}", reader.peek()?);
|
||||||
|
// }
|
||||||
|
// println!("Done with interfaces {:?}", interfaces);
|
||||||
|
// println!("reader peeking shows {:?}", reader.peek());
|
||||||
|
//
|
||||||
|
// Ok(interfaces)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
6
harmony-rs/opnsense-config-xml/src/data/mod.rs
Normal file
6
harmony-rs/opnsense-config-xml/src/data/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mod opnsense;
|
||||||
|
mod interfaces;
|
||||||
|
mod dhcpd;
|
||||||
|
pub use opnsense::*;
|
||||||
|
pub use interfaces::*;
|
||||||
|
pub use dhcpd::*;
|
||||||
@ -1,7 +1,24 @@
|
|||||||
use super::dhcp::Dhcpd;
|
use crate::data::dhcpd::Dhcpd;
|
||||||
use crate::infra::{generic_xml::RawXml, maybe_string::MaybeString};
|
use crate::xml_utils::{MaybeString, RawXml};
|
||||||
|
use log::error;
|
||||||
use yaserde_derive::{YaDeserialize, YaSerialize};
|
use yaserde_derive::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
impl From<String> for OPNsense {
|
||||||
|
fn from(content: String) -> Self {
|
||||||
|
yaserde::de::from_str(&content)
|
||||||
|
.map_err(|e| error!("{}", e.to_string()))
|
||||||
|
.expect("OPNSense received invalid string, should be full XML")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OPNsense {
|
||||||
|
pub fn to_xml(&self) -> String {
|
||||||
|
yaserde::ser::to_string(self)
|
||||||
|
.map_err(|e| error!("{}", e.to_string()))
|
||||||
|
.expect("OPNSense could not serialize to XML")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
#[yaserde(rename = "opnsense")]
|
#[yaserde(rename = "opnsense")]
|
||||||
pub struct OPNsense {
|
pub struct OPNsense {
|
||||||
@ -19,7 +36,7 @@ pub struct OPNsense {
|
|||||||
pub widgets: Widgets,
|
pub widgets: Widgets,
|
||||||
pub revision: Revision,
|
pub revision: Revision,
|
||||||
#[yaserde(rename = "OPNsense")]
|
#[yaserde(rename = "OPNsense")]
|
||||||
pub opnsense: OPNsenseConfig,
|
pub opnsense: OPNsenseXmlSection,
|
||||||
pub staticroutes: StaticRoutes,
|
pub staticroutes: StaticRoutes,
|
||||||
pub ca: MaybeString,
|
pub ca: MaybeString,
|
||||||
pub gateways: Gateways,
|
pub gateways: Gateways,
|
||||||
@ -279,42 +296,6 @@ pub struct WebGui {
|
|||||||
pub compression: MaybeString,
|
pub compression: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug)]
|
|
||||||
pub struct Interfaces {
|
|
||||||
pub interfaces: HashMap<String, Interface>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
|
||||||
pub struct Interface {
|
|
||||||
#[yaserde(rename = "if")]
|
|
||||||
pub physical_interface_name: String,
|
|
||||||
pub descr: String,
|
|
||||||
pub enable: u8,
|
|
||||||
#[yaserde(rename = "spoofmac")]
|
|
||||||
pub spoof_mac: MaybeString,
|
|
||||||
pub internal_dynamic: Option<u8>,
|
|
||||||
pub ipaddr: MaybeString,
|
|
||||||
#[yaserde(rename = "blockpriv")]
|
|
||||||
pub block_priv: Option<u8>,
|
|
||||||
#[yaserde(rename = "blockbogons")]
|
|
||||||
pub block_bogons: Option<u8>,
|
|
||||||
pub lock: Option<u8>,
|
|
||||||
#[yaserde(rename = "type")]
|
|
||||||
pub r#type: MaybeString,
|
|
||||||
#[yaserde(rename = "virtual")]
|
|
||||||
pub r#virtual: MaybeString,
|
|
||||||
pub subnet: MaybeString,
|
|
||||||
pub networks: Option<u8>,
|
|
||||||
pub subnetv6: MaybeString,
|
|
||||||
pub ipaddrv6: MaybeString,
|
|
||||||
#[yaserde(rename = "track6-interface")]
|
|
||||||
pub track6_interface: MaybeString,
|
|
||||||
#[yaserde(rename = "track6-prefix-id")]
|
|
||||||
pub track6_prefix_id: MaybeString,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct NumberOption {
|
pub struct NumberOption {
|
||||||
item: MaybeString,
|
item: MaybeString,
|
||||||
@ -406,7 +387,7 @@ pub struct Created {
|
|||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
#[yaserde(rename = "OPNsense")]
|
#[yaserde(rename = "OPNsense")]
|
||||||
pub struct OPNsenseConfig {
|
pub struct OPNsenseXmlSection {
|
||||||
pub captiveportal: Option<CaptivePortal>,
|
pub captiveportal: Option<CaptivePortal>,
|
||||||
pub cron: Option<Cron>,
|
pub cron: Option<Cron>,
|
||||||
#[yaserde(rename = "Netflow")]
|
#[yaserde(rename = "Netflow")]
|
||||||
@ -463,33 +444,41 @@ pub struct IDSGeneral {
|
|||||||
promisc: Option<u8>,
|
promisc: Option<u8>,
|
||||||
interfaces: String,
|
interfaces: String,
|
||||||
homenet: String,
|
homenet: String,
|
||||||
defaultPacketSize: MaybeString,
|
#[yaserde(rename = "defaultPacketSize")]
|
||||||
UpdateCron: MaybeString,
|
default_packet_size: MaybeString,
|
||||||
AlertLogrotate: String,
|
#[yaserde(rename = "UpdateCron")]
|
||||||
AlertSaveLogs: u8,
|
update_cron: MaybeString,
|
||||||
MPMAlgo: String,
|
#[yaserde(rename = "AlertLogrotate")]
|
||||||
|
alert_logrotate: String,
|
||||||
|
#[yaserde(rename = "AlertSaveLogs")]
|
||||||
|
alert_save_logs: u8,
|
||||||
|
#[yaserde(rename = "MPMAlgo")]
|
||||||
|
mpm_algo: String,
|
||||||
detect: Detect,
|
detect: Detect,
|
||||||
syslog: Option<u8>,
|
syslog: Option<u8>,
|
||||||
syslog_eve: Option<u8>,
|
syslog_eve: Option<u8>,
|
||||||
LogPayload: Option<u8>,
|
#[yaserde(rename = "LogPayload")]
|
||||||
|
log_payload: Option<u8>,
|
||||||
verbosity: MaybeString,
|
verbosity: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||||
pub struct Detect {
|
pub struct Detect {
|
||||||
Profile: String,
|
#[yaserde(rename = "Profile")]
|
||||||
|
profile: String,
|
||||||
toclient_groups: MaybeString,
|
toclient_groups: MaybeString,
|
||||||
toserver_groups: MaybeString,
|
toserver_groups: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||||
#[yaserde(rename = "IPsec")]
|
|
||||||
pub struct IPsec {
|
pub struct IPsec {
|
||||||
#[yaserde(attribute)]
|
#[yaserde(attribute)]
|
||||||
version: String,
|
version: String,
|
||||||
general: GeneralIpsec,
|
general: GeneralIpsec,
|
||||||
keyPairs: MaybeString,
|
#[yaserde(rename = "keyPairs")]
|
||||||
preSharedKeys: MaybeString,
|
key_pairs: MaybeString,
|
||||||
|
#[yaserde(rename = "preSharedKeys")]
|
||||||
|
pre_shared_keys: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||||
@ -891,10 +880,14 @@ pub struct LocalCache {
|
|||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Traffic {
|
pub struct Traffic {
|
||||||
pub enabled: i32,
|
pub enabled: i32,
|
||||||
pub maxDownloadSize: i32,
|
#[yaserde(rename = "maxDownloadSize")]
|
||||||
pub maxUploadSize: i32,
|
pub max_download_size: i32,
|
||||||
pub OverallBandwidthTrotteling: i32,
|
#[yaserde(rename = "maxUploadSize")]
|
||||||
pub perHostTrotteling: i32,
|
pub max_upload_size: i32,
|
||||||
|
#[yaserde(rename = "OverallBandwidthTrotteling")]
|
||||||
|
pub overall_bandwidth_trotteling: i32,
|
||||||
|
#[yaserde(rename = "perHostTrotteling")]
|
||||||
|
pub per_host_trotteling: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
@ -923,11 +916,16 @@ pub struct Forward {
|
|||||||
pub snmp_enable: i32,
|
pub snmp_enable: i32,
|
||||||
pub snmp_port: i32,
|
pub snmp_port: i32,
|
||||||
pub snmp_password: String,
|
pub snmp_password: String,
|
||||||
pub ftpInterfaces: MaybeString,
|
#[yaserde(rename = "ftpInterfaces")]
|
||||||
pub ftpPort: i32,
|
pub ftp_interfaces: MaybeString,
|
||||||
pub ftpTransparentMode: i32,
|
#[yaserde(rename = "ftpPort")]
|
||||||
pub addACLforInterfaceSubnets: i32,
|
pub ftp_port: i32,
|
||||||
pub transparentMode: i32,
|
#[yaserde(rename = "ftpTransparentMode")]
|
||||||
|
pub ftp_transparent_mode: i32,
|
||||||
|
#[yaserde(rename = "addACLforInterfaceSubnets")]
|
||||||
|
pub add_acl_for_interface_subnets: i32,
|
||||||
|
#[yaserde(rename = "transparentMode")]
|
||||||
|
pub transparent_mode: i32,
|
||||||
pub acl: Acl,
|
pub acl: Acl,
|
||||||
pub icap: Icap,
|
pub icap: Icap,
|
||||||
pub authentication: Authentication,
|
pub authentication: Authentication,
|
||||||
@ -935,47 +933,66 @@ pub struct Forward {
|
|||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Acl {
|
pub struct Acl {
|
||||||
pub allowedSubnets: MaybeString,
|
#[yaserde(rename = "allowedSubnets")]
|
||||||
|
pub allowed_subnets: MaybeString,
|
||||||
pub unrestricted: MaybeString,
|
pub unrestricted: MaybeString,
|
||||||
pub bannedHosts: MaybeString,
|
#[yaserde(rename = "bannedHosts")]
|
||||||
pub whiteList: MaybeString,
|
pub banned_hosts: MaybeString,
|
||||||
pub blackList: MaybeString,
|
#[yaserde(rename = "whiteList")]
|
||||||
|
pub white_list: MaybeString,
|
||||||
|
#[yaserde(rename = "blackList")]
|
||||||
|
pub black_list: MaybeString,
|
||||||
pub browser: MaybeString,
|
pub browser: MaybeString,
|
||||||
pub mimeType: MaybeString,
|
#[yaserde(rename = "mimeType")]
|
||||||
pub googleapps: MaybeString,
|
pub mime_type: MaybeString,
|
||||||
|
pub google_apps: MaybeString,
|
||||||
pub youtube: MaybeString,
|
pub youtube: MaybeString,
|
||||||
pub safePorts: String,
|
#[yaserde(rename = "safePorts")]
|
||||||
pub sslPorts: String,
|
pub safe_ports: String,
|
||||||
pub remoteACLs: RemoteAcls,
|
#[yaserde(rename = "sslPorts")]
|
||||||
|
pub ssl_ports: String,
|
||||||
|
#[yaserde(rename = "remoteACLs")]
|
||||||
|
pub remote_acls: RemoteAcls,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct RemoteAcls {
|
pub struct RemoteAcls {
|
||||||
pub blacklists: MaybeString,
|
pub blacklists: MaybeString,
|
||||||
pub UpdateCron: MaybeString,
|
#[yaserde(rename = "UpdateCron")]
|
||||||
|
pub update_cron: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Icap {
|
pub struct Icap {
|
||||||
pub enable: i32,
|
pub enable: i32,
|
||||||
pub RequestURL: String,
|
#[yaserde(rename = "RequestURL")]
|
||||||
pub ResponseURL: String,
|
pub request_url: String,
|
||||||
pub SendClientIP: i32,
|
#[yaserde(rename = "ResponseURL")]
|
||||||
pub SendUsername: i32,
|
pub response_url: String,
|
||||||
pub EncodeUsername: i32,
|
#[yaserde(rename = "SendClientIP")]
|
||||||
pub UsernameHeader: String,
|
pub send_client_ip: i32,
|
||||||
pub EnablePreview: i32,
|
#[yaserde(rename = "SendUsername")]
|
||||||
pub PreviewSize: i32,
|
pub send_username: i32,
|
||||||
pub OptionsTTL: i32,
|
#[yaserde(rename = "EncodeUsername")]
|
||||||
|
pub encode_username: i32,
|
||||||
|
#[yaserde(rename = "UsernameHeader")]
|
||||||
|
pub username_header: String,
|
||||||
|
#[yaserde(rename = "EnablePreview")]
|
||||||
|
pub enable_preview: i32,
|
||||||
|
#[yaserde(rename = "PreviewSize")]
|
||||||
|
pub preview_size: i32,
|
||||||
|
#[yaserde(rename = "OptionsTTL")]
|
||||||
|
pub options_ttl: i32,
|
||||||
pub exclude: MaybeString,
|
pub exclude: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Authentication {
|
pub struct Authentication {
|
||||||
pub method: MaybeString,
|
pub method: MaybeString,
|
||||||
pub authEnforceGroup: MaybeString,
|
#[yaserde(rename = "authEnforceGroup")]
|
||||||
|
pub auth_enforce_group: MaybeString,
|
||||||
pub realm: String,
|
pub realm: String,
|
||||||
pub credentialsttl: i32,
|
pub credentialsttl: i32, // This field is already in snake_case
|
||||||
pub children: i32,
|
pub children: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1263,8 +1280,11 @@ pub struct Account {
|
|||||||
pub struct ConfigOpenVPN {
|
pub struct ConfigOpenVPN {
|
||||||
#[yaserde(attribute)]
|
#[yaserde(attribute)]
|
||||||
pub version: String,
|
pub version: String,
|
||||||
|
#[yaserde(rename = "Overwrites")]
|
||||||
pub Overwrites: MaybeString,
|
pub Overwrites: MaybeString,
|
||||||
|
#[yaserde(rename = "Instances")]
|
||||||
pub Instances: MaybeString,
|
pub Instances: MaybeString,
|
||||||
|
#[yaserde(rename = "StaticKeys")]
|
||||||
pub StaticKeys: MaybeString,
|
pub StaticKeys: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1327,12 +1347,18 @@ pub struct CronJobs {
|
|||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct HaProxyGeneral {
|
pub struct HaProxyGeneral {
|
||||||
pub enabled: i32,
|
pub enabled: i32,
|
||||||
pub gracefulStop: i32,
|
#[yaserde(rename = "gracefulStop")]
|
||||||
pub hardStopAfter: String,
|
pub graceful_stop: i32,
|
||||||
pub closeSpreadTime: MaybeString,
|
#[yaserde(rename = "hardStopAfter")]
|
||||||
pub seamlessReload: i32,
|
pub hard_stop_after: String,
|
||||||
pub storeOcsp: i32,
|
#[yaserde(rename = "closeSpreadTime")]
|
||||||
pub showIntro: i32,
|
pub close_spread_time: MaybeString,
|
||||||
|
#[yaserde(rename = "seamlessReload")]
|
||||||
|
pub seamless_reload: i32,
|
||||||
|
#[yaserde(rename = "storeOcsp")]
|
||||||
|
pub store_ocsp: i32,
|
||||||
|
#[yaserde(rename = "showIntro")]
|
||||||
|
pub show_intro: i32,
|
||||||
pub peers: Peers,
|
pub peers: Peers,
|
||||||
pub tuning: Tuning,
|
pub tuning: Tuning,
|
||||||
pub defaults: HaProxyDefaults,
|
pub defaults: HaProxyDefaults,
|
||||||
@ -1355,36 +1381,56 @@ pub struct Peers {
|
|||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Tuning {
|
pub struct Tuning {
|
||||||
pub root: i32,
|
pub root: i32,
|
||||||
pub maxConnections: MaybeString,
|
#[yaserde(rename = "maxConnections")]
|
||||||
|
pub max_connections: MaybeString,
|
||||||
pub nbthread: i32,
|
pub nbthread: i32,
|
||||||
pub sslServerVerify: String,
|
#[yaserde(rename = "sslServerVerify")]
|
||||||
pub maxDHSize: i32,
|
pub ssl_server_verify: String,
|
||||||
pub bufferSize: i32,
|
#[yaserde(rename = "maxDHSize")]
|
||||||
pub spreadChecks: i32,
|
pub max_dh_size: i32,
|
||||||
pub bogusProxyEnabled: i32,
|
#[yaserde(rename = "bufferSize")]
|
||||||
pub luaMaxMem: i32,
|
pub buffer_size: i32,
|
||||||
pub customOptions: MaybeString,
|
#[yaserde(rename = "spreadChecks")]
|
||||||
|
pub spread_checks: i32,
|
||||||
|
#[yaserde(rename = "bogusProxyEnabled")]
|
||||||
|
pub bogus_proxy_enabled: i32,
|
||||||
|
#[yaserde(rename = "luaMaxMem")]
|
||||||
|
pub lua_max_mem: i32,
|
||||||
|
#[yaserde(rename = "customOptions")]
|
||||||
|
pub custom_options: MaybeString,
|
||||||
#[yaserde(rename = "ssl_defaultsEnabled")]
|
#[yaserde(rename = "ssl_defaultsEnabled")]
|
||||||
pub ssl_defaults_enabled: i32,
|
pub ssl_defaults_enabled: i32,
|
||||||
pub ssl_bindOptions: String,
|
#[yaserde(rename = "ssl_bindOptions")]
|
||||||
pub ssl_minVersion: String,
|
pub ssl_bind_options: String,
|
||||||
pub ssl_maxVersion: MaybeString,
|
#[yaserde(rename = "ssl_minVersion")]
|
||||||
pub ssl_cipherList: String,
|
pub ssl_min_version: String,
|
||||||
pub ssl_cipherSuites: String,
|
#[yaserde(rename = "ssl_maxVersion")]
|
||||||
|
pub ssl_max_version: MaybeString,
|
||||||
|
#[yaserde(rename = "ssl_cipherList")]
|
||||||
|
pub ssl_cipher_list: String,
|
||||||
|
#[yaserde(rename = "ssl_cipherSuites")]
|
||||||
|
pub ssl_cipher_suites: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct HaProxyDefaults {
|
pub struct HaProxyDefaults {
|
||||||
pub maxConnections: MaybeString,
|
#[yaserde(rename = "maxConnections")]
|
||||||
pub maxConnectionsServers: MaybeString,
|
pub max_connections: MaybeString,
|
||||||
pub timeoutClient: String,
|
#[yaserde(rename = "maxConnectionsServers")]
|
||||||
pub timeoutConnect: String,
|
pub max_connections_servers: MaybeString,
|
||||||
pub timeoutCheck: MaybeString,
|
#[yaserde(rename = "timeoutClient")]
|
||||||
pub timeoutServer: String,
|
pub timeout_client: String,
|
||||||
|
#[yaserde(rename = "timeoutConnect")]
|
||||||
|
pub timeout_connect: String,
|
||||||
|
#[yaserde(rename = "timeoutCheck")]
|
||||||
|
pub timeout_check: MaybeString,
|
||||||
|
#[yaserde(rename = "timeoutServer")]
|
||||||
|
pub timeout_server: String,
|
||||||
pub retries: i32,
|
pub retries: i32,
|
||||||
pub redispatch: String,
|
pub redispatch: String,
|
||||||
pub init_addr: String,
|
pub init_addr: String,
|
||||||
pub customOptions: MaybeString,
|
#[yaserde(rename = "customOptions")]
|
||||||
|
pub custom_options: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
@ -1399,13 +1445,20 @@ pub struct HaProxyLogging {
|
|||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
pub enabled: i32,
|
pub enabled: i32,
|
||||||
pub port: i32,
|
pub port: i32,
|
||||||
pub remoteEnabled: i32,
|
#[yaserde(rename = "remoteEnabled")]
|
||||||
pub remoteBind: MaybeString,
|
pub remote_enabled: i32,
|
||||||
pub authEnabled: i32,
|
#[yaserde(rename = "remoteBind")]
|
||||||
|
pub remote_bind: MaybeString,
|
||||||
|
#[yaserde(rename = "authEnabled")]
|
||||||
|
pub auth_enabled: i32,
|
||||||
|
#[yaserde(rename = "users")]
|
||||||
pub users: MaybeString,
|
pub users: MaybeString,
|
||||||
pub allowedUsers: MaybeString,
|
#[yaserde(rename = "allowedUsers")]
|
||||||
pub allowedGroups: MaybeString,
|
pub allowed_users: MaybeString,
|
||||||
pub customOptions: MaybeString,
|
#[yaserde(rename = "allowedGroups")]
|
||||||
|
pub allowed_groups: MaybeString,
|
||||||
|
#[yaserde(rename = "customOptions")]
|
||||||
|
pub custom_options: MaybeString,
|
||||||
pub prometheus_enabled: i32,
|
pub prometheus_enabled: i32,
|
||||||
pub prometheus_bind: String,
|
pub prometheus_bind: String,
|
||||||
pub prometheus_path: String,
|
pub prometheus_path: String,
|
||||||
@ -1414,16 +1467,20 @@ pub struct Stats {
|
|||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct HaProxyCache {
|
pub struct HaProxyCache {
|
||||||
pub enabled: i32,
|
pub enabled: i32,
|
||||||
pub totalMaxSize: i32,
|
#[yaserde(rename = "totalMaxSize")]
|
||||||
pub maxAge: i32,
|
pub total_max_size: i32,
|
||||||
pub maxObjectSize: MaybeString,
|
#[yaserde(rename = "maxAge")]
|
||||||
pub processVary: i32,
|
pub max_age: i32,
|
||||||
pub maxSecondaryEntries: i32,
|
#[yaserde(rename = "maxObjectSize")]
|
||||||
|
pub max_object_size: MaybeString,
|
||||||
|
#[yaserde(rename = "processVary")]
|
||||||
|
pub process_vary: i32,
|
||||||
|
#[yaserde(rename = "maxSecondaryEntries")]
|
||||||
|
pub max_secondary_entries: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct HAProxyFrontends {
|
pub struct HAProxyFrontends {
|
||||||
#[yaserde(rename = "frontend")]
|
|
||||||
pub frontend: Vec<Frontend>,
|
pub frontend: Vec<Frontend>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1436,64 +1493,108 @@ pub struct Frontend {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub bind: String,
|
pub bind: String,
|
||||||
pub bindOptions: MaybeString,
|
#[yaserde(rename = "bindOptions")]
|
||||||
|
pub bind_options: MaybeString,
|
||||||
pub mode: String,
|
pub mode: String,
|
||||||
pub defaultBackend: String,
|
#[yaserde(rename = "defaultBackend")]
|
||||||
|
pub default_backend: String,
|
||||||
pub ssl_enabled: i32,
|
pub ssl_enabled: i32,
|
||||||
pub ssl_certificates: MaybeString,
|
pub ssl_certificates: MaybeString,
|
||||||
pub ssl_default_certificate: MaybeString,
|
pub ssl_default_certificate: MaybeString,
|
||||||
pub ssl_customOptions: MaybeString,
|
#[yaserde(rename = "ssl_customOptions")]
|
||||||
pub ssl_advancedEnabled: i32,
|
pub ssl_custom_options: MaybeString,
|
||||||
pub ssl_bindOptions: String,
|
#[yaserde(rename = "ssl_advancedEnabled")]
|
||||||
pub ssl_minVersion: String,
|
pub ssl_advanced_enabled: i32,
|
||||||
pub ssl_maxVersion: MaybeString,
|
#[yaserde(rename = "ssl_bindOptions")]
|
||||||
pub ssl_cipherList: String,
|
pub ssl_bind_options: String,
|
||||||
pub ssl_cipherSuites: String,
|
#[yaserde(rename = "ssl_minVersion")]
|
||||||
pub ssl_hstsEnabled: i32,
|
pub ssl_min_version: String,
|
||||||
pub ssl_hstsIncludeSubDomains: i32,
|
#[yaserde(rename = "ssl_maxVersion")]
|
||||||
pub ssl_hstsPreload: i32,
|
pub ssl_max_version: MaybeString,
|
||||||
pub ssl_hstsMaxAge: i32,
|
#[yaserde(rename = "ssl_cipherList")]
|
||||||
pub ssl_clientAuthEnabled: i32,
|
pub ssl_cipher_list: String,
|
||||||
pub ssl_clientAuthVerify: String,
|
#[yaserde(rename = "ssl_cipherSuites")]
|
||||||
pub ssl_clientAuthCAs: MaybeString,
|
pub ssl_cipher_suites: String,
|
||||||
pub ssl_clientAuthCRLs: MaybeString,
|
#[yaserde(rename = "ssl_hstsEnabled")]
|
||||||
pub basicAuthEnabled: i32,
|
pub ssl_hsts_enabled: i32,
|
||||||
pub basicAuthUsers: MaybeString,
|
#[yaserde(rename = "ssl_hstsIncludeSubDomains")]
|
||||||
pub basicAuthGroups: MaybeString,
|
pub ssl_hsts_include_sub_domains: i32,
|
||||||
pub tuning_maxConnections: MaybeString,
|
#[yaserde(rename = "ssl_hstsPreload")]
|
||||||
pub tuning_timeoutClient: MaybeString,
|
pub ssl_hsts_preload: i32,
|
||||||
pub tuning_timeoutHttpReq: MaybeString,
|
#[yaserde(rename = "ssl_hstsMaxAge")]
|
||||||
pub tuning_timeoutHttpKeepAlive: MaybeString,
|
pub ssl_hsts_max_age: i32,
|
||||||
pub linkedCpuAffinityRules: MaybeString,
|
#[yaserde(rename = "ssl_clientAuthEnabled")]
|
||||||
|
pub ssl_client_auth_enabled: i32,
|
||||||
|
#[yaserde(rename = "ssl_clientAuthVerify")]
|
||||||
|
pub ssl_client_auth_verify: String,
|
||||||
|
#[yaserde(rename = "ssl_clientAuthCAs")]
|
||||||
|
pub ssl_client_auth_cas: MaybeString,
|
||||||
|
#[yaserde(rename = "ssl_clientAuthCRLs")]
|
||||||
|
pub ssl_client_auth_cr_ls: MaybeString,
|
||||||
|
#[yaserde(rename = "basicAuthEnabled")]
|
||||||
|
pub basic_auth_enabled: i32,
|
||||||
|
#[yaserde(rename = "basicAuthUsers")]
|
||||||
|
pub basic_auth_users: MaybeString,
|
||||||
|
#[yaserde(rename = "basicAuthGroups")]
|
||||||
|
pub basic_auth_groups: MaybeString,
|
||||||
|
#[yaserde(rename = "tuning_maxConnections")]
|
||||||
|
pub tuning_max_connections: MaybeString,
|
||||||
|
#[yaserde(rename = "tuning_timeoutClient")]
|
||||||
|
pub tuning_timeout_client: MaybeString,
|
||||||
|
#[yaserde(rename = "tuning_timeoutHttpReq")]
|
||||||
|
pub tuning_timeout_http_req: MaybeString,
|
||||||
|
#[yaserde(rename = "tuning_timeoutHttpKeepAlive")]
|
||||||
|
pub tuning_timeout_http_keep_alive: MaybeString,
|
||||||
|
#[yaserde(rename = "linkedCpuAffinityRules")]
|
||||||
|
pub linked_cpu_affinity_rules: MaybeString,
|
||||||
pub tuning_shards: MaybeString,
|
pub tuning_shards: MaybeString,
|
||||||
pub logging_dontLogNull: i32,
|
#[yaserde(rename = "logging_dontLogNull")]
|
||||||
pub logging_dontLogNormal: i32,
|
pub logging_dont_log_null: i32,
|
||||||
pub logging_logSeparateErrors: i32,
|
#[yaserde(rename = "logging_dontLogNormal")]
|
||||||
pub logging_detailedLog: i32,
|
pub logging_dont_log_normal: i32,
|
||||||
pub logging_socketStats: i32,
|
#[yaserde(rename = "logging_logSeparateErrors")]
|
||||||
|
pub logging_log_separate_errors: i32,
|
||||||
|
#[yaserde(rename = "logging_detailedLog")]
|
||||||
|
pub logging_detailed_log: i32,
|
||||||
|
#[yaserde(rename = "logging_socketStats")]
|
||||||
|
pub logging_socket_stats: i32,
|
||||||
pub stickiness_pattern: MaybeString,
|
pub stickiness_pattern: MaybeString,
|
||||||
pub stickiness_dataTypes: MaybeString,
|
#[yaserde(rename = "stickiness_dataTypes")]
|
||||||
|
pub stickiness_data_types: MaybeString,
|
||||||
pub stickiness_expire: String,
|
pub stickiness_expire: String,
|
||||||
pub stickiness_size: String,
|
pub stickiness_size: String,
|
||||||
pub stickiness_counter: i32,
|
pub stickiness_counter: i32,
|
||||||
pub stickiness_counter_key: String,
|
pub stickiness_counter_key: String,
|
||||||
pub stickiness_length: MaybeString,
|
pub stickiness_length: MaybeString,
|
||||||
pub stickiness_connRatePeriod: String,
|
#[yaserde(rename = "stickiness_connRatePeriod")]
|
||||||
pub stickiness_sessRatePeriod: String,
|
pub stickiness_conn_rate_period: String,
|
||||||
pub stickiness_httpReqRatePeriod: String,
|
#[yaserde(rename = "stickiness_sessRatePeriod")]
|
||||||
pub stickiness_httpErrRatePeriod: String,
|
pub stickiness_sess_rate_period: String,
|
||||||
pub stickiness_bytesInRatePeriod: String,
|
#[yaserde(rename = "stickiness_httpReqRatePeriod")]
|
||||||
pub stickiness_bytesOutRatePeriod: String,
|
pub stickiness_http_req_rate_period: String,
|
||||||
pub http2Enabled: i32,
|
#[yaserde(rename = "stickiness_httpErrRatePeriod")]
|
||||||
pub http2Enabled_nontls: i32,
|
pub stickiness_http_err_rate_period: String,
|
||||||
|
#[yaserde(rename = "stickiness_bytesInRatePeriod")]
|
||||||
|
pub stickiness_bytes_in_rate_period: String,
|
||||||
|
#[yaserde(rename = "stickiness_bytesOutRatePeriod")]
|
||||||
|
pub stickiness_bytes_out_rate_period: String,
|
||||||
|
#[yaserde(rename = "http2Enabled")]
|
||||||
|
pub http2_enabled: i32,
|
||||||
|
#[yaserde(rename = "http2Enabled_nontls")]
|
||||||
|
pub http2_enabled_nontls: i32,
|
||||||
pub advertised_protocols: String,
|
pub advertised_protocols: String,
|
||||||
pub forwardFor: i32,
|
#[yaserde(rename = "forwardFor")]
|
||||||
|
pub forward_for: i32,
|
||||||
pub prometheus_enabled: i32,
|
pub prometheus_enabled: i32,
|
||||||
pub prometheus_path: String,
|
pub prometheus_path: String,
|
||||||
pub connectionBehaviour: String,
|
#[yaserde(rename = "connectionBehaviour")]
|
||||||
pub customOptions: MaybeString,
|
pub connection_behaviour: String,
|
||||||
pub linkedActions: MaybeString,
|
#[yaserde(rename = "customOptions")]
|
||||||
pub linkedErrorfiles: MaybeString,
|
pub custom_options: MaybeString,
|
||||||
|
#[yaserde(rename = "linkedActions")]
|
||||||
|
pub linked_actions: MaybeString,
|
||||||
|
#[yaserde(rename = "linkedErrorfiles")]
|
||||||
|
pub linked_error_files: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
@ -1628,29 +1729,19 @@ pub struct HAProxyServers {
|
|||||||
pub struct HAProxyServer {
|
pub struct HAProxyServer {
|
||||||
#[yaserde(attribute, rename = "uuid")]
|
#[yaserde(attribute, rename = "uuid")]
|
||||||
pub uuid: String,
|
pub uuid: String,
|
||||||
#[yaserde(rename = "id")]
|
|
||||||
pub id: String,
|
pub id: String,
|
||||||
#[yaserde(rename = "enabled")]
|
|
||||||
pub enabled: u8,
|
pub enabled: u8,
|
||||||
#[yaserde(rename = "name")]
|
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[yaserde(rename = "description")]
|
|
||||||
pub description: MaybeString,
|
pub description: MaybeString,
|
||||||
#[yaserde(rename = "address")]
|
|
||||||
pub address: String,
|
pub address: String,
|
||||||
#[yaserde(rename = "port")]
|
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
#[yaserde(rename = "checkport")]
|
|
||||||
pub checkport: MaybeString,
|
pub checkport: MaybeString,
|
||||||
#[yaserde(rename = "mode")]
|
|
||||||
pub mode: String,
|
pub mode: String,
|
||||||
#[yaserde(rename = "multiplexer_protocol")]
|
|
||||||
pub multiplexer_protocol: String,
|
pub multiplexer_protocol: String,
|
||||||
#[yaserde(rename = "type")]
|
#[yaserde(rename = "type")]
|
||||||
pub server_type: String,
|
pub server_type: String,
|
||||||
#[yaserde(rename = "serviceName")]
|
#[yaserde(rename = "serviceName")]
|
||||||
pub service_name: MaybeString,
|
pub service_name: MaybeString,
|
||||||
#[yaserde(rename = "number")]
|
|
||||||
pub number: MaybeString,
|
pub number: MaybeString,
|
||||||
#[yaserde(rename = "linkedResolver")]
|
#[yaserde(rename = "linkedResolver")]
|
||||||
pub linked_resolver: MaybeString,
|
pub linked_resolver: MaybeString,
|
||||||
@ -1658,7 +1749,6 @@ pub struct HAProxyServer {
|
|||||||
pub resolver_opts: MaybeString,
|
pub resolver_opts: MaybeString,
|
||||||
#[yaserde(rename = "resolvePrefer")]
|
#[yaserde(rename = "resolvePrefer")]
|
||||||
pub resolve_prefer: MaybeString,
|
pub resolve_prefer: MaybeString,
|
||||||
#[yaserde(rename = "ssl")]
|
|
||||||
pub ssl: u8,
|
pub ssl: u8,
|
||||||
#[yaserde(rename = "sslSNI")]
|
#[yaserde(rename = "sslSNI")]
|
||||||
pub ssl_sni: MaybeString,
|
pub ssl_sni: MaybeString,
|
||||||
@ -1672,15 +1762,12 @@ pub struct HAProxyServer {
|
|||||||
pub ssl_client_certificate: MaybeString,
|
pub ssl_client_certificate: MaybeString,
|
||||||
#[yaserde(rename = "maxConnections")]
|
#[yaserde(rename = "maxConnections")]
|
||||||
pub max_connections: MaybeString,
|
pub max_connections: MaybeString,
|
||||||
#[yaserde(rename = "weight")]
|
|
||||||
pub weight: u32,
|
pub weight: u32,
|
||||||
#[yaserde(rename = "checkInterval")]
|
#[yaserde(rename = "checkInterval")]
|
||||||
pub check_interval: MaybeString,
|
pub check_interval: MaybeString,
|
||||||
#[yaserde(rename = "checkDownInterval")]
|
#[yaserde(rename = "checkDownInterval")]
|
||||||
pub check_down_interval: MaybeString,
|
pub check_down_interval: MaybeString,
|
||||||
#[yaserde(rename = "source")]
|
|
||||||
pub source: MaybeString,
|
pub source: MaybeString,
|
||||||
#[yaserde(rename = "advanced")]
|
|
||||||
pub advanced: MaybeString,
|
pub advanced: MaybeString,
|
||||||
#[yaserde(rename = "unix_socket")]
|
#[yaserde(rename = "unix_socket")]
|
||||||
pub unix_socket: MaybeString,
|
pub unix_socket: MaybeString,
|
||||||
3
harmony-rs/opnsense-config-xml/src/lib.rs
Normal file
3
harmony-rs/opnsense-config-xml/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod xml_utils;
|
||||||
|
mod data;
|
||||||
|
pub use data::*;
|
||||||
@ -118,7 +118,7 @@ impl YaSerializeTrait for RawXml {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::infra::yaserde::to_xml_str;
|
use crate::xml_utils::to_xml_str;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
6
harmony-rs/opnsense-config-xml/src/xml_utils/mod.rs
Normal file
6
harmony-rs/opnsense-config-xml/src/xml_utils/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mod generic_xml;
|
||||||
|
mod maybe_string;
|
||||||
|
mod yaserde;
|
||||||
|
pub use generic_xml::*;
|
||||||
|
pub use maybe_string::*;
|
||||||
|
pub use yaserde::*;
|
||||||
@ -1,7 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "opnsense-config"
|
name = "opnsense-config"
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0.123", features = [ "derive" ] }
|
serde = { version = "1.0.123", features = [ "derive" ] }
|
||||||
@ -9,14 +11,10 @@ log = { workspace = true }
|
|||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
russh = { workspace = true }
|
russh = { workspace = true }
|
||||||
russh-keys = { workspace = true }
|
russh-keys = { workspace = true }
|
||||||
#yaserde = { git = "https://git.nationtech.io/NationTech/yaserde" }
|
|
||||||
#yaserde_derive = { git = "https://git.nationtech.io/NationTech/yaserde" }
|
|
||||||
yaserde = { path = "../../../../github/yaserde/yaserde" }
|
|
||||||
yaserde_derive = { path = "../../../../github/yaserde/yaserde_derive" }
|
|
||||||
xml-rs = "0.8"
|
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
opnsense-config-xml = { path = "../opnsense-config-xml" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "1.4.1"
|
pretty_assertions = "1.4.1"
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::modules::opnsense::OPNsense;
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::info;
|
use log::{info, trace};
|
||||||
|
use opnsense_config_xml::OPNsense;
|
||||||
use russh::client::{Config as SshConfig, Handler};
|
use russh::client::{Config as SshConfig, Handler};
|
||||||
use russh_keys::key;
|
use russh_keys::key;
|
||||||
use std::{fs, net::Ipv4Addr, path::Path, sync::Arc};
|
use std::{fs, net::Ipv4Addr, sync::Arc};
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait ConfigRepository: std::fmt::Debug {
|
pub trait ConfigRepository: std::fmt::Debug {
|
||||||
@ -87,6 +87,7 @@ impl ConfigRepository for SshConfigRepository {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut channel = ssh.channel_open_session().await?;
|
let mut channel = ssh.channel_open_session().await?;
|
||||||
|
todo!("Backup, Validate, Reload config file");
|
||||||
|
|
||||||
let command = format!(
|
let command = format!(
|
||||||
"echo '{}' > /conf/config.xml",
|
"echo '{}' > /conf/config.xml",
|
||||||
@ -144,9 +145,9 @@ pub struct Config {
|
|||||||
impl Config {
|
impl Config {
|
||||||
pub async fn new(repository: Box<dyn ConfigRepository + Send + Sync>) -> Result<Self, Error> {
|
pub async fn new(repository: Box<dyn ConfigRepository + Send + Sync>) -> Result<Self, Error> {
|
||||||
let xml = repository.load().await?;
|
let xml = repository.load().await?;
|
||||||
info!("xml {}", xml);
|
trace!("xml {}", xml);
|
||||||
|
|
||||||
let opnsense = yaserde::de::from_str(&xml).map_err(|e| Error::Xml(e.to_string()))?;
|
let opnsense = OPNsense::from(xml);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
opnsense,
|
opnsense,
|
||||||
@ -163,15 +164,12 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save(&self) -> Result<(), Error> {
|
pub async fn save(&self) -> Result<(), Error> {
|
||||||
let xml = yaserde::ser::to_string(&self.opnsense).map_err(|e| Error::Xml(e.to_string()))?;
|
self.repository.save(&self.opnsense.to_xml()).await
|
||||||
self.repository.save(&xml).await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::infra::yaserde::to_xml_str;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
@ -191,11 +189,33 @@ mod tests {
|
|||||||
|
|
||||||
println!("Config {:?}", config);
|
println!("Config {:?}", config);
|
||||||
|
|
||||||
let serialized = to_xml_str(&config.opnsense).unwrap();
|
let serialized = config.opnsense.to_xml();
|
||||||
|
|
||||||
fs::write("/tmp/serialized.xml", &serialized).unwrap();
|
fs::write("/tmp/serialized.xml", &serialized).unwrap();
|
||||||
|
|
||||||
assert_eq!(config_file_str, serialized);
|
assert_eq!(config_file_str, serialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_add_dhcpd_static_entry() {
|
||||||
|
let mut test_file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
test_file_path.push("src/tests/data/config-full-1.xml");
|
||||||
|
|
||||||
|
let config_file_path = test_file_path.to_str().unwrap().to_string();
|
||||||
|
println!("File path {config_file_path}");
|
||||||
|
let repository = Box::new(LocalFileConfigRepository::new(config_file_path));
|
||||||
|
let config_file_str = repository.load().await.unwrap();
|
||||||
|
let mut config = Config::new(repository)
|
||||||
|
.await
|
||||||
|
.expect("Failed to load config");
|
||||||
|
|
||||||
|
println!("Config {:?}", config);
|
||||||
|
|
||||||
|
let serialized = config.opnsense.to_xml();
|
||||||
|
|
||||||
|
fs::write("/tmp/serialized.xml", &serialized).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config_file_str, serialized);
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
pub mod generic_xml;
|
|
||||||
pub mod maybe_string;
|
|
||||||
pub mod yaserde;
|
|
||||||
|
|
||||||
@ -1,7 +1,23 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod modules;
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod infra;
|
pub mod modules;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
use modules::dhcp::DhcpConfig;
|
||||||
|
use opnsense_config_xml::OPNsense;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_public_sdk() {
|
||||||
|
let mut opnsense = OPNsense::default();
|
||||||
|
let mut dhcpd = DhcpConfig::new(&mut opnsense);
|
||||||
|
dhcpd.add_static_mapping(
|
||||||
|
"test_mac",
|
||||||
|
Ipv4Addr::new(192, 168, 168, 168),
|
||||||
|
"test_hostname",
|
||||||
|
);
|
||||||
|
|
||||||
|
todo!();
|
||||||
|
// opnsense.apply_changes().await;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,111 +0,0 @@
|
|||||||
use xml::reader::XmlEvent;
|
|
||||||
use yaserde::{YaDeserialize, YaSerialize};
|
|
||||||
|
|
||||||
use crate::modules::opnsense::{Interface, Interfaces};
|
|
||||||
|
|
||||||
impl YaSerialize for Interfaces {
|
|
||||||
fn serialize<W: std::io::Write>(
|
|
||||||
&self,
|
|
||||||
writer: &mut yaserde::ser::Serializer<W>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
writer.write("Interfaces serializer TODO");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_attributes(
|
|
||||||
&self,
|
|
||||||
attributes: Vec<xml::attribute::OwnedAttribute>,
|
|
||||||
namespace: xml::namespace::Namespace,
|
|
||||||
) -> Result<
|
|
||||||
(
|
|
||||||
Vec<xml::attribute::OwnedAttribute>,
|
|
||||||
xml::namespace::Namespace,
|
|
||||||
),
|
|
||||||
String,
|
|
||||||
> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl YaDeserialize for Interfaces {
|
|
||||||
fn deserialize<R: std::io::Read>(
|
|
||||||
reader: &mut yaserde::de::Deserializer<R>,
|
|
||||||
) -> Result<Self, String> {
|
|
||||||
let mut interfaces = Interfaces::default();
|
|
||||||
let mut current_interface_name = String::new();
|
|
||||||
let mut current_interface = Interface::default();
|
|
||||||
|
|
||||||
let mut event = reader.next_event()?;
|
|
||||||
loop {
|
|
||||||
match event {
|
|
||||||
xml::reader::XmlEvent::EndElement { name } => {
|
|
||||||
println!(
|
|
||||||
"Handling EndElement {}, current_interface_name: {}",
|
|
||||||
name.local_name, current_interface_name
|
|
||||||
);
|
|
||||||
println!("Peeking after EndElement {:?}", reader.peek()?);
|
|
||||||
if name.local_name == "interfaces" {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
todo!("Should not hit here");
|
|
||||||
}
|
|
||||||
xml::reader::XmlEvent::StartElement { ref name, .. } => {
|
|
||||||
println!("Got start Element {:?}", name);
|
|
||||||
current_interface_name = name.local_name.clone();
|
|
||||||
println!("About to deserialize interface from name {:?}", name);
|
|
||||||
// TODO store names
|
|
||||||
'inner_iface: loop {
|
|
||||||
let peek = reader.peek()?;
|
|
||||||
println!("Peeking before forcing next event {:?}", peek);
|
|
||||||
|
|
||||||
if let XmlEvent::EndElement { name } = peek {
|
|
||||||
// TODO save the interface name and struct in the hashmap
|
|
||||||
println!("Forcing next_event");
|
|
||||||
reader.next_event()?;
|
|
||||||
|
|
||||||
let peek = reader.peek()?;
|
|
||||||
println!("Peeking after next event deserializing {:?}", peek);
|
|
||||||
if let XmlEvent::EndElement { name } = peek {
|
|
||||||
println!("Got two EndElement in a row, breaking out of loop");
|
|
||||||
break 'inner_iface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Peeking before deserializing {:?}", reader.peek()?);
|
|
||||||
let interface = <Interface as yaserde::YaDeserialize>::deserialize(reader)?;
|
|
||||||
println!("Interface deserialized {:?}", interface);
|
|
||||||
println!("Peeking after deserializing {:?}", reader.peek()?);
|
|
||||||
}
|
|
||||||
println!(
|
|
||||||
"Done with inner interface, loop completed {:?}",
|
|
||||||
reader.peek()?
|
|
||||||
);
|
|
||||||
}
|
|
||||||
xml::reader::XmlEvent::EndDocument => break,
|
|
||||||
_ => {
|
|
||||||
return Err(
|
|
||||||
"This Interfaces Deserializer does not support all XmlEvent types".into(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let peek = reader.peek()?;
|
|
||||||
|
|
||||||
let read_next = true;
|
|
||||||
if let XmlEvent::EndElement { name } = peek {
|
|
||||||
if name.local_name == "interfaces" {
|
|
||||||
println!("Got endElement interfaces, not reading next event");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if read_next {
|
|
||||||
event = reader.next_event()?;
|
|
||||||
}
|
|
||||||
println!("Outer loop got event {:?}", event);
|
|
||||||
println!("Outer loop got peek {:?}", reader.peek()?);
|
|
||||||
}
|
|
||||||
println!("Done with interfaces {:?}", interfaces);
|
|
||||||
println!("reader peeking shows {:?}", reader.peek());
|
|
||||||
|
|
||||||
Ok(interfaces)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
mod interfaces;
|
|
||||||
|
|
||||||
@ -1,12 +1,9 @@
|
|||||||
|
use opnsense_config_xml::Range;
|
||||||
|
use opnsense_config_xml::StaticMap;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::net::IpAddr;
|
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use super::opnsense::{OPNsense, StaticMap};
|
use opnsense_config_xml::OPNsense;
|
||||||
use crate::infra::maybe_string::MaybeString;
|
|
||||||
use crate::modules::opnsense::NumberOption;
|
|
||||||
use crate::modules::opnsense::Range;
|
|
||||||
use yaserde_derive::{YaDeserialize, YaSerialize};
|
|
||||||
|
|
||||||
pub struct DhcpConfig<'a> {
|
pub struct DhcpConfig<'a> {
|
||||||
opnsense: &'a mut OPNsense,
|
opnsense: &'a mut OPNsense,
|
||||||
@ -48,41 +45,48 @@ impl<'a> DhcpConfig<'a> {
|
|||||||
|
|
||||||
pub fn add_static_mapping(
|
pub fn add_static_mapping(
|
||||||
&mut self,
|
&mut self,
|
||||||
mac: String,
|
mac: &str,
|
||||||
ipaddr: Ipv4Addr,
|
ipaddr: Ipv4Addr,
|
||||||
hostname: String,
|
hostname: &str,
|
||||||
) -> Result<(), DhcpError> {
|
) -> Result<(), DhcpError> {
|
||||||
let range: Range = todo!();
|
let mac = mac.to_string();
|
||||||
|
let hostname = hostname.to_string();
|
||||||
|
let range = &self.opnsense.dhcpd.lan.range;
|
||||||
|
|
||||||
if !Self::is_valid_mac(&mac) {
|
if !Self::is_valid_mac(&mac) {
|
||||||
return Err(DhcpError::InvalidMacAddress(mac));
|
return Err(DhcpError::InvalidMacAddress(mac));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if !Self::is_ip_in_range(&ipaddr, range) {
|
if !Self::is_ip_in_range(&ipaddr, range) {
|
||||||
// return Err(DhcpError::IpAddressOutOfRange(ipaddr));
|
return Err(DhcpError::IpAddressOutOfRange(ipaddr.to_string()));
|
||||||
// }
|
}
|
||||||
|
|
||||||
let existing_mappings = &self.opnsense.dhcpd.lan.staticmaps;
|
let existing_mappings = &self.opnsense.dhcpd.lan.staticmaps;
|
||||||
|
|
||||||
// TODO
|
if existing_mappings.iter().any(|m| {
|
||||||
// if existing_mappings.iter().any(|m| m.ipaddr == ipaddr) {
|
m.ipaddr
|
||||||
// return Err(DhcpError::IpAddressAlreadyMapped(ipaddr));
|
.parse::<Ipv4Addr>()
|
||||||
// }
|
.expect("Mapping contains invalid ipv4")
|
||||||
|
== ipaddr
|
||||||
|
}) {
|
||||||
|
return Err(DhcpError::IpAddressAlreadyMapped(ipaddr.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
// if existing_mappings.iter().any(|m| m.mac == mac) {
|
if existing_mappings.iter().any(|m| m.mac == mac) {
|
||||||
// return Err(DhcpError::MacAddressAlreadyMapped(mac));
|
return Err(DhcpError::MacAddressAlreadyMapped(mac));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let static_map = StaticMap {
|
let static_map = StaticMap {
|
||||||
// mac,
|
mac,
|
||||||
// ipaddr,
|
ipaddr: ipaddr.to_string(),
|
||||||
// hostname,
|
hostname,
|
||||||
// descr: Default::default(),
|
descr: Default::default(),
|
||||||
// winsserver: Default::default(),
|
winsserver: Default::default(),
|
||||||
// dnsserver: Default::default(),
|
dnsserver: Default::default(),
|
||||||
// ntpserver: Default::default(),
|
ntpserver: Default::default(),
|
||||||
// };
|
};
|
||||||
|
|
||||||
// self.opnsense.dhcpd.lan.staticmaps.push(static_map);
|
self.opnsense.dhcpd.lan.staticmaps.push(static_map);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +105,7 @@ impl<'a> DhcpConfig<'a> {
|
|||||||
.all(|part| part.len() == 2 && part.chars().all(|c| c.is_ascii_hexdigit()))
|
.all(|part| part.len() == 2 && part.chars().all(|c| c.is_ascii_hexdigit()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ip_in_range(ip: &Ipv4Addr, range: Range) -> bool {
|
fn is_ip_in_range(ip: &Ipv4Addr, range: &Range) -> bool {
|
||||||
let range_start = range
|
let range_start = range
|
||||||
.from
|
.from
|
||||||
.parse::<Ipv4Addr>()
|
.parse::<Ipv4Addr>()
|
||||||
@ -121,114 +125,11 @@ impl<'a> DhcpConfig<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
|
||||||
#[yaserde(rename = "dhcpd")]
|
|
||||||
pub struct Dhcpd {
|
|
||||||
#[yaserde(rename = "lan")]
|
|
||||||
pub lan: DhcpInterface,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
|
||||||
pub struct DhcpInterface {
|
|
||||||
pub enable: i32,
|
|
||||||
pub gateway: String,
|
|
||||||
pub domain: String,
|
|
||||||
#[yaserde(rename = "ddnsdomainalgorithm")]
|
|
||||||
pub ddns_domain_algorithm: String,
|
|
||||||
#[yaserde(rename = "numberoptions")]
|
|
||||||
pub number_options: Vec<NumberOption>,
|
|
||||||
#[yaserde(rename = "range")]
|
|
||||||
pub range: Range,
|
|
||||||
pub winsserver: MaybeString,
|
|
||||||
pub dnsserver: MaybeString,
|
|
||||||
pub ntpserver: MaybeString,
|
|
||||||
#[yaserde(rename = "staticmap")]
|
|
||||||
pub staticmaps: Vec<StaticMap>,
|
|
||||||
pub pool: MaybeString,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
|
||||||
pub struct DhcpRange {
|
|
||||||
#[yaserde(rename = "from")]
|
|
||||||
pub from: String,
|
|
||||||
#[yaserde(rename = "to")]
|
|
||||||
pub to: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use crate::infra::yaserde::to_xml_str;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
#[test]
|
|
||||||
fn dhcpd_should_deserialize_serialize_identical() {
|
|
||||||
let dhcpd: Dhcpd =
|
|
||||||
yaserde::de::from_str(SERIALIZED_DHCPD).expect("Deserialize Dhcpd failed");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
to_xml_str(&dhcpd).expect("Serialize Dhcpd failed"),
|
|
||||||
SERIALIZED_DHCPD
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SERIALIZED_DHCPD: &str = "<?xml version=\"1.0\"?>
|
|
||||||
<dhcpd>
|
|
||||||
<lan>
|
|
||||||
<enable>1</enable>
|
|
||||||
<gateway>192.168.20.1</gateway>
|
|
||||||
<domain>somedomain.yourlocal.mcd</domain>
|
|
||||||
<ddnsdomainalgorithm>hmac-md5</ddnsdomainalgorithm>
|
|
||||||
<numberoptions>
|
|
||||||
<item/>
|
|
||||||
</numberoptions>
|
|
||||||
<range>
|
|
||||||
<from>192.168.20.50</from>
|
|
||||||
<to>192.168.20.200</to>
|
|
||||||
</range>
|
|
||||||
<winsserver/>
|
|
||||||
<dnsserver>192.168.20.1</dnsserver>
|
|
||||||
<ntpserver/>
|
|
||||||
<staticmap>
|
|
||||||
<mac>55:55:55:55:55:1c</mac>
|
|
||||||
<ipaddr>192.168.20.160</ipaddr>
|
|
||||||
<hostname>somehost983</hostname>
|
|
||||||
<descr>someservire8</descr>
|
|
||||||
<winsserver/>
|
|
||||||
<dnsserver/>
|
|
||||||
<ntpserver/>
|
|
||||||
</staticmap>
|
|
||||||
<staticmap>
|
|
||||||
<mac>55:55:55:55:55:1c</mac>
|
|
||||||
<ipaddr>192.168.20.155</ipaddr>
|
|
||||||
<hostname>somehost893</hostname>
|
|
||||||
<winsserver/>
|
|
||||||
<dnsserver/>
|
|
||||||
<ntpserver/>
|
|
||||||
</staticmap>
|
|
||||||
<staticmap>
|
|
||||||
<mac>55:55:55:55:55:1c</mac>
|
|
||||||
<ipaddr>192.168.20.165</ipaddr>
|
|
||||||
<hostname>somehost893</hostname>
|
|
||||||
<descr/>
|
|
||||||
<winsserver/>
|
|
||||||
<dnsserver/>
|
|
||||||
<ntpserver/>
|
|
||||||
</staticmap>
|
|
||||||
<staticmap>
|
|
||||||
<mac>55:55:55:55:55:1c</mac>
|
|
||||||
<ipaddr>192.168.20.50</ipaddr>
|
|
||||||
<hostname>hostswitch2</hostname>
|
|
||||||
<descr>switch-2 (bottom)</descr>
|
|
||||||
<winsserver/>
|
|
||||||
<dnsserver/>
|
|
||||||
<ntpserver/>
|
|
||||||
</staticmap>
|
|
||||||
<pool/>
|
|
||||||
</lan>
|
|
||||||
</dhcpd>\n";
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ip_in_range() {
|
fn test_ip_in_range() {
|
||||||
@ -239,22 +140,23 @@ mod test {
|
|||||||
|
|
||||||
// Test IP within range
|
// Test IP within range
|
||||||
let ip = "192.168.1.150".parse::<Ipv4Addr>().unwrap();
|
let ip = "192.168.1.150".parse::<Ipv4Addr>().unwrap();
|
||||||
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), true);
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, &range), true);
|
||||||
|
|
||||||
// Test IP at start of range
|
// Test IP at start of range
|
||||||
let ip = "192.168.1.100".parse::<Ipv4Addr>().unwrap();
|
let ip = "192.168.1.100".parse::<Ipv4Addr>().unwrap();
|
||||||
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), true);
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, &range), true);
|
||||||
|
|
||||||
// Test IP at end of range
|
// Test IP at end of range
|
||||||
let ip = "192.168.1.200".parse::<Ipv4Addr>().unwrap();
|
let ip = "192.168.1.200".parse::<Ipv4Addr>().unwrap();
|
||||||
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), true);
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, &range), true);
|
||||||
|
|
||||||
// Test IP before range
|
// Test IP before range
|
||||||
let ip = "192.168.1.99".parse::<Ipv4Addr>().unwrap();
|
let ip = "192.168.1.99".parse::<Ipv4Addr>().unwrap();
|
||||||
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), false);
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, &range), false);
|
||||||
|
|
||||||
// Test IP after range
|
// Test IP after range
|
||||||
let ip = "192.168.1.201".parse::<Ipv4Addr>().unwrap();
|
let ip = "192.168.1.201".parse::<Ipv4Addr>().unwrap();
|
||||||
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), false);
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, &range), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1 @@
|
|||||||
pub mod opnsense;
|
|
||||||
pub mod dhcp;
|
pub mod dhcp;
|
||||||
mod deserializer;
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user