From e5aad660783b93b55a5f698870a862cba4ca52aa Mon Sep 17 00:00:00 2001 From: Quanwei Zhou Date: Tue, 17 Dec 2024 16:08:32 +0800 Subject: [PATCH] vsock: parse cid from vsock Parse vsock cid and port from address("vsock://cid:port"). Fixes: #266 Signed-off-by: Quanwei Zhou --- Cargo.toml | 2 ++ compiler/Cargo.toml | 2 ++ src/common.rs | 77 +++++++++++++++++++++++++++++++-------------- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0df03998..39eda678 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,8 @@ tokio-vsock = { version = "0.4.0", optional = true } [build-dependencies] protobuf-codegen = "3.1.0" +# lock home to avoid conflict with latest version +home = "=0.5.9" [features] default = ["sync"] diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index e449d34d..196b2bed 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -18,6 +18,8 @@ prost = "0.8" prost-build = "0.8" prost-types = "0.8" derive-new = "0.5" +# lock home to avoid conflict with latest version +home = "=0.5.9" tempfile = "3.0" [[bin]] diff --git a/src/common.rs b/src/common.rs index 926d241a..302c5fd5 100644 --- a/src/common.rs +++ b/src/common.rs @@ -101,8 +101,40 @@ fn make_addr(_domain: Domain, sockaddr: &str) -> Result { UnixAddr::new(sockaddr).map_err(err_to_others_err!(e, "")) } -fn make_socket(addr: (&str, u32)) -> Result<(RawFd, Domain, Box)> { - let (sockaddr, _) = addr; +// addr: cid:port +// return (cid, port) +#[cfg(any(target_os = "linux", target_os = "android"))] +fn parse_vscok(addr: &str) -> Result<(u32, u32)> { + // vsock://cid:port + let sockaddr_port_v: Vec<&str> = addr.split(':').collect(); + if sockaddr_port_v.len() != 2 { + return Err(Error::Others(format!( + "sockaddr {addr} is not right for vsock" + ))); + } + + // for -1 need trace to libc::VMADDR_CID_ANY + let cid: u32 = if sockaddr_port_v[0].trim().eq("-1") { + libc::VMADDR_CID_ANY + } else { + sockaddr_port_v[0].parse().map_err(|e| { + Error::Others(format!( + "failed to parse cid from {:?} error: {:?}", + sockaddr_port_v[0], e + )) + })? + }; + + let port: u32 = sockaddr_port_v[1].parse().map_err(|e| { + Error::Others(format!( + "failed to parse port from {:?} error: {:?}", + sockaddr_port_v[1], e + )) + })?; + Ok((cid, port)) +} + +fn make_socket(sockaddr: &str) -> Result<(RawFd, Domain, Box)> { let (domain, sockaddrv) = parse_sockaddr(sockaddr)?; let get_sock_addr = |domain, sockaddr| -> Result<(RawFd, Box)> { @@ -121,15 +153,7 @@ fn make_socket(addr: (&str, u32)) -> Result<(RawFd, Domain, Box get_sock_addr(domain, sockaddrv)?, #[cfg(any(target_os = "linux", target_os = "android"))] Domain::Vsock => { - let sockaddr_port_v: Vec<&str> = sockaddrv.split(':').collect(); - if sockaddr_port_v.len() != 2 { - return Err(Error::Others(format!( - "sockaddr {sockaddr} is not right for vsock" - ))); - } - let port: u32 = sockaddr_port_v[1] - .parse() - .expect("the vsock port is not an number"); + let (cid, port) = parse_vscok(sockaddrv)?; let fd = socket( AddressFamily::Vsock, SockType::Stream, @@ -137,7 +161,6 @@ fn make_socket(addr: (&str, u32)) -> Result<(RawFd, Domain, Box Result<(RawFd, Domain, Box Result<(RawFd, Domain)> { - let (fd, domain, sockaddr) = make_socket((sockaddr, VMADDR_CID_ANY))?; + let (fd, domain, sockaddr) = make_socket(sockaddr)?; setsockopt(fd, sockopt::ReusePort, &true)?; bind(fd, sockaddr.as_ref()).map_err(err_to_others_err!(e, ""))?; @@ -167,7 +180,7 @@ pub(crate) fn do_bind(sockaddr: &str) -> Result<(RawFd, Domain)> { /// Creates a unix socket for client. pub(crate) unsafe fn client_connect(sockaddr: &str) -> Result { - let (fd, _, sockaddr) = make_socket((sockaddr, VMADDR_CID_HOST))?; + let (fd, _, sockaddr) = make_socket(sockaddr)?; connect(fd, sockaddr.as_ref())?; @@ -236,4 +249,20 @@ mod tests { } } } + #[cfg(any(target_os = "linux", target_os = "android"))] + #[test] + fn test_parse_vscok() { + for i in &[ + ("-1:1024", (libc::VMADDR_CID_ANY, 1024)), + ("0:1", (0, 1)), + ("1:2", (1, 2)), + ("4294967294:3", (4294967294, 3)), + // 4294967295 = 0xFFFFFFFF + ("4294967295:4", (libc::VMADDR_CID_ANY, 4)), + ] { + let (input, (cid, port)) = (i.0, i.1); + let r = parse_vscok(input); + assert_eq!(r.unwrap(), (cid, port), "parse {:?} failed", i); + } + } }