Port forwarding is working
This commit is contained in:
		@@ -1,11 +1,18 @@
 | 
				
			|||||||
use crate::constants;
 | 
					use crate::constants;
 | 
				
			||||||
use crate::libvirt_rest_structures::net::NetworkName;
 | 
					use crate::libvirt_rest_structures::net::NetworkName;
 | 
				
			||||||
use crate::nat::nat_definition::NetNat;
 | 
					use crate::nat::nat_definition::{Nat, NatSourceIP, NetNat};
 | 
				
			||||||
use crate::utils::net_utils;
 | 
					use crate::utils::net_utils;
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
use std::net::IpAddr;
 | 
					use std::net::IpAddr;
 | 
				
			||||||
use std::path::{Path, PathBuf};
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
 | 
					use std::process::{Command, ExitStatus};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(thiserror::Error, Debug)]
 | 
				
			||||||
 | 
					enum NatConfModeError {
 | 
				
			||||||
 | 
					    #[error("UpdateFirewall failed!")]
 | 
				
			||||||
 | 
					    UpdateFirewall,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// VirtWeb NAT configuration mode. This executable should never be executed manually
 | 
					/// VirtWeb NAT configuration mode. This executable should never be executed manually
 | 
				
			||||||
#[derive(Parser, Debug, Clone)]
 | 
					#[derive(Parser, Debug, Clone)]
 | 
				
			||||||
@@ -49,11 +56,17 @@ pub async fn sub_main() -> anyhow::Result<()> {
 | 
				
			|||||||
    let conf_json = std::fs::read_to_string(args.network_file())?;
 | 
					    let conf_json = std::fs::read_to_string(args.network_file())?;
 | 
				
			||||||
    let conf: NetNat = serde_json::from_str(&conf_json)?;
 | 
					    let conf: NetNat = serde_json::from_str(&conf_json)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let ips = net_utils::net_list_and_ips()?;
 | 
					    let nic_ips = net_utils::net_list_and_ips()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match (args.operation.as_str(), args.sub_operation.as_str()) {
 | 
					    match (args.operation.as_str(), args.sub_operation.as_str()) {
 | 
				
			||||||
        ("started", "begin") => network_started_begin(&conf, &ips).await?,
 | 
					        ("started", "begin") => {
 | 
				
			||||||
        ("stopped", "end") => network_stopped_end(&conf, &ips).await?,
 | 
					            log::info!("Enable port forwarding for network");
 | 
				
			||||||
 | 
					            trigger_nat_forwarding(true, &conf, &nic_ips).await?
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ("stopped", "end") => {
 | 
				
			||||||
 | 
					            log::info!("Disable port forwarding for network");
 | 
				
			||||||
 | 
					            trigger_nat_forwarding(false, &conf, &nic_ips).await?
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        _ => log::debug!(
 | 
					        _ => log::debug!(
 | 
				
			||||||
            "Operation {} - {} not supported",
 | 
					            "Operation {} - {} not supported",
 | 
				
			||||||
            args.operation,
 | 
					            args.operation,
 | 
				
			||||||
@@ -64,16 +77,156 @@ pub async fn sub_main() -> anyhow::Result<()> {
 | 
				
			|||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn network_started_begin(
 | 
					async fn trigger_nat_forwarding(
 | 
				
			||||||
 | 
					    enable: bool,
 | 
				
			||||||
    conf: &NetNat,
 | 
					    conf: &NetNat,
 | 
				
			||||||
    ips: &HashMap<String, Vec<IpAddr>>,
 | 
					    nic_ips: &HashMap<String, Vec<IpAddr>>,
 | 
				
			||||||
) -> anyhow::Result<()> {
 | 
					) -> anyhow::Result<()> {
 | 
				
			||||||
    todo!()
 | 
					    if let Some(ipv4) = &conf.ipv4 {
 | 
				
			||||||
 | 
					        trigger_nat_forwarding_nat_ipv(
 | 
				
			||||||
 | 
					            enable,
 | 
				
			||||||
 | 
					            &conf.interface,
 | 
				
			||||||
 | 
					            &ipv4.iter().map(|i| i.generalize()).collect::<Vec<_>>(),
 | 
				
			||||||
 | 
					            nic_ips,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if let Some(ipv6) = &conf.ipv6 {
 | 
				
			||||||
 | 
					        trigger_nat_forwarding_nat_ipv(
 | 
				
			||||||
 | 
					            enable,
 | 
				
			||||||
 | 
					            &conf.interface,
 | 
				
			||||||
 | 
					            &ipv6.iter().map(|i| i.generalize()).collect::<Vec<_>>(),
 | 
				
			||||||
 | 
					            nic_ips,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn network_stopped_end(
 | 
					async fn trigger_nat_forwarding_nat_ipv(
 | 
				
			||||||
    conf: &NetNat,
 | 
					    enable: bool,
 | 
				
			||||||
    ips: &HashMap<String, Vec<IpAddr>>,
 | 
					    net_interface: &str,
 | 
				
			||||||
 | 
					    rules: &[Nat<IpAddr>],
 | 
				
			||||||
 | 
					    nic_ips: &HashMap<String, Vec<IpAddr>>,
 | 
				
			||||||
) -> anyhow::Result<()> {
 | 
					) -> anyhow::Result<()> {
 | 
				
			||||||
    todo!()
 | 
					    for r in rules {
 | 
				
			||||||
 | 
					        let host_ips = match &r.host_ip {
 | 
				
			||||||
 | 
					            NatSourceIP::Interface { name } => nic_ips.get(name).cloned().unwrap_or_default(),
 | 
				
			||||||
 | 
					            NatSourceIP::Ip { ip } => vec![*ip],
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for host_ip in host_ips {
 | 
				
			||||||
 | 
					            let mut guest_port = r.guest_port;
 | 
				
			||||||
 | 
					            for host_port in r.host_port.as_seq() {
 | 
				
			||||||
 | 
					                if r.protocol.has_tcp() {
 | 
				
			||||||
 | 
					                    toggle_port_forwarding(
 | 
				
			||||||
 | 
					                        enable,
 | 
				
			||||||
 | 
					                        false,
 | 
				
			||||||
 | 
					                        host_ip,
 | 
				
			||||||
 | 
					                        host_port,
 | 
				
			||||||
 | 
					                        net_interface,
 | 
				
			||||||
 | 
					                        r.guest_ip,
 | 
				
			||||||
 | 
					                        guest_port,
 | 
				
			||||||
 | 
					                    )?
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if r.protocol.has_udp() {
 | 
				
			||||||
 | 
					                    toggle_port_forwarding(
 | 
				
			||||||
 | 
					                        enable,
 | 
				
			||||||
 | 
					                        true,
 | 
				
			||||||
 | 
					                        host_ip,
 | 
				
			||||||
 | 
					                        host_port,
 | 
				
			||||||
 | 
					                        net_interface,
 | 
				
			||||||
 | 
					                        r.guest_ip,
 | 
				
			||||||
 | 
					                        guest_port,
 | 
				
			||||||
 | 
					                    )?
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                guest_port += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn check_cmd(s: ExitStatus) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    if !s.success() {
 | 
				
			||||||
 | 
					        log::error!("Failed to update firewall rules!");
 | 
				
			||||||
 | 
					        return Err(NatConfModeError::UpdateFirewall.into());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn toggle_port_forwarding(
 | 
				
			||||||
 | 
					    enable: bool,
 | 
				
			||||||
 | 
					    is_udp: bool,
 | 
				
			||||||
 | 
					    host_ip: IpAddr,
 | 
				
			||||||
 | 
					    host_port: u16,
 | 
				
			||||||
 | 
					    net_interface: &str,
 | 
				
			||||||
 | 
					    guest_ip: IpAddr,
 | 
				
			||||||
 | 
					    guest_port: u16,
 | 
				
			||||||
 | 
					) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    if host_ip.is_ipv4() != guest_ip.is_ipv4() {
 | 
				
			||||||
 | 
					        log::trace!("Skipping invalid combination {host_ip} -> {guest_ip}");
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let program = match host_ip.is_ipv4() {
 | 
				
			||||||
 | 
					        true => "/sbin/iptables",
 | 
				
			||||||
 | 
					        false => "/sbin/ip6tables",
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let protocol = match is_udp {
 | 
				
			||||||
 | 
					        true => "udp",
 | 
				
			||||||
 | 
					        false => "tcp",
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log::info!("Forward (add={enable}) incoming {protocol} connections for {host_ip}:{host_port} to {guest_ip}:{guest_port} int {net_interface}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Rule 1
 | 
				
			||||||
 | 
					    let cmd = Command::new(program)
 | 
				
			||||||
 | 
					        .arg(match enable {
 | 
				
			||||||
 | 
					            true => "-I",
 | 
				
			||||||
 | 
					            false => "-D",
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .arg("FORWARD")
 | 
				
			||||||
 | 
					        .arg("-o")
 | 
				
			||||||
 | 
					        .arg(net_interface)
 | 
				
			||||||
 | 
					        .arg("-p")
 | 
				
			||||||
 | 
					        .arg(protocol)
 | 
				
			||||||
 | 
					        .arg("-d")
 | 
				
			||||||
 | 
					        .arg(guest_ip.to_string())
 | 
				
			||||||
 | 
					        .arg("--dport")
 | 
				
			||||||
 | 
					        .arg(guest_port.to_string())
 | 
				
			||||||
 | 
					        .arg("-j")
 | 
				
			||||||
 | 
					        .arg("ACCEPT")
 | 
				
			||||||
 | 
					        .status()?;
 | 
				
			||||||
 | 
					    check_cmd(cmd)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Rule 2
 | 
				
			||||||
 | 
					    let cmd = Command::new(program)
 | 
				
			||||||
 | 
					        .arg("-t")
 | 
				
			||||||
 | 
					        .arg("nat")
 | 
				
			||||||
 | 
					        .arg(match enable {
 | 
				
			||||||
 | 
					            true => "-I",
 | 
				
			||||||
 | 
					            false => "-D",
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .arg("PREROUTING")
 | 
				
			||||||
 | 
					        .arg("-p")
 | 
				
			||||||
 | 
					        .arg(protocol)
 | 
				
			||||||
 | 
					        .arg("-d")
 | 
				
			||||||
 | 
					        .arg(host_ip.to_string())
 | 
				
			||||||
 | 
					        .arg("--dport")
 | 
				
			||||||
 | 
					        .arg(host_port.to_string())
 | 
				
			||||||
 | 
					        .arg("-j")
 | 
				
			||||||
 | 
					        .arg("DNAT")
 | 
				
			||||||
 | 
					        .arg("--to")
 | 
				
			||||||
 | 
					        .arg(format!("{guest_ip}:{guest_port}"))
 | 
				
			||||||
 | 
					        .status()?;
 | 
				
			||||||
 | 
					    check_cmd(cmd)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::constants;
 | 
					use crate::constants;
 | 
				
			||||||
use crate::utils::net_utils;
 | 
					use crate::utils::net_utils;
 | 
				
			||||||
use std::net::{Ipv4Addr, Ipv6Addr};
 | 
					use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(thiserror::Error, Debug)]
 | 
					#[derive(thiserror::Error, Debug)]
 | 
				
			||||||
enum NatDefError {
 | 
					enum NatDefError {
 | 
				
			||||||
@@ -10,18 +10,28 @@ enum NatDefError {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
#[serde(tag = "type", rename_all = "lowercase")]
 | 
					#[serde(tag = "type", rename_all = "lowercase")]
 | 
				
			||||||
pub enum NatSource<IPv> {
 | 
					pub enum NatSourceIP<IPv> {
 | 
				
			||||||
    Interface { name: String },
 | 
					    Interface { name: String },
 | 
				
			||||||
    Ip { ip: IPv },
 | 
					    Ip { ip: IPv },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
					#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
pub enum NatProtocol {
 | 
					pub enum NatProtocol {
 | 
				
			||||||
    TCP,
 | 
					    TCP,
 | 
				
			||||||
    UDP,
 | 
					    UDP,
 | 
				
			||||||
    Both,
 | 
					    Both,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl NatProtocol {
 | 
				
			||||||
 | 
					    pub fn has_tcp(&self) -> bool {
 | 
				
			||||||
 | 
					        !matches!(&self, NatProtocol::UDP)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn has_udp(&self) -> bool {
 | 
				
			||||||
 | 
					        !matches!(&self, NatProtocol::TCP)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
#[serde(tag = "type", rename_all = "lowercase")]
 | 
					#[serde(tag = "type", rename_all = "lowercase")]
 | 
				
			||||||
pub enum NatHostPort {
 | 
					pub enum NatHostPort {
 | 
				
			||||||
@@ -29,19 +39,28 @@ pub enum NatHostPort {
 | 
				
			|||||||
    Range { start: u16, end: u16 },
 | 
					    Range { start: u16, end: u16 },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl NatHostPort {
 | 
				
			||||||
 | 
					    pub fn as_seq(&self) -> Vec<u16> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            NatHostPort::Single { port } => vec![*port],
 | 
				
			||||||
 | 
					            NatHostPort::Range { start, end } => (*start..(*end + 1)).collect(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
pub struct Nat<IPv> {
 | 
					pub struct Nat<IPv> {
 | 
				
			||||||
    pub protocol: NatProtocol,
 | 
					    pub protocol: NatProtocol,
 | 
				
			||||||
    pub host_addr: NatSource<IPv>,
 | 
					    pub host_ip: NatSourceIP<IPv>,
 | 
				
			||||||
    pub host_port: NatHostPort,
 | 
					    pub host_port: NatHostPort,
 | 
				
			||||||
    pub guest_addr: IPv,
 | 
					    pub guest_ip: IPv,
 | 
				
			||||||
    pub guest_port: u16,
 | 
					    pub guest_port: u16,
 | 
				
			||||||
    pub comment: Option<String>,
 | 
					    pub comment: Option<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<IPv> Nat<IPv> {
 | 
					impl<IPv> Nat<IPv> {
 | 
				
			||||||
    pub fn check(&self) -> anyhow::Result<()> {
 | 
					    pub fn check(&self) -> anyhow::Result<()> {
 | 
				
			||||||
        if let NatSource::Interface { name } = &self.host_addr {
 | 
					        if let NatSourceIP::Interface { name } = &self.host_ip {
 | 
				
			||||||
            if !net_utils::is_net_interface_name_valid(name) {
 | 
					            if !net_utils::is_net_interface_name_valid(name) {
 | 
				
			||||||
                return Err(NatDefError::InvalidNatDef("Invalid nat interface name!").into());
 | 
					                return Err(NatDefError::InvalidNatDef("Invalid nat interface name!").into());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -75,6 +94,46 @@ impl<IPv> Nat<IPv> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Nat<Ipv4Addr> {
 | 
				
			||||||
 | 
					    pub fn generalize(&self) -> Nat<IpAddr> {
 | 
				
			||||||
 | 
					        Nat {
 | 
				
			||||||
 | 
					            protocol: self.protocol,
 | 
				
			||||||
 | 
					            host_ip: match &self.host_ip {
 | 
				
			||||||
 | 
					                NatSourceIP::Ip { ip } => NatSourceIP::Ip {
 | 
				
			||||||
 | 
					                    ip: IpAddr::V4(*ip),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                NatSourceIP::Interface { name } => NatSourceIP::Interface {
 | 
				
			||||||
 | 
					                    name: name.to_string(),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            host_port: self.host_port.clone(),
 | 
				
			||||||
 | 
					            guest_ip: IpAddr::V4(self.guest_ip),
 | 
				
			||||||
 | 
					            guest_port: self.guest_port,
 | 
				
			||||||
 | 
					            comment: self.comment.clone(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Nat<Ipv6Addr> {
 | 
				
			||||||
 | 
					    pub fn generalize(&self) -> Nat<IpAddr> {
 | 
				
			||||||
 | 
					        Nat {
 | 
				
			||||||
 | 
					            protocol: self.protocol,
 | 
				
			||||||
 | 
					            host_ip: match &self.host_ip {
 | 
				
			||||||
 | 
					                NatSourceIP::Ip { ip } => NatSourceIP::Ip {
 | 
				
			||||||
 | 
					                    ip: IpAddr::V6(*ip),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                NatSourceIP::Interface { name } => NatSourceIP::Interface {
 | 
				
			||||||
 | 
					                    name: name.to_string(),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            host_port: self.host_port.clone(),
 | 
				
			||||||
 | 
					            guest_ip: IpAddr::V6(self.guest_ip),
 | 
				
			||||||
 | 
					            guest_port: self.guest_port,
 | 
				
			||||||
 | 
					            comment: self.comment.clone(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
 | 
				
			||||||
pub struct NetNat {
 | 
					pub struct NetNat {
 | 
				
			||||||
    pub interface: String,
 | 
					    pub interface: String,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,9 +23,9 @@ export type NatHostPort =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export interface NatEntry {
 | 
					export interface NatEntry {
 | 
				
			||||||
  protocol: "TCP" | "UDP" | "Both";
 | 
					  protocol: "TCP" | "UDP" | "Both";
 | 
				
			||||||
  host_addr: NatSource;
 | 
					  host_ip: NatSource;
 | 
				
			||||||
  host_port: NatHostPort;
 | 
					  host_port: NatHostPort;
 | 
				
			||||||
  guest_addr: string;
 | 
					  guest_ip: string;
 | 
				
			||||||
  guest_port: number;
 | 
					  guest_port: number;
 | 
				
			||||||
  comment?: string;
 | 
					  comment?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,12 +30,12 @@ export function NetNatConfiguration(p: {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const addEntry = () => {
 | 
					  const addEntry = () => {
 | 
				
			||||||
    p.nat.push({
 | 
					    p.nat.push({
 | 
				
			||||||
      host_addr: {
 | 
					      host_ip: {
 | 
				
			||||||
        type: "ip",
 | 
					        type: "ip",
 | 
				
			||||||
        ip: p.version === 4 ? "10.0.0.1" : "fd00::",
 | 
					        ip: p.version === 4 ? "10.0.0.1" : "fd00::",
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      host_port: { type: "single", port: 80 },
 | 
					      host_port: { type: "single", port: 80 },
 | 
				
			||||||
      guest_addr: p.version === 4 ? "10.0.0.100" : "fd00::",
 | 
					      guest_ip: p.version === 4 ? "10.0.0.100" : "fd00::",
 | 
				
			||||||
      guest_port: 10,
 | 
					      guest_port: 10,
 | 
				
			||||||
      protocol: "TCP",
 | 
					      protocol: "TCP",
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -122,7 +122,7 @@ function NatEntryForm(p: {
 | 
				
			|||||||
          <NATEntryProp label="Host configuration">
 | 
					          <NATEntryProp label="Host configuration">
 | 
				
			||||||
            <SelectInput
 | 
					            <SelectInput
 | 
				
			||||||
              {...p}
 | 
					              {...p}
 | 
				
			||||||
              label="Host address specification"
 | 
					              label="Host IP address specification"
 | 
				
			||||||
              options={[
 | 
					              options={[
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                  label: "Specific IP",
 | 
					                  label: "Specific IP",
 | 
				
			||||||
@@ -136,39 +136,38 @@ function NatEntryForm(p: {
 | 
				
			|||||||
                    "Use active IP addresses on the selected network interface during network startup to determine host adddress",
 | 
					                    "Use active IP addresses on the selected network interface during network startup to determine host adddress",
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
              ]}
 | 
					              ]}
 | 
				
			||||||
              value={p.entry.host_addr.type}
 | 
					              value={p.entry.host_ip.type}
 | 
				
			||||||
              onValueChange={(v) => {
 | 
					              onValueChange={(v) => {
 | 
				
			||||||
                p.entry.host_addr.type = v as any;
 | 
					                p.entry.host_ip.type = v as any;
 | 
				
			||||||
                p.onChange?.();
 | 
					                p.onChange?.();
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {p.entry.host_addr.type === "ip" && (
 | 
					            {p.entry.host_ip.type === "ip" && (
 | 
				
			||||||
              <IPInput
 | 
					              <IPInput
 | 
				
			||||||
                {...p}
 | 
					                {...p}
 | 
				
			||||||
                label="Host IP address"
 | 
					                label="Host IP address"
 | 
				
			||||||
                value={p.entry.host_addr.ip}
 | 
					                value={p.entry.host_ip.ip}
 | 
				
			||||||
                onValueChange={(v) => {
 | 
					                onValueChange={(v) => {
 | 
				
			||||||
                  if (p.entry.host_addr.type === "ip")
 | 
					                  if (p.entry.host_ip.type === "ip") p.entry.host_ip.ip = v!;
 | 
				
			||||||
                    p.entry.host_addr.ip = v!;
 | 
					 | 
				
			||||||
                  p.onChange?.();
 | 
					                  p.onChange?.();
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {p.entry.host_addr.type === "interface" && (
 | 
					            {p.entry.host_ip.type === "interface" && (
 | 
				
			||||||
              <SelectInput
 | 
					              <SelectInput
 | 
				
			||||||
                {...p}
 | 
					                {...p}
 | 
				
			||||||
                label="Network interface"
 | 
					                label="Network interface"
 | 
				
			||||||
                value={p.entry.host_addr.name}
 | 
					                value={p.entry.host_ip.name}
 | 
				
			||||||
                options={p.nicsList.map((n) => {
 | 
					                options={p.nicsList.map((n) => {
 | 
				
			||||||
                  return {
 | 
					                  return {
 | 
				
			||||||
                    value: n,
 | 
					                    value: n,
 | 
				
			||||||
                  };
 | 
					                  };
 | 
				
			||||||
                })}
 | 
					                })}
 | 
				
			||||||
                onValueChange={(v) => {
 | 
					                onValueChange={(v) => {
 | 
				
			||||||
                  if (p.entry.host_addr.type === "interface")
 | 
					                  if (p.entry.host_ip.type === "interface")
 | 
				
			||||||
                    p.entry.host_addr.name = v!;
 | 
					                    p.entry.host_ip.name = v!;
 | 
				
			||||||
                  p.onChange?.();
 | 
					                  p.onChange?.();
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
@@ -178,10 +177,10 @@ function NatEntryForm(p: {
 | 
				
			|||||||
          <NATEntryProp label="Target guest configuration">
 | 
					          <NATEntryProp label="Target guest configuration">
 | 
				
			||||||
            <IPInput
 | 
					            <IPInput
 | 
				
			||||||
              {...p}
 | 
					              {...p}
 | 
				
			||||||
              label="Guest address"
 | 
					              label="Guest IP"
 | 
				
			||||||
              value={p.entry.guest_addr}
 | 
					              value={p.entry.guest_ip}
 | 
				
			||||||
              onValueChange={(v) => {
 | 
					              onValueChange={(v) => {
 | 
				
			||||||
                p.entry.guest_addr = v!;
 | 
					                p.entry.guest_ip = v!;
 | 
				
			||||||
                p.onChange?.();
 | 
					                p.onChange?.();
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user