import DeleteIcon from "@mui/icons-material/Delete"; import { Button, Card, CardActions, CardContent, Grid, IconButton, Tooltip, Typography, } from "@mui/material"; import React, { PropsWithChildren } from "react"; import { NatEntry } from "../../api/NetworksApi"; import { ServerApi } from "../../api/ServerApi"; import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider"; import { IPInput } from "./IPInput"; import { PortInput } from "./PortInput"; import { RadioGroupInput } from "./RadioGroupInput"; import { SelectInput } from "./SelectInput"; import { TextInput } from "./TextInput"; export function NetNatConfiguration(p: { editable: boolean; nat: NatEntry[]; nicsList: string[]; onChange?: (nat: NatEntry[]) => void; version: 4 | 6; }): React.ReactElement { const confirm = useConfirm(); const addEntry = () => { p.nat.push({ host_ip: { type: "ip", ip: p.version === 4 ? "10.0.0.1" : "fd00::", }, host_port: { type: "single", port: 80 }, guest_ip: p.version === 4 ? "10.0.0.100" : "fd00::", guest_port: 10, protocol: "TCP", }); p.onChange?.(p.nat); }; const onDelete = async (idx: number) => { if (!(await confirm("Do you really want to delete this entry?"))) return; p.nat.splice(idx, 1); p.onChange?.(p.nat); }; return ( <> {p.nat.map((e, num) => ( p.onChange?.(p.nat)} onDelete={() => onDelete(num)} /> ))} {p.nat.length === 0 && ( You have not set any NAT entry yet. )} {p.editable && } ); } function NatEntryForm(p: { editable: boolean; version: 4 | 6; entry: NatEntry; onChange?: () => void; onDelete: () => void; nicsList: string[]; }): React.ReactElement { const guestPortEnd = p.entry.host_port.type === "range" ? p.entry.host_port.end - p.entry.host_port.start + p.entry.guest_port : undefined; return ( { p.entry.protocol = v as any; p.onChange?.(); }} /> { p.entry.comment = v; p.onChange?.(); }} size={ServerApi.Config.constraints.net_nat_comment_size} /> {/* Host conf */} { p.entry.host_ip.type = v as any; p.onChange?.(); }} /> {p.entry.host_ip.type === "ip" && ( { if (p.entry.host_ip.type === "ip") p.entry.host_ip.ip = v!; p.onChange?.(); }} /> )} {p.entry.host_ip.type === "interface" && ( { return { value: n, }; })} onValueChange={(v) => { if (p.entry.host_ip.type === "interface") p.entry.host_ip.name = v!; p.onChange?.(); }} /> )} { p.entry.guest_ip = v!; p.onChange?.(); }} /> { p.entry.host_port.type = v as any; p.onChange?.(); }} /> {p.entry.host_port.type === "single" && ( { if (p.entry.host_port.type === "single") p.entry.host_port.port = v!; p.onChange?.(); }} /> )} {p.entry.host_port.type === "range" && (
{ if (p.entry.host_port.type === "range") p.entry.host_port.start = v!; p.onChange?.(); }} /> { if (p.entry.host_port.type === "range") p.entry.host_port.end = v!; p.onChange?.(); }} />
)}
{ p.entry.guest_port = v!; p.onChange?.(); }} /> {guestPortEnd && } {guestPortEnd && ( { p.entry.guest_port = v!; p.onChange?.(); }} /> )}
{p.editable && ( )}
); } function NATEntryProp( p: PropsWithChildren<{ label?: string }> ): React.ReactElement { return ( {p.label && ( {p.label} )} {p.children} ); } function PortSpacer(): React.ReactElement { return ; }