use nix::unistd::Pid;
use std::process::Command;
use super::SetupStatus;
use crate::error::*;
#[derive(Clone, Debug)]
pub struct Pasta {
pub(crate) prog: String,
args: Vec<String>,
}
impl Pasta {
pub fn program(&mut self, program: &str) -> &mut Self {
self.prog = program.to_string();
self
}
pub fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
for arg in args {
self.args.push(arg.as_ref().to_string());
}
self
}
}
impl Default for Pasta {
fn default() -> Self {
Self {
prog: "pasta".to_string(),
args: vec![],
}
}
}
impl Pasta {
pub(crate) fn mainp_setup(pasta: &Self, child: Pid) -> Result<SetupStatus> {
let cmdline = Self::to_cmdline(pasta, child);
log::debug!("Configuring Network: Execve: {cmdline:?}");
let output = Command::new(cmdline[0].clone())
.args(&cmdline[1..])
.output();
match output {
Ok(output) if output.status.success() => {
let output = format!("\n{}", String::from_utf8_lossy(&output.stderr).trim());
log::debug!("Configuring Network: Output: {output}");
Ok(SetupStatus::None)
}
Ok(output) => {
let errmsg = format!("\n{}", String::from_utf8_lossy(&output.stderr).trim());
Err(ProcessErrorKind::SetupNetworkFailed(errmsg))?
}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
let errmsg = format!("command {:?} not found", pasta.prog);
Err(ProcessErrorKind::SetupNetworkFailed(errmsg))?
}
Err(err) => {
let errmsg = format!("{err}");
Err(ProcessErrorKind::SetupNetworkFailed(errmsg))?
}
}
}
#[doc(hidden)]
pub fn to_cmdline(pasta: &Self, child: Pid) -> Vec<String> {
let mut no_map_gw = true;
let mut no_tcp_ports = true;
let mut no_udp_ports = true;
let mut no_tcp_ns_ports = true;
let mut no_udp_ns_ports = true;
let mut cmdline = vec![];
cmdline.push(pasta.prog.clone());
cmdline.push("--config-net".to_string());
let mut args = vec![];
for arg in pasta.args.iter() {
match arg.as_ref() {
"--map-gw" => {
no_map_gw = false;
continue;
}
"-t" | "--tcp-ports" => no_tcp_ports = false,
"-u" | "--udp-ports" => no_udp_ports = false,
"-T" | "--tcp-ns" => no_tcp_ns_ports = false,
"-U" | "--udp-ns" => no_udp_ns_ports = false,
_ => {}
};
args.push(arg.to_string());
}
if no_map_gw {
cmdline.push("--no-map-gw".to_string());
}
if no_tcp_ports {
cmdline.push("--tcp-ports".to_string());
cmdline.push("none".to_string());
}
if no_udp_ports {
cmdline.push("--udp-ports".to_string());
cmdline.push("none".to_string());
}
if no_tcp_ns_ports {
cmdline.push("--tcp-ns".to_string());
cmdline.push("none".to_string());
}
if no_udp_ns_ports {
cmdline.push("--udp-ns".to_string());
cmdline.push("none".to_string());
}
cmdline.append(&mut args);
cmdline.push(format!("{child}"));
cmdline
}
}