diff --git a/src/bindings.rs b/src/bindings.rs index 12f30f0..6bcd071 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -13,6 +13,7 @@ extern "C" { pub fn krun_set_port_map(ctx: u32, port_map: *const *const c_char) -> i32; pub fn krun_set_workdir(ctx: u32, workdir_path: *const c_char) -> i32; pub fn krun_add_virtiofs(ctx: u32, tag: *const c_char, path: *const c_char) -> i32; + pub fn krun_add_vsock_port(ctx: u32, port: u32, filepath: *const c_char) -> i32; pub fn krun_set_exec( ctx: u32, exec_path: *const c_char, diff --git a/src/commands/start.rs b/src/commands/start.rs index 5c56c97..c70a415 100644 --- a/src/commands/start.rs +++ b/src/commands/start.rs @@ -44,6 +44,12 @@ pub struct StartCmd { /// env(s) in format "key=value" to be exposed to the VM #[arg(long = "env")] envs: Option>, + + /// vsock port to host Unix socket mapping(s) in format + /// "PORT:/host/path.sock". Guest connections to AF_VSOCK + /// (CID 2, PORT) are proxied to the Unix socket on the host. + #[arg(long = "vsock")] + vsocks: Option>, } impl StartCmd { @@ -76,11 +82,39 @@ impl StartCmd { Vec::new() }; + let vsock_ports: Vec<(u32, String)> = self + .vsocks + .unwrap_or_default() + .into_iter() + .map(|val| match val.split_once(':') { + Some((port, path)) => match port.parse::() { + Ok(port) => (port, path.to_string()), + Err(_) => { + println!("Invalid vsock port in mapping: {}", val); + std::process::exit(-1); + } + }, + None => { + println!("Invalid vsock mapping (expected PORT:PATH): {}", val); + std::process::exit(-1); + } + }) + .collect(); + set_rlimits(); let _file = set_lock(&rootfs); - unsafe { exec_vm(vmcfg, &rootfs, self.command.as_deref(), vm_args, env_pairs) }; + unsafe { + exec_vm( + vmcfg, + &rootfs, + self.command.as_deref(), + vm_args, + env_pairs, + vsock_ports, + ) + }; umount_container(cfg, vmcfg).expect("Error unmounting container"); } @@ -143,6 +177,7 @@ unsafe fn exec_vm( cmd: Option<&str>, args: Vec, env_pairs: Vec, + vsock_ports: Vec<(u32, String)>, ) { //bindings::krun_set_log_level(9); @@ -185,6 +220,15 @@ unsafe fn exec_vm( std::process::exit(-1); } + for (port, path) in vsock_ports.iter() { + let c_path = CString::new(path.as_str()).unwrap(); + let ret = bindings::krun_add_vsock_port(ctx, *port, c_path.as_ptr()); + if ret < 0 { + println!("Error adding vsock port {} -> {}", port, path); + std::process::exit(-1); + } + } + if !vmcfg.workdir.is_empty() { let c_workdir = CString::new(vmcfg.workdir.clone()).unwrap(); let ret = bindings::krun_set_workdir(ctx, c_workdir.as_ptr());