Can edit MAC rules

This commit is contained in:
Pierre HUBERT 2024-01-04 12:26:51 +01:00
parent 7d7a052f5f
commit ad45c0d654
4 changed files with 242 additions and 27 deletions

View File

@ -11,7 +11,10 @@ pub struct NetworkFilterRefXML {
#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[serde(rename = "all")]
pub struct NetworkFilterRuleProtocolAll {}
pub struct NetworkFilterRuleProtocolAllXML {
#[serde(rename = "@comment", skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[serde(rename = "mac")]
@ -128,7 +131,11 @@ pub struct NetworkFilterRuleXML {
/// Match all protocols
#[serde(default, rename = "all", skip_serializing_if = "Vec::is_empty")]
pub all_selectors: Vec<NetworkFilterRuleProtocolAll>,
pub all_selectors: Vec<NetworkFilterRuleProtocolAllXML>,
/// Match all ipv6 protocols
#[serde(default, rename = "all-ipv6", skip_serializing_if = "Vec::is_empty")]
pub all_ipv6_selectors: Vec<NetworkFilterRuleProtocolAllXML>,
/// Match mac protocol
#[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]

View File

@ -1,5 +1,5 @@
use crate::libvirt_lib_structures::nwfilter::{
NetworkFilterRefXML, NetworkFilterRuleProtocolAll, NetworkFilterRuleProtocolArpXML,
NetworkFilterRefXML, NetworkFilterRuleProtocolAllXML, NetworkFilterRuleProtocolArpXML,
NetworkFilterRuleProtocolIpvx, NetworkFilterRuleProtocolLayer4, NetworkFilterRuleProtocolMac,
NetworkFilterRuleXML, NetworkFilterXML,
};
@ -308,6 +308,11 @@ impl Layer4State {
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorAll {
comment: Option<String>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorMac {
src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
@ -369,7 +374,7 @@ pub struct NetworkFilterSelectorLayer4<IPv> {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum NetworkFilterSelector {
All,
All(NetworkSelectorAll),
Mac(NetworkSelectorMac),
Arp(NetworkSelectorARP),
Rarp(NetworkSelectorARP),
@ -379,6 +384,7 @@ pub enum NetworkFilterSelector {
UDP(NetworkFilterSelectorLayer4<Ipv4Addr>),
SCTP(NetworkFilterSelectorLayer4<Ipv4Addr>),
ICMP(NetworkFilterSelectorLayer4<Ipv4Addr>),
Allipv6(NetworkSelectorAll),
TCPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
UDPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
SCTPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
@ -410,8 +416,10 @@ pub struct NetworkFilter {
}
impl NetworkFilter {
fn lib2rest_process_all_rule(_n: &NetworkFilterRuleProtocolAll) -> NetworkFilterSelector {
NetworkFilterSelector::All
fn lib2rest_process_all_rule(n: &NetworkFilterRuleProtocolAllXML) -> NetworkSelectorAll {
NetworkSelectorAll {
comment: n.comment.clone(),
}
}
fn lib2rest_process_mac_rule(n: &NetworkFilterRuleProtocolMac) -> NetworkFilterSelector {
@ -481,16 +489,24 @@ impl NetworkFilter {
for rule in &xml.rules {
let mut selectors = Vec::new();
// All selector
// All selectors
selectors.append(
&mut rule
.all_selectors
.iter()
.map(Self::lib2rest_process_all_rule)
.map(|r| NetworkFilterSelector::All(Self::lib2rest_process_all_rule(r)))
.collect(),
);
// Mac rules
selectors.append(
&mut rule
.all_ipv6_selectors
.iter()
.map(|r| NetworkFilterSelector::Allipv6(Self::lib2rest_process_all_rule(r)))
.collect(),
);
// Mac selectors
selectors.append(
&mut rule
.mac_selectors
@ -499,7 +515,7 @@ impl NetworkFilter {
.collect(),
);
// ARP - RARP rules
// ARP - RARP selectors
selectors.append(
&mut rule
.arp_selectors
@ -515,7 +531,7 @@ impl NetworkFilter {
.collect(),
);
// IPv4 - IPv6 rules
// IPv4 - IPv6 selectors
selectors.append(
&mut rule
.ipv4_selectors
@ -531,7 +547,7 @@ impl NetworkFilter {
.collect(),
);
// Layer 4 protocols
// Layer 4 protocols selectors
selectors.append(
&mut rule
.tcp_selectors
@ -648,6 +664,14 @@ impl NetworkFilter {
})
}
fn rest2lib_process_all_selector(
selector: &NetworkSelectorAll,
) -> anyhow::Result<NetworkFilterRuleProtocolAllXML> {
Ok(NetworkFilterRuleProtocolAllXML {
comment: extract_nw_filter_comment(&selector.comment)?,
})
}
fn rest2lib_process_arp_selector(
selector: &NetworkSelectorARP,
) -> anyhow::Result<NetworkFilterRuleProtocolArpXML> {
@ -714,8 +738,16 @@ impl NetworkFilter {
for sel in &rule.selectors {
match sel {
NetworkFilterSelector::All => {
rule_xml.all_selectors.push(NetworkFilterRuleProtocolAll {});
NetworkFilterSelector::All(all) => {
rule_xml
.all_selectors
.push(Self::rest2lib_process_all_selector(all)?);
}
NetworkFilterSelector::Allipv6(all) => {
rule_xml
.all_ipv6_selectors
.push(Self::rest2lib_process_all_selector(all)?);
}
NetworkFilterSelector::Mac(mac) => {

View File

@ -6,10 +6,18 @@ export interface NWFilterChain {
suffix?: string;
}
export interface NWFSAll {
type: "all";
export interface NWFSAllBase {
comment?: string;
}
export type NWFSAll = NWFSAllBase & {
type: "all";
};
export type NWFSAllIPv6 = NWFSAllBase & {
type: "allipv6";
};
export interface NWFSMac {
type: "mac";
src_mac_addr?: string;
@ -91,6 +99,7 @@ export type NFWSICMPv6 = NWFSLayer4Base & { type: "icmpipv6" };
export type NWFSelector =
| NWFSAll
| NWFSAllIPv6
| NWFSMac
| NWFSArp
| NWFSRArp

View File

@ -7,12 +7,16 @@ import {
CardActions,
CardContent,
IconButton,
Paper,
Tooltip,
} from "@mui/material";
import { NWFilterRule } from "../../api/NWFilterApi";
import { NWFSMac, NWFSelector, NWFilterRule } from "../../api/NWFilterApi";
import { EditSection } from "./EditSection";
import { SelectInput } from "./SelectInput";
import { TextInput } from "./TextInput";
import { ServerApi } from "../../api/ServerApi";
import PlaylistAddIcon from "@mui/icons-material/PlaylistAdd";
import { MACInput } from "./MACInput";
export function NWFilterRules(p: {
editable: boolean;
@ -72,6 +76,18 @@ function NWRuleEdit(p: {
onGoDown?: () => void;
onDelete: () => void;
}): React.ReactElement {
const addSelector = () => {
p.rule.selectors.push({
type: "all",
});
p.onChange?.();
};
const deleteSelector = (num: number) => {
p.rule.selectors.splice(num, 1);
p.onChange?.();
};
return (
<Card style={{ margin: "30px" }} elevation={3}>
<CardContent>
@ -120,23 +136,51 @@ function NWRuleEdit(p: {
size={ServerApi.Config.constraints.nwfilter_priority}
/>
</div>
{p.rule.selectors.map((s, n) => (
<NWFSelectorEdit
key={n}
editable={p.editable}
onChange={p.onChange}
selector={s}
onDelete={() => deleteSelector(n)}
/>
))}
</CardContent>
<CardActions>
{p.editable && (
<div style={{ display: "flex", width: "100%" }}>
<IconButton color="error" onClick={p.onDelete}>
<DeleteIcon />
</IconButton>
<Tooltip title="Remove the rule">
<IconButton color="error" onClick={p.onDelete}>
<DeleteIcon />
</IconButton>
</Tooltip>
<span style={{ flex: 1 }}></span>
{p.onGoUp && (
<IconButton onClick={p.onGoUp}>
<ArrowUpwardIcon />
</IconButton>
{ServerApi.Config.constraints.nwfilter_selectors_count.max >
p.rule.selectors.length && (
<Tooltip title="Add a selector">
<IconButton onClick={addSelector}>
<PlaylistAddIcon />
</IconButton>
</Tooltip>
)}
{p.onGoUp && (
<Tooltip title="Move rule upward">
<IconButton onClick={p.onGoUp}>
<ArrowUpwardIcon />
</IconButton>
</Tooltip>
)}
{p.onGoDown && (
<IconButton onClick={p.onGoDown}>
<ArrowDownwardIcon />
</IconButton>
<Tooltip title="Move rule downward">
<IconButton onClick={p.onGoDown}>
<ArrowDownwardIcon />
</IconButton>
</Tooltip>
)}
</div>
)}
@ -144,3 +188,126 @@ function NWRuleEdit(p: {
</Card>
);
}
function NWFSelectorEdit(p: {
editable: boolean;
selector: NWFSelector;
onDelete: () => void;
onChange?: () => void;
}): React.ReactElement {
return (
<Paper elevation={10} style={{ padding: "10px" }}>
<div style={{ display: "flex", width: "100%" }}>
<div style={{ flex: 1 }}>
<SelectInput
editable={p.editable}
label="Type"
onValueChange={(v) => {
p.selector.type = v! as any;
p.onChange?.();
}}
value={p.selector.type}
options={[
{ label: "All over IPv4", value: "all" },
{ label: "All over IPv6", value: "allipv6" },
{ label: "MAC (Ethernet)", value: "mac" },
{ label: "ARP", value: "arp" },
{ label: "RARP", value: "rarp" },
{ label: "IPv4", value: "ipv4" },
{ label: "IPv6", value: "ipv6" },
{ label: "TCP over IPv4", value: "tcp" },
{ label: "UDP over IPv4", value: "udp" },
{ label: "SCTP over IPv4", value: "sctp" },
{ label: "ICMPv4", value: "icmp" },
{ label: "TCP over IPv6", value: "tcpipv6" },
{ label: "UDP over IPv6", value: "udpipv6" },
{ label: "SCTP over IPv6", value: "sctpipv6" },
{ label: "ICMPv6", value: "icmpipv6" },
]}
/>
{p.selector.type === "mac" && (
<NWFSelectorMac {...p} selector={p.selector} />
)}
<TextInput
editable={p.editable}
label="Comment"
value={p.selector.comment}
onValueChange={(v) => {
p.selector.comment = v;
p.onChange?.();
}}
size={ServerApi.Config.constraints.nwfilter_comment_size}
/>
</div>
{p.editable && (
<div style={{ display: "flex", justifyContent: "center" }}>
<Tooltip title="Remove the selector">
<IconButton color="error" onClick={p.onDelete}>
<DeleteIcon />
</IconButton>
</Tooltip>
</div>
)}
</div>
</Paper>
);
}
interface SpecificSelectorEditor<E> {
editable: boolean;
selector: E;
onChange?: () => void;
}
function NWFSelectorMac(
p: SpecificSelectorEditor<NWFSMac>
): React.ReactElement {
return (
<>
<MACInput
{...p}
label="Src mac address"
value={p.selector.src_mac_addr}
onValueChange={(v) => {
p.selector.src_mac_addr = v;
p.onChange?.();
}}
/>
<MACInput
{...p}
label="Src mac mask"
value={p.selector.src_mac_mask}
onValueChange={(v) => {
p.selector.src_mac_mask = v;
p.onChange?.();
}}
/>
<MACInput
{...p}
label="Dst mac address"
value={p.selector.dst_mac_addr}
onValueChange={(v) => {
p.selector.dst_mac_addr = v;
p.onChange?.();
}}
/>
<MACInput
{...p}
label="Dst mac mask"
value={p.selector.dst_mac_mask}
onValueChange={(v) => {
p.selector.dst_mac_mask = v;
p.onChange?.();
}}
/>
</>
);
}