Parse NW filters XML structure
This commit is contained in:
		@@ -1,5 +1,7 @@
 | 
				
			|||||||
use crate::app_config::AppConfig;
 | 
					use crate::app_config::AppConfig;
 | 
				
			||||||
use crate::libvirt_lib_structures::{DomainState, DomainXML, NetworkXML, XMLUuid};
 | 
					use crate::libvirt_lib_structures::{
 | 
				
			||||||
 | 
					    DomainState, DomainXML, NetworkFilterXML, NetworkXML, XMLUuid,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use crate::libvirt_rest_structures::*;
 | 
					use crate::libvirt_rest_structures::*;
 | 
				
			||||||
use actix::{Actor, Context, Handler, Message};
 | 
					use actix::{Actor, Context, Handler, Message};
 | 
				
			||||||
use image::ImageOutputFormat;
 | 
					use image::ImageOutputFormat;
 | 
				
			||||||
@@ -7,6 +9,7 @@ use std::io::Cursor;
 | 
				
			|||||||
use virt::connect::Connect;
 | 
					use virt::connect::Connect;
 | 
				
			||||||
use virt::domain::Domain;
 | 
					use virt::domain::Domain;
 | 
				
			||||||
use virt::network::Network;
 | 
					use virt::network::Network;
 | 
				
			||||||
 | 
					use virt::nwfilter::NWFilter;
 | 
				
			||||||
use virt::stream::Stream;
 | 
					use virt::stream::Stream;
 | 
				
			||||||
use virt::sys;
 | 
					use virt::sys;
 | 
				
			||||||
use virt::sys::VIR_DOMAIN_XML_SECURE;
 | 
					use virt::sys::VIR_DOMAIN_XML_SECURE;
 | 
				
			||||||
@@ -549,3 +552,39 @@ impl Handler<StopNetwork> for LibVirtActor {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Message)]
 | 
				
			||||||
 | 
					#[rtype(result = "anyhow::Result<Vec<XMLUuid>>")]
 | 
				
			||||||
 | 
					pub struct GetNWFiltersListReq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Handler<GetNWFiltersListReq> for LibVirtActor {
 | 
				
			||||||
 | 
					    type Result = anyhow::Result<Vec<XMLUuid>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn handle(&mut self, _msg: GetNWFiltersListReq, _ctx: &mut Self::Context) -> Self::Result {
 | 
				
			||||||
 | 
					        log::debug!("Get full list of network filters");
 | 
				
			||||||
 | 
					        let networks = self.m.list_all_nw_filters(0)?;
 | 
				
			||||||
 | 
					        let mut ids = Vec::with_capacity(networks.len());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for d in networks {
 | 
				
			||||||
 | 
					            ids.push(XMLUuid::parse_from_str(&d.get_uuid_string()?)?);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(ids)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Message)]
 | 
				
			||||||
 | 
					#[rtype(result = "anyhow::Result<NetworkFilterXML>")]
 | 
				
			||||||
 | 
					pub struct GetNWFilterXMLReq(pub XMLUuid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Handler<GetNWFilterXMLReq> for LibVirtActor {
 | 
				
			||||||
 | 
					    type Result = anyhow::Result<NetworkFilterXML>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn handle(&mut self, msg: GetNWFilterXMLReq, _ctx: &mut Self::Context) -> Self::Result {
 | 
				
			||||||
 | 
					        log::debug!("Get network filter XML:\n{}", msg.0.as_string());
 | 
				
			||||||
 | 
					        let filter = NWFilter::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
 | 
				
			||||||
 | 
					        let xml = filter.get_xml_desc(0)?;
 | 
				
			||||||
 | 
					        log::debug!("XML = {}", xml);
 | 
				
			||||||
 | 
					        NetworkFilterXML::parse_xml(xml)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,3 +46,31 @@ pub const DISK_SIZE_MAX: usize = 1000 * 1000 * 2;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Network mac address default prefix
 | 
					/// Network mac address default prefix
 | 
				
			||||||
pub const NET_MAC_ADDR_PREFIX: &str = "52:54:00";
 | 
					pub const NET_MAC_ADDR_PREFIX: &str = "52:54:00";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Built-in network filter rules
 | 
				
			||||||
 | 
					pub const BUILTIN_NETWORK_FILTER_RULES: [&str; 24] = [
 | 
				
			||||||
 | 
					    "allow-arp",
 | 
				
			||||||
 | 
					    "allow-dhcp",
 | 
				
			||||||
 | 
					    "allow-dhcp-server",
 | 
				
			||||||
 | 
					    "allow-dhcpv6",
 | 
				
			||||||
 | 
					    "allow-dhcpv6-server",
 | 
				
			||||||
 | 
					    "allow-incoming-ipv4",
 | 
				
			||||||
 | 
					    "allow-incoming-ipv6",
 | 
				
			||||||
 | 
					    "allow-ipv4",
 | 
				
			||||||
 | 
					    "allow-ipv6",
 | 
				
			||||||
 | 
					    "clean-traffic",
 | 
				
			||||||
 | 
					    "clean-traffic-gateway",
 | 
				
			||||||
 | 
					    "no-arp-ip-spoofing",
 | 
				
			||||||
 | 
					    "no-arp-mac-spoofing",
 | 
				
			||||||
 | 
					    "no-arp-spoofing",
 | 
				
			||||||
 | 
					    "no-ip-multicast",
 | 
				
			||||||
 | 
					    "no-ip-spoofing",
 | 
				
			||||||
 | 
					    "no-ipv6-multicast",
 | 
				
			||||||
 | 
					    "no-ipv6-spoofing",
 | 
				
			||||||
 | 
					    "no-mac-broadcast",
 | 
				
			||||||
 | 
					    "no-mac-spoofing",
 | 
				
			||||||
 | 
					    "no-other-l2-traffic",
 | 
				
			||||||
 | 
					    "no-other-rarp-traffic",
 | 
				
			||||||
 | 
					    "qemu-announce-self",
 | 
				
			||||||
 | 
					    "qemu-announce-self-rarp",
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ use std::io::ErrorKind;
 | 
				
			|||||||
pub mod auth_controller;
 | 
					pub mod auth_controller;
 | 
				
			||||||
pub mod iso_controller;
 | 
					pub mod iso_controller;
 | 
				
			||||||
pub mod network_controller;
 | 
					pub mod network_controller;
 | 
				
			||||||
 | 
					pub mod nwfilter_controller;
 | 
				
			||||||
pub mod server_controller;
 | 
					pub mod server_controller;
 | 
				
			||||||
pub mod static_controller;
 | 
					pub mod static_controller;
 | 
				
			||||||
pub mod vm_controller;
 | 
					pub mod vm_controller;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								virtweb_backend/src/controllers/nwfilter_controller.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								virtweb_backend/src/controllers/nwfilter_controller.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					use crate::controllers::{HttpResult, LibVirtReq};
 | 
				
			||||||
 | 
					use crate::libvirt_lib_structures::XMLUuid;
 | 
				
			||||||
 | 
					use actix_web::{web, HttpResponse};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
 | 
					pub struct NetworkFilterID {
 | 
				
			||||||
 | 
					    uid: XMLUuid,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get the list of network filters
 | 
				
			||||||
 | 
					pub async fn list(client: LibVirtReq) -> HttpResult {
 | 
				
			||||||
 | 
					    let networks = match client.get_full_network_filters_list().await {
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            log::error!("Failed to get the list of network filters! {e}");
 | 
				
			||||||
 | 
					            return Ok(HttpResponse::InternalServerError()
 | 
				
			||||||
 | 
					                .json(format!("Failed to get the list of networks! {e}")));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(l) => l,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*let networks = networks
 | 
				
			||||||
 | 
					    .into_iter()
 | 
				
			||||||
 | 
					    .map(|n| NetworkInfo::from_xml(n).unwrap())
 | 
				
			||||||
 | 
					    .collect::<Vec<_>>();*/
 | 
				
			||||||
 | 
					    // TODO : turn into lib structure
 | 
				
			||||||
 | 
					    println!("{:#?}", networks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(HttpResponse::Ok().body(format!("{:#?}", networks)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get the information about a single network filter
 | 
				
			||||||
 | 
					pub async fn get_single(client: LibVirtReq, req: web::Path<NetworkFilterID>) -> HttpResult {
 | 
				
			||||||
 | 
					    let nwfilter = client.get_single_network_filter(req.uid).await?;
 | 
				
			||||||
 | 
					    // TODO : turn into lib structure
 | 
				
			||||||
 | 
					    Ok(HttpResponse::Ok().body(format!("{:#?}", nwfilter)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -16,6 +16,7 @@ struct StaticConfig {
 | 
				
			|||||||
    iso_mimetypes: &'static [&'static str],
 | 
					    iso_mimetypes: &'static [&'static str],
 | 
				
			||||||
    net_mac_prefix: &'static str,
 | 
					    net_mac_prefix: &'static str,
 | 
				
			||||||
    constraints: ServerConstraints,
 | 
					    constraints: ServerConstraints,
 | 
				
			||||||
 | 
					    builtin_network_rules: &'static [&'static str],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize)]
 | 
					#[derive(serde::Serialize)]
 | 
				
			||||||
@@ -45,6 +46,7 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
 | 
				
			|||||||
        oidc_auth_enabled: !AppConfig::get().disable_oidc,
 | 
					        oidc_auth_enabled: !AppConfig::get().disable_oidc,
 | 
				
			||||||
        iso_mimetypes: &constants::ALLOWED_ISO_MIME_TYPES,
 | 
					        iso_mimetypes: &constants::ALLOWED_ISO_MIME_TYPES,
 | 
				
			||||||
        net_mac_prefix: constants::NET_MAC_ADDR_PREFIX,
 | 
					        net_mac_prefix: constants::NET_MAC_ADDR_PREFIX,
 | 
				
			||||||
 | 
					        builtin_network_rules: &constants::BUILTIN_NETWORK_FILTER_RULES,
 | 
				
			||||||
        constraints: ServerConstraints {
 | 
					        constraints: ServerConstraints {
 | 
				
			||||||
            iso_max_size: constants::ISO_MAX_SIZE,
 | 
					            iso_max_size: constants::ISO_MAX_SIZE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
use crate::actors::libvirt_actor;
 | 
					use crate::actors::libvirt_actor;
 | 
				
			||||||
use crate::actors::libvirt_actor::LibVirtActor;
 | 
					use crate::actors::libvirt_actor::LibVirtActor;
 | 
				
			||||||
use crate::libvirt_lib_structures::{DomainState, DomainXML, NetworkXML, XMLUuid};
 | 
					use crate::libvirt_lib_structures::{
 | 
				
			||||||
 | 
					    DomainState, DomainXML, NetworkFilterXML, NetworkXML, XMLUuid,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use crate::libvirt_rest_structures::{HypervisorInfo, NetworkInfo, VMInfo};
 | 
					use crate::libvirt_rest_structures::{HypervisorInfo, NetworkInfo, VMInfo};
 | 
				
			||||||
use actix::Addr;
 | 
					use actix::Addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -165,4 +167,19 @@ impl LibVirtClient {
 | 
				
			|||||||
    pub async fn stop_network(&self, id: XMLUuid) -> anyhow::Result<()> {
 | 
					    pub async fn stop_network(&self, id: XMLUuid) -> anyhow::Result<()> {
 | 
				
			||||||
        self.0.send(libvirt_actor::StopNetwork(id)).await?
 | 
					        self.0.send(libvirt_actor::StopNetwork(id)).await?
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Get the full list of network filters
 | 
				
			||||||
 | 
					    pub async fn get_full_network_filters_list(&self) -> anyhow::Result<Vec<NetworkFilterXML>> {
 | 
				
			||||||
 | 
					        let ids = self.0.send(libvirt_actor::GetNWFiltersListReq).await??;
 | 
				
			||||||
 | 
					        let mut info = Vec::with_capacity(ids.len());
 | 
				
			||||||
 | 
					        for id in ids {
 | 
				
			||||||
 | 
					            info.push(self.get_single_network_filter(id).await?)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(info)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Get the information about a single domain
 | 
				
			||||||
 | 
					    pub async fn get_single_network_filter(&self, id: XMLUuid) -> anyhow::Result<NetworkFilterXML> {
 | 
				
			||||||
 | 
					        self.0.send(libvirt_actor::GetNWFilterXMLReq(id)).await?
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					use std::fmt::Display;
 | 
				
			||||||
use std::net::{IpAddr, Ipv4Addr};
 | 
					use std::net::{IpAddr, Ipv4Addr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug)]
 | 
				
			||||||
@@ -548,3 +549,316 @@ impl NetworkXML {
 | 
				
			|||||||
        Ok(network_xml)
 | 
					        Ok(network_xml)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "filterref")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRefXML {
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@filter"))]
 | 
				
			||||||
 | 
					    pub filter: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "all")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRuleProtocolAll {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "mac")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRuleProtocolMac {
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacmask: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstmacmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstmacmask: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@comment"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    comment: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "arp")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRuleProtocolArp {
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacmask: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstmacmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstmacmask: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@arpsrcipaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    arpsrcipaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@arpsrcipmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    arpsrcipmask: Option<u8>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@arpdstipaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    arpdstipaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@arpdstipmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    arpdstipmask: Option<u8>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@comment"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    comment: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "ipvx")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRuleProtocolIpvx {
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacmask: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstmacmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstmacmask: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcipaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcipaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcipmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcipmask: Option<u8>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstipaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstipaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstipmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstipmask: Option<u8>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@comment"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    comment: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "layer4")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRuleProtocolLayer4 {
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcmacaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcipaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcipaddr: Option<IpAddr>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcipmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcipmask: Option<u8>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstipaddr"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstipaddr: Option<IpAddr>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstipmask"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstipmask: Option<u8>,
 | 
				
			||||||
 | 
					    /// Start of range of source IP address
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcipfrom"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcipfrom: Option<IpAddr>,
 | 
				
			||||||
 | 
					    /// End of range of source IP address
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcipto"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcipto: Option<IpAddr>,
 | 
				
			||||||
 | 
					    /// Start of range of destination IP address
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstipfrom"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstipfrom: Option<IpAddr>,
 | 
				
			||||||
 | 
					    /// End of range of destination IP address
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstipto"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstipto: Option<IpAddr>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcportstart"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcportstart: Option<u16>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@srcportend"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    srcportend: Option<u16>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstportstart"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstportstart: Option<u16>,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@dstportend"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    dstportend: Option<u16>,
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@state"), skip_serializing_if = "Option::is_none")]
 | 
				
			||||||
 | 
					    state: Option<String>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        rename(serialize = "@comment"),
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    comment: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "rule")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterRuleXML {
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@action"))]
 | 
				
			||||||
 | 
					    pub action: String,
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@direction"))]
 | 
				
			||||||
 | 
					    pub direction: String,
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@priority"))]
 | 
				
			||||||
 | 
					    pub priority: Option<i32>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match all protocols
 | 
				
			||||||
 | 
					    #[serde(skip_serializing_if = "Option::is_none")]
 | 
				
			||||||
 | 
					    pub all: Option<NetworkFilterRuleProtocolAll>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match mac protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub mac_rules: Vec<NetworkFilterRuleProtocolMac>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match arp protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "arp", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub arp_rules: Vec<NetworkFilterRuleProtocolArp>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match IPv4 protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "ip", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub ipv4_rules: Vec<NetworkFilterRuleProtocolIpvx>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match IPv6 protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "ipv6", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub ipv6_rules: Vec<NetworkFilterRuleProtocolIpvx>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match TCP protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "tcp", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub tcp_rules: Vec<NetworkFilterRuleProtocolLayer4>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match UDP protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "udp", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub udp_rules: Vec<NetworkFilterRuleProtocolLayer4>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Match SCTP protocol
 | 
				
			||||||
 | 
					    #[serde(default, rename = "sctp", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub sctp_rules: Vec<NetworkFilterRuleProtocolLayer4>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
				
			||||||
 | 
					#[serde(rename = "filter")]
 | 
				
			||||||
 | 
					pub struct NetworkFilterXML {
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@name"))]
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    #[serde(rename(serialize = "@chain"), default)]
 | 
				
			||||||
 | 
					    pub chain: String,
 | 
				
			||||||
 | 
					    #[serde(
 | 
				
			||||||
 | 
					        skip_serializing_if = "Option::is_none",
 | 
				
			||||||
 | 
					        rename(serialize = "@priority"),
 | 
				
			||||||
 | 
					        default
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    pub priority: Option<i32>,
 | 
				
			||||||
 | 
					    #[serde(skip_serializing_if = "Option::is_none")]
 | 
				
			||||||
 | 
					    pub uuid: Option<XMLUuid>,
 | 
				
			||||||
 | 
					    #[serde(default, rename = "filterref", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub filterrefs: Vec<NetworkFilterRefXML>,
 | 
				
			||||||
 | 
					    #[serde(default, rename = "rule", skip_serializing_if = "Vec::is_empty")]
 | 
				
			||||||
 | 
					    pub rules: Vec<NetworkFilterRuleXML>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl NetworkFilterXML {
 | 
				
			||||||
 | 
					    pub fn parse_xml<D: Display>(xml: D) -> anyhow::Result<Self> {
 | 
				
			||||||
 | 
					        let xml = xml.to_string();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We need to put all filter refs at the same location
 | 
				
			||||||
 | 
					        let mut filter_refs = Vec::new();
 | 
				
			||||||
 | 
					        let xml = lazy_regex::regex_replace_all!(r#"<filterref.*/>"#, &xml, |r: &str| {
 | 
				
			||||||
 | 
					            filter_refs.push(r.to_string());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if r.contains('\n') {
 | 
				
			||||||
 | 
					                log::warn!("A filterref contain a new line. This is a symptom of a new unsupported child attribute of <filterref /> object!");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ""
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let filter_refs = filter_refs.join("\n");
 | 
				
			||||||
 | 
					        let xml = xml.replace("</filter>", &format!("{filter_refs}</filter>"));
 | 
				
			||||||
 | 
					        log::debug!("Effective NW filter rule parsed: {xml}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(serde_xml_rs::from_str(&xml)?)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -700,6 +700,144 @@ impl NetworkInfo {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum NetworkFilterChain {
 | 
				
			||||||
 | 
					    Root,
 | 
				
			||||||
 | 
					    Mac,
 | 
				
			||||||
 | 
					    STP,
 | 
				
			||||||
 | 
					    VLAN,
 | 
				
			||||||
 | 
					    ARP,
 | 
				
			||||||
 | 
					    RARP,
 | 
				
			||||||
 | 
					    IPv4,
 | 
				
			||||||
 | 
					    IPv6,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Network filter definition
 | 
				
			||||||
 | 
					pub struct NetworkFilter {
 | 
				
			||||||
 | 
					    name: String,
 | 
				
			||||||
 | 
					    chain: Option<NetworkFilterChain>,
 | 
				
			||||||
 | 
					    priority: Option<i32>,
 | 
				
			||||||
 | 
					    uuid: Option<XMLUuid>,
 | 
				
			||||||
 | 
					    /// Referenced filters rules
 | 
				
			||||||
 | 
					    join_rules: Vec<String>,
 | 
				
			||||||
 | 
					    rules: Vec<NetworkFilterRule>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum NetworkFilterAction {
 | 
				
			||||||
 | 
					    /// matching the rule silently discards the packet with no further analysis
 | 
				
			||||||
 | 
					    Drop,
 | 
				
			||||||
 | 
					    /// matching the rule generates an ICMP reject message with no further analysis
 | 
				
			||||||
 | 
					    Reject,
 | 
				
			||||||
 | 
					    /// matching the rule accepts the packet with no further analysis
 | 
				
			||||||
 | 
					    Accept,
 | 
				
			||||||
 | 
					    /// matching the rule passes this filter, but returns control to the calling filter for further
 | 
				
			||||||
 | 
					    /// analysis
 | 
				
			||||||
 | 
					    Return,
 | 
				
			||||||
 | 
					    /// matching the rule goes on to the next rule for further analysis
 | 
				
			||||||
 | 
					    Continue,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum NetworkFilterDirection {
 | 
				
			||||||
 | 
					    In,
 | 
				
			||||||
 | 
					    Out,
 | 
				
			||||||
 | 
					    InOut,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum Layer4State {
 | 
				
			||||||
 | 
					    NEW,
 | 
				
			||||||
 | 
					    ESTABLISHED,
 | 
				
			||||||
 | 
					    RELATED,
 | 
				
			||||||
 | 
					    INVALID,
 | 
				
			||||||
 | 
					    NONE,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum Layer4Type {
 | 
				
			||||||
 | 
					    TCP,
 | 
				
			||||||
 | 
					    UDP,
 | 
				
			||||||
 | 
					    SCTP,
 | 
				
			||||||
 | 
					    ICMP,
 | 
				
			||||||
 | 
					    TCPipv6,
 | 
				
			||||||
 | 
					    UDPipv6,
 | 
				
			||||||
 | 
					    SCTPipv6,
 | 
				
			||||||
 | 
					    ICMPipv6,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum NetworkFilterSelector {
 | 
				
			||||||
 | 
					    All,
 | 
				
			||||||
 | 
					    Mac {
 | 
				
			||||||
 | 
					        src_mac_addr: Option<String>,
 | 
				
			||||||
 | 
					        src_mac_mask: Option<String>,
 | 
				
			||||||
 | 
					        dst_mac_addr: Option<String>,
 | 
				
			||||||
 | 
					        dst_mac_mask: Option<String>,
 | 
				
			||||||
 | 
					        comment: Option<String>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    Arp {
 | 
				
			||||||
 | 
					        srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        srcmacmask: Option<String>,
 | 
				
			||||||
 | 
					        dstmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        dstmacmask: Option<String>,
 | 
				
			||||||
 | 
					        arpsrcipaddr: Option<IpAddr>,
 | 
				
			||||||
 | 
					        arpsrcipmask: Option<u8>,
 | 
				
			||||||
 | 
					        arpdstipaddr: Option<IpAddr>,
 | 
				
			||||||
 | 
					        arpdstipmask: Option<u8>,
 | 
				
			||||||
 | 
					        comment: Option<String>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    IPv4 {
 | 
				
			||||||
 | 
					        srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        srcmacmask: Option<String>,
 | 
				
			||||||
 | 
					        dstmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        dstmacmask: Option<String>,
 | 
				
			||||||
 | 
					        srcipaddr: Option<Ipv4Addr>,
 | 
				
			||||||
 | 
					        srcipmask: Option<u8>,
 | 
				
			||||||
 | 
					        dstipaddr: Option<Ipv4Addr>,
 | 
				
			||||||
 | 
					        dstipmask: Option<u8>,
 | 
				
			||||||
 | 
					        comment: Option<String>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    IPv6 {
 | 
				
			||||||
 | 
					        srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        srcmacmask: Option<String>,
 | 
				
			||||||
 | 
					        dstmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        dstmacmask: Option<String>,
 | 
				
			||||||
 | 
					        srcipaddr: Option<Ipv6Addr>,
 | 
				
			||||||
 | 
					        srcipmask: Option<u8>,
 | 
				
			||||||
 | 
					        dstipaddr: Option<Ipv6Addr>,
 | 
				
			||||||
 | 
					        dstipmask: Option<u8>,
 | 
				
			||||||
 | 
					        comment: Option<String>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    Layer4 {
 | 
				
			||||||
 | 
					        r#type: Layer4Type,
 | 
				
			||||||
 | 
					        srcmacaddr: Option<String>,
 | 
				
			||||||
 | 
					        srcipaddr: Option<IpAddr>,
 | 
				
			||||||
 | 
					        srcipmask: Option<u8>,
 | 
				
			||||||
 | 
					        dstipaddr: Option<IpAddr>,
 | 
				
			||||||
 | 
					        dstipmask: Option<u8>,
 | 
				
			||||||
 | 
					        /// Start of range of source IP address
 | 
				
			||||||
 | 
					        srcipfrom: Option<IpAddr>,
 | 
				
			||||||
 | 
					        /// End of range of source IP address
 | 
				
			||||||
 | 
					        srcipto: Option<IpAddr>,
 | 
				
			||||||
 | 
					        /// Start of range of destination IP address
 | 
				
			||||||
 | 
					        dstipfrom: Option<IpAddr>,
 | 
				
			||||||
 | 
					        /// End of range of destination IP address
 | 
				
			||||||
 | 
					        dstipto: Option<IpAddr>,
 | 
				
			||||||
 | 
					        srcportstart: Option<u16>,
 | 
				
			||||||
 | 
					        srcportend: Option<u16>,
 | 
				
			||||||
 | 
					        dstportstart: Option<u16>,
 | 
				
			||||||
 | 
					        dstportend: Option<u16>,
 | 
				
			||||||
 | 
					        state: Option<Layer4State>,
 | 
				
			||||||
 | 
					        comment: Option<String>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct NetworkFilterRule {
 | 
				
			||||||
 | 
					    action: NetworkFilterAction,
 | 
				
			||||||
 | 
					    direction: NetworkFilterDirection,
 | 
				
			||||||
 | 
					    /// optional; the priority of the rule controls the order in which the rule will be instantiated
 | 
				
			||||||
 | 
					    /// relative to other rules
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Valid values are in the range of -1000 to 1000.
 | 
				
			||||||
 | 
					    priority: Option<i32>,
 | 
				
			||||||
 | 
					    selectors: Vec<NetworkFilterSelector>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn extract_ipv4(ip: IpAddr) -> Ipv4Addr {
 | 
					fn extract_ipv4(ip: IpAddr) -> Ipv4Addr {
 | 
				
			||||||
    match ip {
 | 
					    match ip {
 | 
				
			||||||
        IpAddr::V4(i) => i,
 | 
					        IpAddr::V4(i) => i,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,8 +22,8 @@ use virtweb_backend::constants::{
 | 
				
			|||||||
    MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME,
 | 
					    MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use virtweb_backend::controllers::{
 | 
					use virtweb_backend::controllers::{
 | 
				
			||||||
    auth_controller, iso_controller, network_controller, server_controller, static_controller,
 | 
					    auth_controller, iso_controller, network_controller, nwfilter_controller, server_controller,
 | 
				
			||||||
    vm_controller,
 | 
					    static_controller, vm_controller,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use virtweb_backend::libvirt_client::LibVirtClient;
 | 
					use virtweb_backend::libvirt_client::LibVirtClient;
 | 
				
			||||||
use virtweb_backend::middlewares::auth_middleware::AuthChecker;
 | 
					use virtweb_backend::middlewares::auth_middleware::AuthChecker;
 | 
				
			||||||
@@ -239,6 +239,15 @@ async fn main() -> std::io::Result<()> {
 | 
				
			|||||||
                "/api/network/{uid}/stop",
 | 
					                "/api/network/{uid}/stop",
 | 
				
			||||||
                web::get().to(network_controller::stop),
 | 
					                web::get().to(network_controller::stop),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					            // Network filters controller
 | 
				
			||||||
 | 
					            .route(
 | 
				
			||||||
 | 
					                "/api/nwfilter/list",
 | 
				
			||||||
 | 
					                web::get().to(nwfilter_controller::list),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .route(
 | 
				
			||||||
 | 
					                "/api/nwfilter/{uid}",
 | 
				
			||||||
 | 
					                web::get().to(nwfilter_controller::get_single),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
            // Static assets
 | 
					            // Static assets
 | 
				
			||||||
            .route("/", web::get().to(static_controller::root_index))
 | 
					            .route("/", web::get().to(static_controller::root_index))
 | 
				
			||||||
            .route(
 | 
					            .route(
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user