Add Layer4 rules support
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
				
			|||||||
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
 | 
					import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
 | 
				
			||||||
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
 | 
					import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
 | 
				
			||||||
import DeleteIcon from "@mui/icons-material/Delete";
 | 
					import DeleteIcon from "@mui/icons-material/Delete";
 | 
				
			||||||
 | 
					import PlaylistAddIcon from "@mui/icons-material/PlaylistAdd";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Button,
 | 
					  Button,
 | 
				
			||||||
  Card,
 | 
					  Card,
 | 
				
			||||||
@@ -11,20 +12,20 @@ import {
 | 
				
			|||||||
  Tooltip,
 | 
					  Tooltip,
 | 
				
			||||||
} from "@mui/material";
 | 
					} from "@mui/material";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  NWFSArp,
 | 
					 | 
				
			||||||
  NWFSArpOrRARP,
 | 
					  NWFSArpOrRARP,
 | 
				
			||||||
  NWFSIPBase,
 | 
					  NWFSIPBase,
 | 
				
			||||||
 | 
					  NWFSLayer4Base,
 | 
				
			||||||
  NWFSMac,
 | 
					  NWFSMac,
 | 
				
			||||||
  NWFSelector,
 | 
					  NWFSelector,
 | 
				
			||||||
  NWFilterRule,
 | 
					  NWFilterRule,
 | 
				
			||||||
} from "../../api/NWFilterApi";
 | 
					} from "../../api/NWFilterApi";
 | 
				
			||||||
 | 
					import { ServerApi } from "../../api/ServerApi";
 | 
				
			||||||
import { EditSection } from "./EditSection";
 | 
					import { EditSection } from "./EditSection";
 | 
				
			||||||
 | 
					import { IPInput, IPInputWithMask } from "./IPInput";
 | 
				
			||||||
 | 
					import { MACInput } from "./MACInput";
 | 
				
			||||||
 | 
					import { PortInput } from "./PortInput";
 | 
				
			||||||
import { SelectInput } from "./SelectInput";
 | 
					import { SelectInput } from "./SelectInput";
 | 
				
			||||||
import { TextInput } from "./TextInput";
 | 
					import { TextInput } from "./TextInput";
 | 
				
			||||||
import { ServerApi } from "../../api/ServerApi";
 | 
					 | 
				
			||||||
import PlaylistAddIcon from "@mui/icons-material/PlaylistAdd";
 | 
					 | 
				
			||||||
import { MACInput } from "./MACInput";
 | 
					 | 
				
			||||||
