Can edit MAC rules
This commit is contained in:
parent
7d7a052f5f
commit
ad45c0d654
@ -11,7 +11,10 @@ pub struct NetworkFilterRefXML {
|
|||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||||
#[serde(rename = "all")]
|
#[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)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||||
#[serde(rename = "mac")]
|
#[serde(rename = "mac")]
|
||||||
@ -128,7 +131,11 @@ pub struct NetworkFilterRuleXML {
|
|||||||
|
|
||||||
/// Match all protocols
|
/// Match all protocols
|
||||||
#[serde(default, rename = "all", skip_serializing_if = "Vec::is_empty")]
|
#[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
|
/// Match mac protocol
|
||||||
#[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::libvirt_lib_structures::nwfilter::{
|
use crate::libvirt_lib_structures::nwfilter::{
|
||||||
NetworkFilterRefXML, NetworkFilterRuleProtocolAll, NetworkFilterRuleProtocolArpXML,
|
NetworkFilterRefXML, NetworkFilterRuleProtocolAllXML, NetworkFilterRuleProtocolArpXML,
|
||||||
NetworkFilterRuleProtocolIpvx, NetworkFilterRuleProtocolLayer4, NetworkFilterRuleProtocolMac,
|
NetworkFilterRuleProtocolIpvx, NetworkFilterRuleProtocolLayer4, NetworkFilterRuleProtocolMac,
|
||||||
NetworkFilterRuleXML, NetworkFilterXML,
|
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)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
pub struct NetworkSelectorMac {
|
pub struct NetworkSelectorMac {
|
||||||
src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
|
src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
|
||||||
@ -369,7 +374,7 @@ pub struct NetworkFilterSelectorLayer4<IPv> {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "type", rename_all = "lowercase")]
|
#[serde(tag = "type", rename_all = "lowercase")]
|
||||||
pub enum NetworkFilterSelector {
|
pub enum NetworkFilterSelector {
|
||||||
All,
|
All(NetworkSelectorAll),
|
||||||
Mac(NetworkSelectorMac),
|
Mac(NetworkSelectorMac),
|
||||||
Arp(NetworkSelectorARP),
|
Arp(NetworkSelectorARP),
|
||||||
Rarp(NetworkSelectorARP),
|
Rarp(NetworkSelectorARP),
|
||||||
@ -379,6 +384,7 @@ pub enum NetworkFilterSelector {
|
|||||||
UDP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
UDP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
SCTP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
SCTP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
ICMP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
ICMP(NetworkFilterSelectorLayer4<Ipv4Addr>),
|
||||||
|
Allipv6(NetworkSelectorAll),
|
||||||
TCPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
TCPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
UDPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
UDPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
SCTPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
SCTPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
|
||||||
@ -410,8 +416,10 @@ pub struct NetworkFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkFilter {
|
impl NetworkFilter {
|
||||||
fn lib2rest_process_all_rule(_n: &NetworkFilterRuleProtocolAll) -> NetworkFilterSelector {
|
fn lib2rest_process_all_rule(n: &NetworkFilterRuleProtocolAllXML) -> NetworkSelectorAll {
|
||||||
NetworkFilterSelector::All
|
NetworkSelectorAll {
|
||||||
|
comment: n.comment.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lib2rest_process_mac_rule(n: &NetworkFilterRuleProtocolMac) -> NetworkFilterSelector {
|
fn lib2rest_process_mac_rule(n: &NetworkFilterRuleProtocolMac) -> NetworkFilterSelector {
|
||||||
@ -481,16 +489,24 @@ impl NetworkFilter {
|
|||||||
for rule in &xml.rules {
|
for rule in &xml.rules {
|
||||||
let mut selectors = Vec::new();
|
let mut selectors = Vec::new();
|
||||||
|
|
||||||
// All selector
|
// All selectors
|
||||||
selectors.append(
|
selectors.append(
|
||||||
&mut rule
|
&mut rule
|
||||||
.all_selectors
|
.all_selectors
|
||||||
.iter()
|
.iter()
|
||||||
.map(Self::lib2rest_process_all_rule)
|
.map(|r| NetworkFilterSelector::All(Self::lib2rest_process_all_rule(r)))
|
||||||
.collect(),
|
.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(
|
selectors.append(
|
||||||
&mut rule
|
&mut rule
|
||||||
.mac_selectors
|
.mac_selectors
|
||||||
@ -499,7 +515,7 @@ impl NetworkFilter {
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ARP - RARP rules
|
// ARP - RARP selectors
|
||||||
selectors.append(
|
selectors.append(
|
||||||
&mut rule
|
&mut rule
|
||||||
.arp_selectors
|
.arp_selectors
|
||||||
@ -515,7 +531,7 @@ impl NetworkFilter {
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// IPv4 - IPv6 rules
|
// IPv4 - IPv6 selectors
|
||||||
selectors.append(
|
selectors.append(
|
||||||
&mut rule
|
&mut rule
|
||||||
.ipv4_selectors
|
.ipv4_selectors
|
||||||
@ -531,7 +547,7 @@ impl NetworkFilter {
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Layer 4 protocols
|
// Layer 4 protocols selectors
|
||||||
selectors.append(
|
selectors.append(
|
||||||
&mut rule
|
&mut rule
|
||||||
.tcp_selectors
|
.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(
|
fn rest2lib_process_arp_selector(
|
||||||
selector: &NetworkSelectorARP,
|
selector: &NetworkSelectorARP,
|
||||||
) -> anyhow::Result<NetworkFilterRuleProtocolArpXML> {
|
) -> anyhow::Result<NetworkFilterRuleProtocolArpXML> {
|
||||||
@ -714,8 +738,16 @@ impl NetworkFilter {
|
|||||||
|
|
||||||
for sel in &rule.selectors {
|
for sel in &rule.selectors {
|
||||||
match sel {
|
match sel {
|
||||||
NetworkFilterSelector::All => {
|
NetworkFilterSelector::All(all) => {
|
||||||
rule_xml.all_selectors.push(NetworkFilterRuleProtocolAll {});
|
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) => {
|
NetworkFilterSelector::Mac(mac) => {
|
||||||
|
@ -6,10 +6,18 @@ export interface NWFilterChain {
|
|||||||
suffix?: string;
|
suffix?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NWFSAll {
|
export interface NWFSAllBase {
|
||||||
type: "all";
|
comment?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type NWFSAll = NWFSAllBase & {
|
||||||
|
type: "all";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NWFSAllIPv6 = NWFSAllBase & {
|
||||||
|
type: "allipv6";
|
||||||
|
};
|
||||||
|
|
||||||
export interface NWFSMac {
|
export interface NWFSMac {
|
||||||
type: "mac";
|
type: "mac";
|
||||||
src_mac_addr?: string;
|
src_mac_addr?: string;
|
||||||
@ -91,6 +99,7 @@ export type NFWSICMPv6 = NWFSLayer4Base & { type: "icmpipv6" };
|
|||||||
|
|
||||||
export type NWFSelector =
|
export type NWFSelector =
|
||||||
| NWFSAll
|
| NWFSAll
|
||||||
|
| NWFSAllIPv6
|
||||||
| NWFSMac
|
| NWFSMac
|
||||||
| NWFSArp
|
| NWFSArp
|
||||||
| NWFSRArp
|
| NWFSRArp
|
||||||
|
@ -7,12 +7,16 @@ import {
|
|||||||
CardActions,
|
CardActions,
|
||||||
CardContent,
|
CardContent,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
Paper,
|
||||||
|
Tooltip,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { NWFilterRule } from "../../api/NWFilterApi";
|
import { NWFSMac, NWFSelector, NWFilterRule } from "../../api/NWFilterApi";
|
||||||
import { EditSection } from "./EditSection";
|
import { EditSection } from "./EditSection";
|
||||||
import { SelectInput } from "./SelectInput";
|
import { SelectInput } from "./SelectInput";
|
||||||
import { TextInput } from "./TextInput";
|
import { TextInput } from "./TextInput";
|
||||||
import { ServerApi } from "../../api/ServerApi";
|
import { ServerApi } from "../../api/ServerApi";
|
||||||
|
import PlaylistAddIcon from "@mui/icons-material/PlaylistAdd";
|
||||||
|
import { MACInput } from "./MACInput";
|
||||||
|
|
||||||
export function NWFilterRules(p: {
|
export function NWFilterRules(p: {
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
@ -72,6 +76,18 @@ function NWRuleEdit(p: {
|
|||||||
onGoDown?: () => void;
|
onGoDown?: () => void;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
}): React.ReactElement {
|
}): 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 (
|
return (
|
||||||
<Card style={{ margin: "30px" }} elevation={3}>
|
<Card style={{ margin: "30px" }} elevation={3}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@ -120,23 +136,51 @@ function NWRuleEdit(p: {
|
|||||||
size={ServerApi.Config.constraints.nwfilter_priority}
|
size={ServerApi.Config.constraints.nwfilter_priority}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{p.rule.selectors.map((s, n) => (
|
||||||
|
<NWFSelectorEdit
|
||||||
|
key={n}
|
||||||
|
editable={p.editable}
|
||||||
|
onChange={p.onChange}
|
||||||
|
selector={s}
|
||||||
|
onDelete={() => deleteSelector(n)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardActions>
|
<CardActions>
|
||||||
{p.editable && (
|
{p.editable && (
|
||||||
<div style={{ display: "flex", width: "100%" }}>
|
<div style={{ display: "flex", width: "100%" }}>
|
||||||
|
<Tooltip title="Remove the rule">
|
||||||
<IconButton color="error" onClick={p.onDelete}>
|
<IconButton color="error" onClick={p.onDelete}>
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<span style={{ flex: 1 }}></span>
|
<span style={{ flex: 1 }}></span>
|
||||||
|
|
||||||
|
{ServerApi.Config.constraints.nwfilter_selectors_count.max >
|
||||||
|
p.rule.selectors.length && (
|
||||||
|
<Tooltip title="Add a selector">
|
||||||
|
<IconButton onClick={addSelector}>
|
||||||
|
<PlaylistAddIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
{p.onGoUp && (
|
{p.onGoUp && (
|
||||||
|
<Tooltip title="Move rule upward">
|
||||||
<IconButton onClick={p.onGoUp}>
|
<IconButton onClick={p.onGoUp}>
|
||||||
<ArrowUpwardIcon />
|
<ArrowUpwardIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{p.onGoDown && (
|
{p.onGoDown && (
|
||||||
|
<Tooltip title="Move rule downward">
|
||||||
<IconButton onClick={p.onGoDown}>
|
<IconButton onClick={p.onGoDown}>
|
||||||
<ArrowDownwardIcon />
|
<ArrowDownwardIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -144,3 +188,126 @@ function NWRuleEdit(p: {
|
|||||||
</Card>
|
</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?.();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user