From 35c8f5cc6c2299f7f4cb77f128df1fd77b323469 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 23 Feb 2026 20:02:25 +0100 Subject: [PATCH] minor link handling improvements --- src/link.rs | 52 ++++++++++++++++++++------------------------ src/namespace/mod.rs | 6 +++-- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/link.rs b/src/link.rs index bcce0e4..865d86c 100644 --- a/src/link.rs +++ b/src/link.rs @@ -1,4 +1,3 @@ -use crate::namespace::{NamespaceEnterError, NamespaceHandle}; use neli::consts::nl::NlmF; use neli::consts::rtnl::Ifla; use neli::consts::rtnl::RtAddrFamily; @@ -12,25 +11,28 @@ use neli::rtnl::{Ifinfomsg, RtattrBuilder}; use neli::types::{Buffer, RtBuffer}; use neli::utils::Groups; use nix::libc::c_int; +use std::fmt::Debug; use std::os::fd::AsRawFd; use thiserror::Error; use tracing::info; #[derive(Debug, Error)] pub enum LinkError { - #[error("failed to communicate with netlink")] - Netlink, - #[error("failed to code netlink response")] - Parse, + #[error("Failed to communicate with netlink:")] + Netlink(String), + #[error("Failed to parse netlink response")] + Parse(String), #[error("Link not found: {0}")] NotFound(String), - #[error(transparent)] - Enter(#[from] NamespaceEnterError), } -impl From> for LinkError { - fn from(_value: RouterError) -> Self { - LinkError::Netlink +impl From> for LinkError +where + T: Debug, + P: Debug, +{ + fn from(value: RouterError) -> Self { + LinkError::Netlink(value.to_string()) } } @@ -89,7 +91,7 @@ impl LinkManager { .rtattrs() .get_attr_handle() .get_attr_payload_as_with_len::(Ifla::Ifname) - .map_err(|_| LinkError::Parse)?; + .map_err(|e| LinkError::Parse(e.to_string()))?; Ok(Some(Link { family: *payload.ifi_family(), index: *payload.ifi_index(), @@ -103,7 +105,7 @@ impl LinkManager { } /// Move a link to a namespace - pub fn move_link(&self, link: &Link, namespace: Fd) -> Result<(), LinkError> { + pub fn move_link(&self, link: &Link, namespace: &Fd) -> Result<(), LinkError> { let ns_handle = namespace.as_raw_fd(); let mut info_attrs = RtBuffer::::new(); @@ -143,27 +145,21 @@ pub fn link_up(link_name: &str) -> Result<(), LinkError> { } /// Move a link into a namespace -pub fn move_link_into(link_name: &str, namespace: &NamespaceHandle) -> Result<(), LinkError> { +pub fn move_link_into(link_name: &str, namespace: &Fd) -> Result<(), LinkError> { let manager = LinkManager::new()?; let link = manager.get_link(link_name)?; info!(name = &link.name, "moving link into namespace"); manager.move_link(&link, namespace) } -/// Move all links out of a namespace, except for lo -pub fn move_all_links_out( - namespace: &NamespaceHandle, - parent: &NamespaceHandle, -) -> Result<(), LinkError> { - namespace.run_in(|| { - let manager = LinkManager::new()?; - for link in manager.get_links()?.flatten() { - if link.name != "lo" { - info!(name = &link.name, "moving link out of namespace"); - manager.move_link(&link, parent)? - } +/// Move all links from the current namespace (except lo) into a namespace +pub fn move_all_links(namespace: &Fd) -> Result<(), LinkError> { + let manager = LinkManager::new()?; + for link in manager.get_links()?.flatten() { + if link.name != "lo" { + info!(name = &link.name, "moving link"); + manager.move_link(&link, namespace)? } - Ok::<_, LinkError>(()) - })??; - Ok(()) + } + Ok::<_, LinkError>(()) } diff --git a/src/namespace/mod.rs b/src/namespace/mod.rs index 29e452a..2b9295f 100644 --- a/src/namespace/mod.rs +++ b/src/namespace/mod.rs @@ -2,7 +2,7 @@ mod handle; mod raw; use crate::config::{DeviceName, NamespaceName}; -use crate::link::{link_up, move_all_links_out, move_link_into, LinkError}; +use crate::link::{link_up, move_all_links, move_link_into, LinkError}; pub use crate::namespace::handle::{NamespaceHandle, NamespaceHandleError}; use crate::namespace::raw::{create_network_namespace, NamespaceSetupError}; use either::Either; @@ -162,7 +162,9 @@ impl NetNs { pub fn delete(self) -> Result<(), NamespaceError> { let parent_namespace = NamespaceHandle::parent()?; - move_all_links_out(self.handle(), &parent_namespace)?; + self.handle.run_in(|| { + move_all_links(&parent_namespace) + })??; let name = self.path.file_name().unwrap().to_str().unwrap(); info!(name, "deleting network namespace"); match umount2(&self.path, MntFlags::MNT_DETACH) {