import { IPInput, IPInputWithMask } from "./IPInput";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function NWFilterRules(p: {
 | 
					export function NWFilterRules(p: {
 | 
				
			||||||
  editable: boolean;
 | 
					  editable: boolean;
 | 
				
			||||||
@@ -255,6 +256,20 @@ function NWFSelectorEdit(p: {
 | 
				
			|||||||
            <NWFSelectorIP {...p} selector={p.selector} version={6} />
 | 
					            <NWFSelectorIP {...p} selector={p.selector} version={6} />
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {(p.selector.type === "tcp" ||
 | 
				
			||||||
 | 
					            p.selector.type === "udp" ||
 | 
				
			||||||
 | 
					            p.selector.type === "sctp" ||
 | 
				
			||||||
 | 
					            p.selector.type === "icmp") && (
 | 
				
			||||||
 | 
					            <NWFSelectorLayer4 {...p} selector={p.selector} version={4} />
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {(p.selector.type === "tcpipv6" ||
 | 
				
			||||||
 | 
					            p.selector.type === "udpipv6" ||
 | 
				
			||||||
 | 
					            p.selector.type === "sctpipv6" ||
 | 
				
			||||||
 | 
					            p.selector.type === "icmpipv6") && (
 | 
				
			||||||
 | 
					            <NWFSelectorLayer4 {...p} selector={p.selector} version={6} />
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <TextInput
 | 
					          <TextInput
 | 
				
			||||||
            editable={p.editable}
 | 
					            editable={p.editable}
 | 
				
			||||||
            label="Comment"
 | 
					            label="Comment"
 | 
				
			||||||
@@ -354,9 +369,9 @@ function NWFSelectorArp(
 | 
				
			|||||||
      <MACInput
 | 
					      <MACInput
 | 
				
			||||||
        {...p}
 | 
					        {...p}
 | 
				
			||||||
        label="Src mac mask"
 | 
					        label="Src mac mask"
 | 
				
			||||||
        value={p.selector.srcmacaddr}
 | 
					        value={p.selector.srcmacmask}
 | 
				
			||||||
        onValueChange={(v) => {
 | 
					        onValueChange={(v) => {
 | 
				
			||||||
          p.selector.srcmacaddr = v;
 | 
					          p.selector.srcmacmask = v;
 | 
				
			||||||
          p.onChange?.();
 | 
					          p.onChange?.();
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
@@ -372,9 +387,9 @@ function NWFSelectorArp(
 | 
				
			|||||||
      <MACInput
 | 
					      <MACInput
 | 
				
			||||||
        {...p}
 | 
					        {...p}
 | 
				
			||||||
        label="Dst mac mask"
 | 
					        label="Dst mac mask"
 | 
				
			||||||
        value={p.selector.dstmacaddr}
 | 
					        value={p.selector.dstmacmask}
 | 
				
			||||||
        onValueChange={(v) => {
 | 
					        onValueChange={(v) => {
 | 
				
			||||||
          p.selector.dstmacaddr = v;
 | 
					          p.selector.dstmacmask = v;
 | 
				
			||||||
          p.onChange?.();
 | 
					          p.onChange?.();
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
@@ -423,9 +438,9 @@ function NWFSelectorIP(
 | 
				
			|||||||
      <MACInput
 | 
					      <MACInput
 | 
				
			||||||
        {...p}
 | 
					        {...p}
 | 
				
			||||||
        label="Src mac mask"
 | 
					        label="Src mac mask"
 | 
				
			||||||
        value={p.selector.srcmacaddr}
 | 
					        value={p.selector.srcmacmask}
 | 
				
			||||||
        onValueChange={(v) => {
 | 
					        onValueChange={(v) => {
 | 
				
			||||||
          p.selector.srcmacaddr = v;
 | 
					          p.selector.srcmacmask = v;
 | 
				
			||||||
          p.onChange?.();
 | 
					          p.onChange?.();
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
@@ -441,9 +456,9 @@ function NWFSelectorIP(
 | 
				
			|||||||
      <MACInput
 | 
					      <MACInput
 | 
				
			||||||
        {...p}
 | 
					        {...p}
 | 
				
			||||||
        label="Dst mac mask"
 | 
					        label="Dst mac mask"
 | 
				
			||||||
        value={p.selector.dstmacaddr}
 | 
					        value={p.selector.dstmacmask}
 | 
				
			||||||
        onValueChange={(v) => {
 | 
					        onValueChange={(v) => {
 | 
				
			||||||
          p.selector.dstmacaddr = v;
 | 
					          p.selector.dstmacmask = v;
 | 
				
			||||||
          p.onChange?.();
 | 
					          p.onChange?.();
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
@@ -474,3 +489,134 @@ function NWFSelectorIP(
 | 
				
			|||||||
    </>
 | 
					    </>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function NWFSelectorLayer4(
 | 
				
			||||||
 | 
					  p: SpecificSelectorEditorWithIPVersion<NWFSLayer4Base>
 | 
				
			||||||
 | 
					): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <MACInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Src mac address"
 | 
				
			||||||
 | 
					        value={p.selector.srcmacaddr}
 | 
				
			||||||
 | 
					        onValueChange={(v) => {
 | 
				
			||||||
 | 
					          p.selector.srcmacaddr = v;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <IPInputWithMask
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Source IP address / mask"
 | 
				
			||||||
 | 
					        ip={p.selector.srcipaddr}
 | 
				
			||||||
 | 
					        mask={p.selector.srcipmask}
 | 
				
			||||||
 | 
					        version={p.version}
 | 
				
			||||||
 | 
					        onValueChange={(ip, mask) => {
 | 
				
			||||||
 | 
					          p.selector.srcipaddr = ip;
 | 
				
			||||||
 | 
					          p.selector.srcipmask = mask;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <IPInputWithMask
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Destination IP address / mask"
 | 
				
			||||||
 | 
					        ip={p.selector.dstipaddr}
 | 
				
			||||||
 | 
					        mask={p.selector.dstipmask}
 | 
				
			||||||
 | 
					        version={p.version}
 | 
				
			||||||
 | 
					        onValueChange={(ip, mask) => {
 | 
				
			||||||
 | 
					          p.selector.dstipaddr = ip;
 | 
				
			||||||
 | 
					          p.selector.dstipmask = mask;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <IPInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Source IP from"
 | 
				
			||||||
 | 
					        value={p.selector.srcipfrom}
 | 
				
			||||||
 | 
					        onValueChange={(ip) => {
 | 
				
			||||||
 | 
					          p.selector.srcipfrom = ip;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <IPInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Source IP to"
 | 
				
			||||||
 | 
					        value={p.selector.srcipto}
 | 
				
			||||||
 | 
					        onValueChange={(ip) => {
 | 
				
			||||||
 | 
					          p.selector.srcipto = ip;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <IPInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Destination IP from"
 | 
				
			||||||
 | 
					        value={p.selector.dstipfrom}
 | 
				
			||||||
 | 
					        onValueChange={(ip) => {
 | 
				
			||||||
 | 
					          p.selector.dstipfrom = ip;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <IPInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Destination IP to"
 | 
				
			||||||
 | 
					        value={p.selector.dstipto}
 | 
				
			||||||
 | 
					        onValueChange={(ip) => {
 | 
				
			||||||
 | 
					          p.selector.dstipto = ip;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <PortInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Source port start"
 | 
				
			||||||
 | 
					        value={p.selector.srcportstart}
 | 
				
			||||||
 | 
					        onChange={(port) => {
 | 
				
			||||||
 | 
					          p.selector.srcportstart = port;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <PortInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Source port end"
 | 
				
			||||||
 | 
					        value={p.selector.srcportend}
 | 
				
			||||||
 | 
					        onChange={(port) => {
 | 
				
			||||||
 | 
					          p.selector.srcportend = port;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <PortInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Destination port start"
 | 
				
			||||||
 | 
					        value={p.selector.dstportstart}
 | 
				
			||||||
 | 
					        onChange={(port) => {
 | 
				
			||||||
 | 
					          p.selector.dstportstart = port;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <PortInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Destination port end"
 | 
				
			||||||
 | 
					        value={p.selector.dstportend}
 | 
				
			||||||
 | 
					        onChange={(port) => {
 | 
				
			||||||
 | 
					          p.selector.dstportend = port;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <SelectInput
 | 
				
			||||||
 | 
					        {...p}
 | 
				
			||||||
 | 
					        label="Connection state"
 | 
				
			||||||
 | 
					        value={p.selector.state}
 | 
				
			||||||
 | 
					        onValueChange={(s) => {
 | 
				
			||||||
 | 
					          p.selector.state = s as any;
 | 
				
			||||||
 | 
					          p.onChange?.();
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        options={[
 | 
				
			||||||
 | 
					          { label: "None", value: undefined },
 | 
				
			||||||
 | 
					          { label: "NEW", value: "NEW" },
 | 
				
			||||||
 | 
					          { label: "ESTABLISHED", value: "ESTABLISHED" },
 | 
				
			||||||
 | 
					          { label: "RELATED", value: "RELATED" },
 | 
				
			||||||
 | 
					          { label: "INVALID", value: "INVALID" },
 | 
				
			||||||
 | 
					          { label: "NONE", value: "NONE" },
 | 
				
			||||||
 | 
					        ]}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								virtweb_frontend/src/widgets/forms/PortInput.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								virtweb_frontend/src/widgets/forms/PortInput.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					import { TextInput } from "./TextInput";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function PortInput(p: {
 | 
				
			||||||
 | 
					  editable: boolean;
 | 
				
			||||||
 | 
					  label: string;
 | 
				
			||||||
 | 
					  value?: number;
 | 
				
			||||||
 | 
					  onChange: (value: number | undefined) => void;
 | 
				
			||||||
 | 
					}): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <TextInput
 | 
				
			||||||
 | 
					      {...p}
 | 
				
			||||||
 | 
					      value={p.value?.toString() ?? ""}
 | 
				
			||||||
 | 
					      type="number"
 | 
				
			||||||
 | 
					      onValueChange={(v) => {
 | 
				
			||||||
 | 
					        p.onChange?.(sanitizePort(v));
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function sanitizePort(port?: string): number | undefined {
 | 
				
			||||||
 | 
					  if (port === undefined) return undefined;
 | 
				
			||||||
 | 
					  const val = Number(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (val < 0) return 0;
 | 
				
			||||||
 | 
					  if (val > 65535) return 65535;
 | 
				
			||||||
 | 
					  return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user