Add Layer4 selectors extraction
This commit is contained in:
parent
c6c1ce26d3
commit
388a1ed478
@ -227,7 +227,7 @@ pub struct NetworkFilterRuleProtocolLayer4<IPv> {
|
|||||||
pub comment: Option<String>,
|
pub comment: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Default)]
|
||||||
#[serde(rename = "rule")]
|
#[serde(rename = "rule")]
|
||||||
pub struct NetworkFilterRuleXML {
|
pub struct NetworkFilterRuleXML {
|
||||||
#[serde(rename(serialize = "@action"))]
|
#[serde(rename(serialize = "@action"))]
|
||||||
@ -275,7 +275,7 @@ pub struct NetworkFilterRuleXML {
|
|||||||
|
|
||||||
/// Match ICMP protocol
|
/// Match ICMP protocol
|
||||||
#[serde(default, rename = "icmp", skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, rename = "icmp", skip_serializing_if = "Vec::is_empty")]
|
||||||
pub imcp_selectors: Vec<NetworkFilterRuleProtocolLayer4<Ipv4Addr>>,
|
pub icmp_selectors: Vec<NetworkFilterRuleProtocolLayer4<Ipv4Addr>>,
|
||||||
|
|
||||||
/// Match TCP IPv6 protocol
|
/// Match TCP IPv6 protocol
|
||||||
#[serde(default, rename = "tcp-ipv6", skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, rename = "tcp-ipv6", skip_serializing_if = "Vec::is_empty")]
|
||||||
|
@ -96,14 +96,14 @@ fn extract_ip_or_var<const V: usize>(
|
|||||||
Ok(n.as_ref().map(|n| n.0.to_string()))
|
Ok(n.as_ref().map(|n| n.0.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_ip_mask<const V: usize>(n: &Option<u8>) -> anyhow::Result<Option<u8>> {
|
fn extract_ip_mask<const V: usize>(n: Option<u8>) -> anyhow::Result<Option<u8>> {
|
||||||
if let Some(mask) = n {
|
if let Some(mask) = n {
|
||||||
if !net_utils::is_mask_valid(V, *mask) {
|
if !net_utils::is_mask_valid(V, mask) {
|
||||||
return Err(NetworkFilterExtraction(format!("Invalid IPv{V} mask! {}", mask)).into());
|
return Err(NetworkFilterExtraction(format!("Invalid IPv{V} mask! {mask}")).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(*n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_nw_filter_comment(n: &Option<String>) -> anyhow::Result<Option<String>> {
|
fn extract_nw_filter_comment(n: &Option<String>) -> anyhow::Result<Option<String>> {
|
||||||
@ -192,6 +192,211 @@ impl NetworkFilterChain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NetworkFilterAction {
|
||||||
|
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
|
||||||
|
Ok(match xml {
|
||||||
|
"drop" => Self::Drop,
|
||||||
|
"reject" => Self::Reject,
|
||||||
|
"accept" => Self::Accept,
|
||||||
|
"return" => Self::Return,
|
||||||
|
"continue" => Self::Continue,
|
||||||
|
s => {
|
||||||
|
return Err(LibVirtStructError::ParseFilteringChain(format!(
|
||||||
|
"Unkown filter action {s}!"
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_xml(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Drop => "drop",
|
||||||
|
Self::Reject => "reject",
|
||||||
|
Self::Accept => "accept",
|
||||||
|
Self::Return => "return",
|
||||||
|
Self::Continue => "continue",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum NetworkFilterDirection {
|
||||||
|
In,
|
||||||
|
Out,
|
||||||
|
InOut,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NetworkFilterDirection {
|
||||||
|
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
|
||||||
|
Ok(match xml {
|
||||||
|
"in" => Self::In,
|
||||||
|
"out" => Self::Out,
|
||||||
|
"inout" => Self::InOut,
|
||||||
|
s => {
|
||||||
|
return Err(LibVirtStructError::ParseFilteringChain(format!(
|
||||||
|
"Unkown filter direction {s}!"
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_xml(&self) -> String {
|
||||||
|
match self {
|
||||||
|
NetworkFilterDirection::In => "in",
|
||||||
|
NetworkFilterDirection::Out => "out",
|
||||||
|
NetworkFilterDirection::InOut => "inout",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
|
||||||
|
pub enum Layer4State {
|
||||||
|
NEW,
|
||||||
|
ESTABLISHED,
|
||||||
|
RELATED,
|
||||||
|
INVALID,
|
||||||
|
NONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Layer4State {
|
||||||
|
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
|
||||||
|
Ok(match xml {
|
||||||
|
"NEW" => Self::NEW,
|
||||||
|
"ESTABLISHED" => Self::ESTABLISHED,
|
||||||
|
"RELATED" => Self::RELATED,
|
||||||
|
"INVALID" => Self::INVALID,
|
||||||
|
"NONE" => Self::NONE,
|
||||||
|
s => {
|
||||||
|
return Err(LibVirtStructError::ParseFilteringChain(format!(
|
||||||
|
"Unkown layer4 state '{s}'!"
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_xml(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::NEW => "NEW",
|
||||||
|
Self::ESTABLISHED => "ESTABLISHED",
|
||||||
|
Self::RELATED => "RELATED",
|
||||||
|
Self::INVALID => "INVALID",
|
||||||
|
Self::NONE => "NONE",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
pub struct NetworkSelectorMac {
|
||||||
|
src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
src_mac_mask: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
dst_mac_addr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
dst_mac_mask: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
comment: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
pub struct NetworkSelectorARP {
|
||||||
|
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
srcmacmask: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
dstmacmask: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
arpsrcipaddr: Option<NetworkFilterIPv4OrVar>,
|
||||||
|
arpsrcipmask: Option<u8>,
|
||||||
|
arpdstipaddr: Option<NetworkFilterIPv4OrVar>,
|
||||||
|
arpdstipmask: Option<u8>,
|
||||||
|
comment: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
pub struct NetworkFilterSelectorIP<const V: usize> {
|
||||||
|
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
srcmacmask: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
dstmacmask: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
srcipaddr: Option<NetworkFilterIPOrVar<V>>,
|
||||||
|
srcipmask: Option<u8>,
|
||||||
|
dstipaddr: Option<NetworkFilterIPOrVar<V>>,
|
||||||
|
dstipmask: Option<u8>,
|
||||||
|
comment: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
pub struct NetworkFilterSelectorLayer4<IPv> {
|
||||||
|
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
|
srcipaddr: Option<IPv>,
|
||||||
|
srcipmask: Option<u8>,
|
||||||
|
dstipaddr: Option<IPv>,
|
||||||
|
dstipmask: Option<u8>,
|
||||||
|
/// Start of range of source IP address
|
||||||
|
srcipfrom: Option<IPv>,
|
||||||
|
/// End of range of source IP address
|
||||||
|
srcipto: Option<IPv>,
|
||||||
|
/// Start of range of destination IP address
|
||||||
|
dstipfrom: Option<IPv>,
|
||||||
|
/// End of range of destination IP address
|
||||||
|
dstipto: Option<IPv>,
|
||||||
|
srcportstart: Option<u16>,
|
||||||
|
srcportend: Option<u16>,
|
||||||
|
dstportstart: Option<u16>,
|
||||||
|
dstportend: Option<u16>,
|
||||||
|
state: Option<Layer4State>,
|
||||||
|
comment: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
#[serde(tag = "type", rename_all = "lowercase")]
|
||||||
|
pub enum NetworkFilterSelector {
|
||||||
|
All,
|
||||||
|
Mac(NetworkSelectorMac),
|
||||||
|
Arp(NetworkSelectorARP),
|
||||||
|
Rarp(NetworkSelectorARP),
|
||||||
|
IPv4(NetworkFilterSelectorIP<4>),
|
||||||
|
IPv6(NetworkFilterSelectorIP<6>),
|
||||||
|
TCP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
|
UDP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
|
SCTP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
|
ICMP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
|
TCPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
|
UDPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
|
SCTPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
|
ICMPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
|
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>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Network filter definition
|
/// Network filter definition
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
pub struct NetworkFilter {
|
pub struct NetworkFilter {
|
||||||
@ -251,8 +456,8 @@ impl NetworkFilter {
|
|||||||
|
|
||||||
fn lib2rest_process_layer4_rule<IPv: Copy>(
|
fn lib2rest_process_layer4_rule<IPv: Copy>(
|
||||||
n: &NetworkFilterRuleProtocolLayer4<IPv>,
|
n: &NetworkFilterRuleProtocolLayer4<IPv>,
|
||||||
) -> anyhow::Result<NetworkSelectorLayer4<IPv>> {
|
) -> anyhow::Result<NetworkFilterSelectorLayer4<IPv>> {
|
||||||
Ok(NetworkSelectorLayer4 {
|
Ok(NetworkFilterSelectorLayer4 {
|
||||||
srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
|
srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
|
||||||
srcipaddr: n.srcipaddr,
|
srcipaddr: n.srcipaddr,
|
||||||
srcipmask: n.srcipmask,
|
srcipmask: n.srcipmask,
|
||||||
@ -362,7 +567,7 @@ impl NetworkFilter {
|
|||||||
);
|
);
|
||||||
selectors.append(
|
selectors.append(
|
||||||
&mut rule
|
&mut rule
|
||||||
.imcp_selectors
|
.icmp_selectors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|r| {
|
.map(|r| {
|
||||||
Ok(NetworkFilterSelector::ICMP(
|
Ok(NetworkFilterSelector::ICMP(
|
||||||
@ -468,9 +673,33 @@ impl NetworkFilter {
|
|||||||
dstmacaddr: extract_mac_address_or_var(&selector.dstmacaddr)?,
|
dstmacaddr: extract_mac_address_or_var(&selector.dstmacaddr)?,
|
||||||
dstmacmask: extract_mac_address_or_var(&selector.dstmacmask)?,
|
dstmacmask: extract_mac_address_or_var(&selector.dstmacmask)?,
|
||||||
srcipaddr: extract_ip_or_var(&selector.srcipaddr)?,
|
srcipaddr: extract_ip_or_var(&selector.srcipaddr)?,
|
||||||
srcipmask: extract_ip_mask::<V>(&selector.srcipmask)?,
|
srcipmask: extract_ip_mask::<V>(selector.srcipmask)?,
|
||||||
dstipaddr: extract_ip_or_var(&selector.dstipaddr)?,
|
dstipaddr: extract_ip_or_var(&selector.dstipaddr)?,
|
||||||
dstipmask: extract_ip_mask::<V>(&selector.dstipmask)?,
|
dstipmask: extract_ip_mask::<V>(selector.dstipmask)?,
|
||||||
|
comment: extract_nw_filter_comment(&selector.comment)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rest2lib_process_layer4_selector<IPv: Copy>(
|
||||||
|
selector: &NetworkFilterSelectorLayer4<IPv>,
|
||||||
|
) -> anyhow::Result<NetworkFilterRuleProtocolLayer4<IPv>> {
|
||||||
|
Ok(NetworkFilterRuleProtocolLayer4 {
|
||||||
|
srcmacaddr: extract_mac_address_or_var(&selector.srcmacaddr)?,
|
||||||
|
srcipaddr: selector.srcipaddr,
|
||||||
|
// This IP mask is not checked
|
||||||
|
srcipmask: selector.srcipmask,
|
||||||
|
dstipaddr: selector.dstipaddr,
|
||||||
|
// This IP mask is not checked
|
||||||
|
dstipmask: selector.dstipmask,
|
||||||
|
srcipfrom: selector.srcipfrom,
|
||||||
|
srcipto: selector.srcipto,
|
||||||
|
dstipfrom: selector.dstipfrom,
|
||||||
|
dstipto: selector.dstipto,
|
||||||
|
srcportstart: selector.srcportstart,
|
||||||
|
srcportend: selector.srcportend,
|
||||||
|
dstportstart: selector.dstportstart,
|
||||||
|
dstportend: selector.dstportend,
|
||||||
|
state: selector.state.map(|s| s.to_xml()),
|
||||||
comment: extract_nw_filter_comment(&selector.comment)?,
|
comment: extract_nw_filter_comment(&selector.comment)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -480,20 +709,7 @@ impl NetworkFilter {
|
|||||||
action: rule.action.to_xml(),
|
action: rule.action.to_xml(),
|
||||||
direction: rule.direction.to_xml(),
|
direction: rule.direction.to_xml(),
|
||||||
priority: rule.priority,
|
priority: rule.priority,
|
||||||
all_selectors: vec![],
|
..Default::default()
|
||||||
mac_selectors: vec![],
|
|
||||||
arp_selectors: vec![],
|
|
||||||
rarp_selectors: vec![],
|
|
||||||
ipv4_selectors: vec![],
|
|
||||||
ipv6_selectors: vec![],
|
|
||||||
tcp_selectors: vec![],
|
|
||||||
udp_selectors: vec![],
|
|
||||||
sctp_selectors: vec![],
|
|
||||||
imcp_selectors: vec![],
|
|
||||||
tcp_ipv6_selectors: vec![],
|
|
||||||
udp_ipv6_selectors: vec![],
|
|
||||||
sctp_ipv6_selectors: vec![],
|
|
||||||
imcp_ipv6_selectors: vec![],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for sel in &rule.selectors {
|
for sel in &rule.selectors {
|
||||||
@ -531,14 +747,37 @@ impl NetworkFilter {
|
|||||||
.ipv6_selectors
|
.ipv6_selectors
|
||||||
.push(Self::rest2lib_process_ip_selector(ip)?),
|
.push(Self::rest2lib_process_ip_selector(ip)?),
|
||||||
|
|
||||||
NetworkFilterSelector::TCP(_) => todo!(),
|
NetworkFilterSelector::TCP(tcp) => rule_xml
|
||||||
NetworkFilterSelector::UDP(_) => todo!(),
|
.tcp_selectors
|
||||||
NetworkFilterSelector::SCTP(_) => todo!(),
|
.push(Self::rest2lib_process_layer4_selector(tcp)?),
|
||||||
NetworkFilterSelector::ICMP(_) => todo!(),
|
|
||||||
NetworkFilterSelector::TCPipv6(_) => todo!(),
|
NetworkFilterSelector::UDP(udp) => rule_xml
|
||||||
NetworkFilterSelector::UDPipv6(_) => todo!(),
|
.udp_selectors
|
||||||
NetworkFilterSelector::SCTPipv6(_) => todo!(),
|
.push(Self::rest2lib_process_layer4_selector(udp)?),
|
||||||
NetworkFilterSelector::ICMPipv6(_) => todo!(),
|
|
||||||
|
NetworkFilterSelector::SCTP(sctp) => rule_xml
|
||||||
|
.sctp_selectors
|
||||||
|
.push(Self::rest2lib_process_layer4_selector(sctp)?),
|
||||||
|
|
||||||
|
NetworkFilterSelector::ICMP(icmp) => rule_xml
|
||||||
|
.icmp_selectors
|
||||||
|
.push(Self::rest2lib_process_layer4_selector(icmp)?),
|
||||||
|
|
||||||
|
NetworkFilterSelector::TCPipv6(tcpv6) => rule_xml
|
||||||
|
.tcp_ipv6_selectors
|
||||||
|
.push(Self::rest2lib_process_layer4_selector(tcpv6)?),
|
||||||
|
|
||||||
|
NetworkFilterSelector::UDPipv6(udpv6) => rule_xml
|
||||||
|
.udp_ipv6_selectors
|
||||||
|
.push(Self::rest2lib_process_layer4_selector(udpv6)?),
|
||||||
|
|
||||||
|
NetworkFilterSelector::SCTPipv6(sctpv6) => rule_xml
|
||||||
|
.sctp_ipv6_selectors
|
||||||
|
.push(Self::rest2lib_process_layer4_selector(sctpv6)?),
|
||||||
|
|
||||||
|
NetworkFilterSelector::ICMPipv6(icmpv6) => rule_xml
|
||||||
|
.imcp_ipv6_selectors
|
||||||
|
.push(Self::rest2lib_process_layer4_selector(icmpv6)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,211 +830,6 @@ impl NetworkFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
|
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NetworkFilterAction {
|
|
||||||
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
|
|
||||||
Ok(match xml {
|
|
||||||
"drop" => Self::Drop,
|
|
||||||
"reject" => Self::Reject,
|
|
||||||
"accept" => Self::Accept,
|
|
||||||
"return" => Self::Return,
|
|
||||||
"continue" => Self::Continue,
|
|
||||||
s => {
|
|
||||||
return Err(LibVirtStructError::ParseFilteringChain(format!(
|
|
||||||
"Unkown filter action {s}!"
|
|
||||||
))
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_xml(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Drop => "drop",
|
|
||||||
Self::Reject => "reject",
|
|
||||||
Self::Accept => "accept",
|
|
||||||
Self::Return => "return",
|
|
||||||
Self::Continue => "continue",
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
pub enum NetworkFilterDirection {
|
|
||||||
In,
|
|
||||||
Out,
|
|
||||||
InOut,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NetworkFilterDirection {
|
|
||||||
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
|
|
||||||
Ok(match xml {
|
|
||||||
"in" => Self::In,
|
|
||||||
"out" => Self::Out,
|
|
||||||
"inout" => Self::InOut,
|
|
||||||
s => {
|
|
||||||
return Err(LibVirtStructError::ParseFilteringChain(format!(
|
|
||||||
"Unkown filter direction {s}!"
|
|
||||||
))
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_xml(&self) -> String {
|
|
||||||
match self {
|
|
||||||
NetworkFilterDirection::In => "in",
|
|
||||||
NetworkFilterDirection::Out => "out",
|
|
||||||
NetworkFilterDirection::InOut => "inout",
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
pub enum Layer4State {
|
|
||||||
NEW,
|
|
||||||
ESTABLISHED,
|
|
||||||
RELATED,
|
|
||||||
INVALID,
|
|
||||||
NONE,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Layer4State {
|
|
||||||
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
|
|
||||||
Ok(match xml {
|
|
||||||
"NEW" => Self::NEW,
|
|
||||||
"ESTABLISHED" => Self::ESTABLISHED,
|
|
||||||
"RELATED" => Self::RELATED,
|
|
||||||
"INVALID" => Self::INVALID,
|
|
||||||
"NONE" => Self::NONE,
|
|
||||||
s => {
|
|
||||||
return Err(LibVirtStructError::ParseFilteringChain(format!(
|
|
||||||
"Unkown layer4 state '{s}'!"
|
|
||||||
))
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_xml(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::NEW => "NEW",
|
|
||||||
Self::ESTABLISHED => "ESTABLISHED",
|
|
||||||
Self::RELATED => "RELATED",
|
|
||||||
Self::INVALID => "INVALID",
|
|
||||||
Self::NONE => "NONE",
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
pub struct NetworkSelectorMac {
|
|
||||||
src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
src_mac_mask: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
dst_mac_addr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
dst_mac_mask: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
comment: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
pub struct NetworkSelectorARP {
|
|
||||||
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
srcmacmask: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
dstmacmask: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
arpsrcipaddr: Option<NetworkFilterIPv4OrVar>,
|
|
||||||
arpsrcipmask: Option<u8>,
|
|
||||||
arpdstipaddr: Option<NetworkFilterIPv4OrVar>,
|
|
||||||
arpdstipmask: Option<u8>,
|
|
||||||
comment: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
pub struct NetworkFilterSelectorIP<const V: usize> {
|
|
||||||
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
srcmacmask: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
dstmacmask: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
srcipaddr: Option<NetworkFilterIPOrVar<V>>,
|
|
||||||
srcipmask: Option<u8>,
|
|
||||||
dstipaddr: Option<NetworkFilterIPOrVar<V>>,
|
|
||||||
dstipmask: Option<u8>,
|
|
||||||
comment: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
pub struct NetworkSelectorLayer4<IPv> {
|
|
||||||
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
|
|
||||||
srcipaddr: Option<IPv>,
|
|
||||||
srcipmask: Option<u8>,
|
|
||||||
dstipaddr: Option<IPv>,
|
|
||||||
dstipmask: Option<u8>,
|
|
||||||
/// Start of range of source IP address
|
|
||||||
srcipfrom: Option<IPv>,
|
|
||||||
/// End of range of source IP address
|
|
||||||
srcipto: Option<IPv>,
|
|
||||||
/// Start of range of destination IP address
|
|
||||||
dstipfrom: Option<IPv>,
|
|
||||||
/// End of range of destination IP address
|
|
||||||
dstipto: Option<IPv>,
|
|
||||||
srcportstart: Option<u16>,
|
|
||||||
srcportend: Option<u16>,
|
|
||||||
dstportstart: Option<u16>,
|
|
||||||
dstportend: Option<u16>,
|
|
||||||
state: Option<Layer4State>,
|
|
||||||
comment: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
#[serde(tag = "type", rename_all = "lowercase")]
|
|
||||||
pub enum NetworkFilterSelector {
|
|
||||||
All,
|
|
||||||
Mac(NetworkSelectorMac),
|
|
||||||
Arp(NetworkSelectorARP),
|
|
||||||
Rarp(NetworkSelectorARP),
|
|
||||||
IPv4(NetworkFilterSelectorIP<4>),
|
|
||||||
IPv6(NetworkFilterSelectorIP<6>),
|
|
||||||
TCP(NetworkSelectorLayer4<Ipv4Addr>),
|
|
||||||
UDP(NetworkSelectorLayer4<Ipv4Addr>),
|
|
||||||
SCTP(NetworkSelectorLayer4<Ipv4Addr>),
|
|
||||||
ICMP(NetworkSelectorLayer4<Ipv4Addr>),
|
|
||||||
TCPipv6(NetworkSelectorLayer4<Ipv6Addr>),
|
|
||||||
UDPipv6(NetworkSelectorLayer4<Ipv6Addr>),
|
|
||||||
SCTPipv6(NetworkSelectorLayer4<Ipv6Addr>),
|
|
||||||
ICMPipv6(NetworkSelectorLayer4<Ipv6Addr>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
|
||||||
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>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::libvirt_rest_structures::nw_filter::is_var_def;
|
use crate::libvirt_rest_structures::nw_filter::is_var_def;
|
||||||
|
Loading…
Reference in New Issue
Block a user