From 4774814c73788c5a9b30ade18f106cb0fc256a90 Mon Sep 17 00:00:00 2001 From: Liu Jiang Date: Sat, 30 May 2020 23:10:59 +0800 Subject: [PATCH] netlink: get rid of dependency on rustjail The netlink crate is a library to communicate with Linux kenrel by using the netlink socket. It's generic enough to be reused by other clients. So get rid of dependency on the rustjail crate by: 1) normalize all pub interfaces to return Result, 2) add helpers to reduce duplicated code, 3) move parse_mac() into lib.rs, Signed-off-by: Liu Jiang --- src/agent/Cargo.lock | 1 - src/agent/netlink/Cargo.toml | 1 - src/agent/netlink/src/lib.rs | 109 +++++++++++++++++++-------------- src/agent/netlink/src/neigh.rs | 44 ++----------- 4 files changed, 70 insertions(+), 85 deletions(-) diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index c7c18e2777..f763467a50 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -255,7 +255,6 @@ dependencies = [ "nix 0.17.0", "protobuf", "protocols", - "rustjail", "scan_fmt", "slog", "slog-async", diff --git a/src/agent/netlink/Cargo.toml b/src/agent/netlink/Cargo.toml index 5dc6b50940..0e91983a4c 100644 --- a/src/agent/netlink/Cargo.toml +++ b/src/agent/netlink/Cargo.toml @@ -10,7 +10,6 @@ edition = "2018" libc = "0.2.58" nix = "0.17.0" protobuf = "=2.14.0" -rustjail = { path = "../rustjail" } protocols = { path = "../protocols" } slog = { version = "2.5.2", features = ["dynamic-keys", "max_level_trace", "release_max_level_info"] } slog-json = "2.3.0" diff --git a/src/agent/netlink/src/lib.rs b/src/agent/netlink/src/lib.rs index 738ab7fed8..f10aa6088e 100644 --- a/src/agent/netlink/src/lib.rs +++ b/src/agent/netlink/src/lib.rs @@ -15,7 +15,6 @@ extern crate libc; extern crate nix; extern crate protobuf; extern crate protocols; -extern crate rustjail; #[macro_use] extern crate slog; @@ -29,7 +28,6 @@ extern crate scan_fmt; use nix::errno::Errno; use protobuf::RepeatedField; use protocols::types::{IPAddress, IPFamily, Interface, Route}; -use rustjail::errors::*; use std::clone::Clone; use std::default::Default; use std::fmt; @@ -37,6 +35,8 @@ use std::mem; use std::net::{Ipv4Addr, Ipv6Addr}; use std::str::FromStr; +type Result = std::result::Result; + // Convenience macro to obtain the scope logger macro_rules! sl { () => { @@ -1169,7 +1169,7 @@ impl RtnlHandle { mem::size_of::() as libc::socklen_t; if tmpfd < 0 { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } let mut err = libc::setsockopt( @@ -1182,7 +1182,7 @@ impl RtnlHandle { if err < 0 { libc::close(tmpfd); - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } err = libc::setsockopt( @@ -1195,7 +1195,7 @@ impl RtnlHandle { if err < 0 { libc::close(tmpfd); - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } libc::setsockopt( @@ -1216,7 +1216,7 @@ impl RtnlHandle { ); if err < 0 { libc::close(tmpfd); - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } err = libc::getsockname( @@ -1226,14 +1226,14 @@ impl RtnlHandle { ); if err < 0 { libc::close(tmpfd); - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } if sa.nl_family as i32 != libc::AF_NETLINK || addrlen as usize != mem::size_of::() { libc::close(tmpfd); - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EINVAL)).into()); + return nix_errno(Errno::EINVAL); } tmpfd @@ -1268,9 +1268,10 @@ impl RtnlHandle { let err = libc::sendmsg(self.fd, &h as *const libc::msghdr, 0); if err < 0 { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } } + Ok(()) } @@ -1296,7 +1297,7 @@ impl RtnlHandle { ); if rlen < 0 { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } // if rlen < 32768 { @@ -1311,16 +1312,16 @@ impl RtnlHandle { rlen = libc::recvmsg(self.fd, &mut h as *mut libc::msghdr, 0); if rlen < 0 { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::last())).into()); + return nix_last_os_err(); } if sa.nl_pid != 0 { // not our netlink message - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EBADMSG)).into()); + return nix_errno(Errno::EBADMSG); } if h.msg_flags & libc::MSG_TRUNC != 0 { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EBADMSG)).into()); + return nix_errno(Errno::EBADMSG); } v.resize(rlen as usize, 0); @@ -1362,13 +1363,11 @@ impl RtnlHandle { if (*nlh).nlmsg_len < NLMSG_LENGTH!(mem::size_of::()) { // truncated - return Err(ErrorKind::ErrorCode("truncated message".to_string()).into()); + return nix_errno(Errno::EBADMSG); } let el: *const nlmsgerr = NLMSG_DATA!(nlh) as *const nlmsgerr; - return Err( - ErrorKind::Nix(nix::Error::Sys(Errno::from_i32(-(*el).error))).into(), - ); + return nix_errno(Errno::from_i32(-(*el).error)); } lv.push(nlh); @@ -1393,9 +1392,10 @@ impl RtnlHandle { // still remain some bytes? if msglen != 0 { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EINVAL)).into()); + return nix_errno(Errno::EINVAL); } } + Ok((slv, lv)) } @@ -1563,20 +1563,10 @@ impl RtnlHandle { } fn find_link_by_hwaddr(&mut self, hwaddr: &str) -> Result { - let mut hw: Vec = vec![0; 6]; + let hw = parse_mac(hwaddr)?; + let p = hw.as_ptr() as *const u8 as *const libc::c_void; unsafe { //parse out hwaddr in request - let p = hw.as_mut_ptr() as *mut u8; - let (hw0, hw1, hw2, hw3, hw4, hw5) = scan_fmt!(hwaddr, "{x}:{x}:{x}:{x}:{x}:{x}", - [hex u8], [hex u8], [hex u8], [hex u8], [hex u8], - [hex u8])?; - - hw[0] = hw0; - hw[1] = hw1; - hw[2] = hw2; - hw[3] = hw3; - hw[4] = hw4; - hw[5] = hw5; // dump out all links let (_slv, lv) = self.dump_all_links()?; @@ -1608,7 +1598,7 @@ impl RtnlHandle { if attrs[IFLA_ADDRESS as usize] as i64 != 0 { let a = RTA_DATA!(attrs[IFLA_ADDRESS as usize]) as *const libc::c_void; if libc::memcmp( - p as *const libc::c_void, + p, a, RTA_PAYLOAD!(attrs[IFLA_ADDRESS as usize]) as libc::size_t, ) == 0 @@ -1619,7 +1609,7 @@ impl RtnlHandle { } } - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::ENODEV)).into()); + nix_errno(Errno::ENODEV) } fn find_link_by_name(&mut self, name: &str) -> Result { @@ -1688,9 +1678,7 @@ impl RtnlHandle { if (*nlh).nlmsg_len < NLMSG_LENGTH!(mem::size_of::()) { // truncated - return Err( - ErrorKind::ErrorCode("truncated message".to_string()).into() - ); + return nix_errno(Errno::EBADMSG); } let el: *const nlmsgerr = NLMSG_DATA!(nlh) as *const nlmsgerr; @@ -1700,9 +1688,7 @@ impl RtnlHandle { return Ok(Vec::new()); } - return Err( - ErrorKind::Nix(nix::Error::Sys(Errno::from_i32(-(*el).error))).into(), - ); + return nix_errno(Errno::from_i32(-(*el).error)); } // good message @@ -1723,7 +1709,7 @@ impl RtnlHandle { } if !(NLMSG_OK!(nlh, msglen)) { - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EINVAL)).into()); + return nix_errno(Errno::EINVAL); } } } @@ -2042,7 +2028,7 @@ impl RtnlHandle { } } - Err(ErrorKind::ErrorCode("no name".to_string()).into()) + nix_errno(Errno::ENOENT) } pub fn list_routes(&mut self) -> Result> { @@ -2711,7 +2697,7 @@ unsafe fn format_address(addr: *const u8, len: u32) -> Result { */ } - return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EINVAL)).into()); + nix_errno(Errno::EINVAL) } impl Drop for RtnlHandle { @@ -2740,13 +2726,15 @@ impl Default for RtRoute { } fn parse_cidripv4(s: &str) -> Result<(Vec, u8)> { - let (a0, a1, a2, a3, len) = scan_fmt!(s, "{}.{}.{}.{}/{}", u8, u8, u8, u8, u8)?; + let (a0, a1, a2, a3, len) = scan_fmt!(s, "{}.{}.{}.{}/{}", u8, u8, u8, u8, u8) + .map_err(|_| nix::Error::Sys(Errno::EINVAL))?; let ip: Vec = vec![a0, a1, a2, a3]; Ok((ip, len)) } fn parse_ipv4(s: &str) -> Result> { - let (a0, a1, a2, a3) = scan_fmt!(s, "{}.{}.{}.{}", u8, u8, u8, u8)?; + let (a0, a1, a2, a3) = + scan_fmt!(s, "{}.{}.{}.{}", u8, u8, u8, u8).map_err(|_| nix::Error::Sys(Errno::EINVAL))?; let ip: Vec = vec![a0, a1, a2, a3]; Ok(ip) @@ -2758,12 +2746,15 @@ fn parse_ipaddr(s: &str) -> Result> { } // v4 - Ok(Vec::from(Ipv4Addr::from_str(s)?.octets().as_ref())) + match Ipv4Addr::from_str(s) { + Ok(v) => Ok(Vec::from(v.octets().as_ref())), + Err(_e) => nix_errno(Errno::EINVAL), + } } fn parse_cider(s: &str) -> Result<(Vec, u8)> { let (addr, mask) = if s.contains("/") { - scan_fmt!(s, "{}/{}", String, u8)? + scan_fmt!(s, "{}/{}", String, u8).map_err(|_| nix::Error::Sys(Errno::EINVAL))? } else { (s.to_string(), 0) }; @@ -2771,6 +2762,24 @@ fn parse_cider(s: &str) -> Result<(Vec, u8)> { Ok((parse_ipaddr(addr.as_str())?, mask)) } +fn parse_mac(hwaddr: &str) -> Result> { + let mut hw: Vec = vec![0; 6]; + + let (hw0, hw1, hw2, hw3, hw4, hw5) = scan_fmt!(hwaddr, "{x}:{x}:{x}:{x}:{x}:{x}", + [hex u8], [hex u8], [hex u8], [hex u8], [hex u8], + [hex u8]) + .map_err(|_| nix::Error::Sys(Errno::EINVAL))?; + + hw[0] = hw0; + hw[1] = hw1; + hw[2] = hw2; + hw[3] = hw3; + hw[4] = hw4; + hw[5] = hw5; + + Ok(hw) +} + impl From for RtRoute { fn from(r: Route) -> Self { // only handle ipv4 @@ -2849,6 +2858,16 @@ impl From for RtIPAddr { } } +#[inline] +fn nix_last_os_err() -> Result { + Err(nix::Error::Sys(Errno::last())) +} + +#[inline] +fn nix_errno(err: Errno) -> Result { + Err(nix::Error::Sys(err)) +} + #[cfg(test)] mod tests { use crate::{nlmsghdr, NLMSG_ALIGNTO, RTA_ALIGNTO, RTM_BASE}; diff --git a/src/agent/netlink/src/neigh.rs b/src/agent/netlink/src/neigh.rs index 6134f8a912..bb50965313 100644 --- a/src/agent/netlink/src/neigh.rs +++ b/src/agent/netlink/src/neigh.rs @@ -3,13 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 // -use crate::{ - __s32, __u16, __u8, addattr_var, ifinfomsg, nlmsghdr, parse_ipaddr, IFA_F_PERMANENT, - NLMSG_ALIGNTO, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REQUEST, RTM_NEWNEIGH, -}; -use crate::{NLMSG_ALIGN, NLMSG_DATA, NLMSG_HDRLEN, NLMSG_LENGTH}; +use super::*; use protocols::types::ARPNeighbor; -use rustjail::errors::*; use std::mem; #[repr(C)] @@ -58,29 +53,19 @@ impl crate::RtnlHandle { Ok(()) } + pub fn add_one_arp_neighbor(&mut self, neigh: &ARPNeighbor) -> Result<()> { - let dev: ifinfomsg; - - match self.find_link_by_name(&neigh.device) { - Ok(d) => dev = d, - Err(e) => { - return Err(ErrorKind::ErrorCode(format!( - "Could not find link from device {}: {}", - neigh.device, e - )) - .into()); - } - } - if neigh.toIPAddress.is_none() { - return Err(ErrorKind::ErrorCode("toIPAddress is required".to_string()).into()); + return nix_errno(Errno::EINVAL); } let to_ip = &neigh.toIPAddress.as_ref().unwrap().address; if to_ip.is_empty() { - return Err(ErrorKind::ErrorCode("toIPAddress.address is required".to_string()).into()); + return nix_errno(Errno::EINVAL); } + let dev = self.find_link_by_name(&neigh.device)?; + let mut v: Vec = vec![0; 2048]; unsafe { // init @@ -129,23 +114,6 @@ impl crate::RtnlHandle { } } -fn parse_mac(hwaddr: &str) -> Result> { - let mut hw: Vec = vec![0; 6]; - - let (hw0, hw1, hw2, hw3, hw4, hw5) = scan_fmt!(hwaddr, "{x}:{x}:{x}:{x}:{x}:{x}", - [hex u8], [hex u8], [hex u8], [hex u8], [hex u8], - [hex u8])?; - - hw[0] = hw0; - hw[1] = hw1; - hw[2] = hw2; - hw[3] = hw3; - hw[4] = hw4; - hw[5] = hw5; - - Ok(hw) -} - fn parse_addr(ip_address: &str) -> Result<(__u8, Vec)> { let ip_data = parse_ipaddr(ip_address)?; let family: __u8;