From 0458e60b6943b1118763d68e83e91e999ef260a5 Mon Sep 17 00:00:00 2001 From: Vincent Thiberville Date: Tue, 19 Sep 2023 16:00:51 +0200 Subject: [PATCH 1/8] feat: update to nix 0.27.1 --- Cargo.toml | 2 +- src/ns.rs | 7 +++++-- src/traffic_control/add_filter.rs | 6 +++--- src/traffic_control/add_qdisc.rs | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a331262..3772017 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ netlink-packet-utils = { version = "0.5" } netlink-packet-route = { version = "0.17" } netlink-packet-core = { version = "0.7" } netlink-proto = { default-features = false, version = "0.11" } -nix = { version = "0.26.1", default-features = false, features = ["fs", "mount", "sched", "signal"] } +nix = { version = "0.27.1", default-features = false, features = ["fs", "mount", "sched", "signal"] } tokio = { version = "1.0.1", features = ["rt"], optional = true} async-global-executor = { version = "2.0.2", optional = true } diff --git a/src/ns.rs b/src/ns.rs index efc65f8..ad3a17f 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -10,7 +10,7 @@ use nix::{ }, unistd::{fork, ForkResult}, }; -use std::{option::Option, path::Path, process::exit}; +use std::{option::Option, os::fd::BorrowedFd, path::Path, process::exit}; // if "only" smol or smol+tokio were enabled, we use smol because // it doesn't require an active tokio runtime - just to be sure. @@ -329,7 +329,10 @@ impl NetworkNamespace { } setns_flags.insert(CloneFlags::CLONE_NEWNET); - if let Err(e) = nix::sched::setns(fd, setns_flags) { + if let Err(e) = nix::sched::setns( + unsafe { BorrowedFd::borrow_raw(fd) }, + setns_flags, + ) { log::error!("setns error: {}", e); let err_msg = format!("setns error: {e}"); let _ = nix::unistd::unlink(ns_path); diff --git a/src/traffic_control/add_filter.rs b/src/traffic_control/add_filter.rs index 335870c..64c50d7 100644 --- a/src/traffic_control/add_filter.rs +++ b/src/traffic_control/add_filter.rs @@ -162,7 +162,7 @@ impl TrafficFilterNewRequest { #[cfg(test)] mod test { - use std::{fs::File, os::unix::io::AsRawFd, path::Path}; + use std::{fs::File, os::fd::AsFd, path::Path}; use futures::stream::TryStreamExt; use netlink_packet_route::LinkMessage; @@ -193,7 +193,7 @@ mod test { // entry new ns let ns_path = Path::new(NETNS_PATH); let file = File::open(ns_path.join(path)).unwrap(); - setns(file.as_raw_fd(), CloneFlags::CLONE_NEWNET).unwrap(); + setns(file.as_fd(), CloneFlags::CLONE_NEWNET).unwrap(); Self { path: path.to_string(), @@ -205,7 +205,7 @@ mod test { impl Drop for Netns { fn drop(&mut self) { println!("exit ns: {}", self.path); - setns(self.last.as_raw_fd(), CloneFlags::CLONE_NEWNET).unwrap(); + setns(self.last.as_fd(), CloneFlags::CLONE_NEWNET).unwrap(); let ns_path = Path::new(NETNS_PATH).join(&self.path); nix::mount::umount2(&ns_path, nix::mount::MntFlags::MNT_DETACH) diff --git a/src/traffic_control/add_qdisc.rs b/src/traffic_control/add_qdisc.rs index 0f294cf..1325cfb 100644 --- a/src/traffic_control/add_qdisc.rs +++ b/src/traffic_control/add_qdisc.rs @@ -73,7 +73,7 @@ impl QDiscNewRequest { #[cfg(test)] mod test { - use std::{fs::File, os::unix::io::AsRawFd, path::Path}; + use std::{fs::File, os::fd::AsFd, path::Path}; use futures::stream::TryStreamExt; use nix::sched::{setns, CloneFlags}; @@ -106,7 +106,7 @@ mod test { // entry new ns let ns_path = Path::new(NETNS_PATH); let file = File::open(ns_path.join(path)).unwrap(); - setns(file.as_raw_fd(), CloneFlags::CLONE_NEWNET).unwrap(); + setns(file.as_fd(), CloneFlags::CLONE_NEWNET).unwrap(); Self { path: path.to_string(), @@ -118,7 +118,7 @@ mod test { impl Drop for Netns { fn drop(&mut self) { println!("exit ns: {}", self.path); - setns(self.last.as_raw_fd(), CloneFlags::CLONE_NEWNET).unwrap(); + setns(self.last.as_fd(), CloneFlags::CLONE_NEWNET).unwrap(); let ns_path = Path::new(NETNS_PATH).join(&self.path); nix::mount::umount2(&ns_path, nix::mount::MntFlags::MNT_DETACH) From 454fc585e004b89dd8ba37f236606e0846ec3236 Mon Sep 17 00:00:00 2001 From: Felix Obenhuber Date: Wed, 27 Sep 2023 07:45:55 +0200 Subject: [PATCH 2/8] Specify rust-version in manifest Specify the rust-version in the cargo manfiest as 1.66.1. The current reason for the the requirement is the use if `std::os::fd::RawFd` in `netlink-packet-route` `0.17.1` (link_xdp.rs). --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 3772017..e9e6b96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT" readme = "README.md" repository = "https://github.com/rust-netlink/rtnetlink" description = "manipulate linux networking resources via netlink" +rust-version = "1.66.1" [features] test_as_root = [] From dabef438c77e5d63b320f59e895a0bd405bea7fa Mon Sep 17 00:00:00 2001 From: Richard Stephens Date: Fri, 22 Sep 2023 15:55:37 +0200 Subject: [PATCH 3/8] Rule: function to set fw_mark when adding rule --- src/rule/add.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rule/add.rs b/src/rule/add.rs index 002c340..27172ce 100644 --- a/src/rule/add.rs +++ b/src/rule/add.rs @@ -93,6 +93,12 @@ impl RuleAddRequest { self } + /// Set the fwmark + pub fn fw_mark(mut self, fw_mark: u32) -> Self { + self.message.nlas.push(Nla::FwMark(fw_mark)); + self + } + /// Build an IP v4 rule pub fn v4(mut self) -> RuleAddRequest { self.message.header.family = AF_INET as u8; From ba4825a661752bb3bb436511f602cf1d21f6f9ba Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Tue, 5 Dec 2023 22:30:15 +0800 Subject: [PATCH 4/8] Use netlink-packet-route 0.18.0 Signed-off-by: Gris Ge --- Cargo.toml | 4 +- examples/create_vlan.rs | 14 +-- examples/get_links.rs | 18 ++-- examples/get_links_async.rs | 18 ++-- examples/get_links_thread_builder.rs | 19 ++-- examples/ip_monitor.rs | 17 +++- examples/property_altname.rs | 9 +- src/addr/add.rs | 55 +++++------ src/addr/del.rs | 5 +- src/addr/get.rs | 34 +++---- src/addr/handle.rs | 2 +- src/connection.rs | 10 +- src/errors.rs | 4 +- src/handle.rs | 13 +-- src/link/add.rs | 77 +++++++-------- src/link/del.rs | 5 +- src/link/get.rs | 29 ++++-- src/link/property_add.rs | 9 +- src/link/property_del.rs | 9 +- src/link/set.rs | 82 ++++++++++++---- src/link/set_bond_port.rs | 16 ++-- src/link/test.rs | 18 ++-- src/macros.rs | 2 +- src/neighbour/add.rs | 84 ++++++++++------- src/neighbour/del.rs | 5 +- src/neighbour/get.rs | 10 +- src/neighbour/handle.rs | 2 +- src/route/add.rs | 74 +++++++++------ src/route/del.rs | 5 +- src/route/get.rs | 28 +++--- src/route/handle.rs | 2 +- src/rule/add.rs | 50 +++++----- src/rule/del.rs | 5 +- src/rule/get.rs | 18 ++-- src/rule/handle.rs | 2 +- src/traffic_control/add_filter.rs | 135 +++++++++++++++------------ src/traffic_control/add_qdisc.rs | 44 +++++---- src/traffic_control/del_qdisc.rs | 7 +- src/traffic_control/get.rs | 30 +++--- src/traffic_control/handle.rs | 2 +- src/traffic_control/test.rs | 50 ++++++---- 41 files changed, 589 insertions(+), 433 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e9e6b96..0ede49a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rtnetlink" -version = "0.13.1" +version = "0.14.0" authors = ["Corentin Henry "] edition = "2018" homepage = "https://github.com/rust-netlink/rtnetlink" @@ -23,7 +23,7 @@ log = "0.4.8" thiserror = "1" netlink-sys = { version = "0.8" } netlink-packet-utils = { version = "0.5" } -netlink-packet-route = { version = "0.17" } +netlink-packet-route = { version = "0.18" } netlink-packet-core = { version = "0.7" } netlink-proto = { default-features = false, version = "0.11" } nix = { version = "0.27.1", default-features = false, features = ["fs", "mount", "sched", "signal"] } diff --git a/examples/create_vlan.rs b/examples/create_vlan.rs index cb01496..55dac5a 100644 --- a/examples/create_vlan.rs +++ b/examples/create_vlan.rs @@ -7,7 +7,7 @@ use rtnetlink::{new_connection, QosMapping}; fn parse_mapping(parameter: &str) -> Result> { let (from, to) = parameter .split_once(':') - .ok_or_else(|| "Failed to parse mapping..")?; + .ok_or("Failed to parse mapping..")?; Ok(QosMapping { from: u32::from_str(from)?, @@ -15,11 +15,11 @@ fn parse_mapping(parameter: &str) -> Result> { }) } -const ARG_BASE: &'static str = "--base"; -const ARG_NAME: &'static str = "--name"; -const ARG_ID: &'static str = "--id"; -const ARG_INGRESS_QOS: &'static str = "--ingress-qos-mapping"; -const ARG_EGRESS_QOS: &'static str = "--egress-qos-mapping"; +const ARG_BASE: &str = "--base"; +const ARG_NAME: &str = "--name"; +const ARG_ID: &str = "--id"; +const ARG_INGRESS_QOS: &str = "--ingress-qos-mapping"; +const ARG_EGRESS_QOS: &str = "--egress-qos-mapping"; enum ParsingMode { None, @@ -51,7 +51,7 @@ async fn main() -> Result<(), String> { ARG_EGRESS_QOS => Ok(ParsingMode::Egress), other => { usage(); - return Err(format!("Unexpected argument: {other}")); + Err(format!("Unexpected argument: {other}")) } } } diff --git a/examples/get_links.rs b/examples/get_links.rs index f78558d..9a33a9c 100644 --- a/examples/get_links.rs +++ b/examples/get_links.rs @@ -2,8 +2,8 @@ use futures::stream::TryStreamExt; use netlink_packet_route::{ - constants::{AF_BRIDGE, RTEXT_FILTER_BRVLAN}, - link::nlas::Nla, + link::{LinkAttribute, LinkExtentMask}, + AddressFamily, }; use rtnetlink::{new_connection, Error, Handle}; @@ -52,8 +52,8 @@ async fn get_link_by_index(handle: Handle, index: u32) -> Result<(), Error> { // We should have received only one message assert!(links.try_next().await?.is_none()); - for nla in msg.nlas.into_iter() { - if let Nla::IfName(name) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::IfName(name) = nla { println!("found link with index {index} (name = {name})"); return Ok(()); } @@ -79,8 +79,8 @@ async fn get_link_by_name(handle: Handle, name: String) -> Result<(), Error> { async fn dump_links(handle: Handle) -> Result<(), Error> { let mut links = handle.link().get().execute(); 'outer: while let Some(msg) = links.try_next().await? { - for nla in msg.nlas.into_iter() { - if let Nla::IfName(name) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::IfName(name) = nla { println!("found link {} ({})", msg.header.index, name); continue 'outer; } @@ -94,11 +94,11 @@ async fn dump_bridge_filter_info(handle: Handle) -> Result<(), Error> { let mut links = handle .link() .get() - .set_filter_mask(AF_BRIDGE as u8, RTEXT_FILTER_BRVLAN) + .set_filter_mask(AddressFamily::Bridge, vec![LinkExtentMask::Brvlan]) .execute(); 'outer: while let Some(msg) = links.try_next().await? { - for nla in msg.nlas.into_iter() { - if let Nla::AfSpecBridge(data) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::AfSpecBridge(data) = nla { println!( "found interface {} with AfSpecBridge data {:?})", msg.header.index, data diff --git a/examples/get_links_async.rs b/examples/get_links_async.rs index 6525f06..33b951a 100644 --- a/examples/get_links_async.rs +++ b/examples/get_links_async.rs @@ -2,8 +2,8 @@ use futures::stream::TryStreamExt; use netlink_packet_route::{ - constants::{AF_BRIDGE, RTEXT_FILTER_BRVLAN}, - link::nlas::Nla, + link::{LinkAttribute, LinkExtentMask}, + AddressFamily, }; use rtnetlink::{new_connection, Error, Handle}; @@ -52,8 +52,8 @@ async fn get_link_by_index(handle: Handle, index: u32) -> Result<(), Error> { // We should have received only one message assert!(links.try_next().await?.is_none()); - for nla in msg.nlas.into_iter() { - if let Nla::IfName(name) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::IfName(name) = nla { println!("found link with index {index} (name = {name})"); return Ok(()); } @@ -79,8 +79,8 @@ async fn get_link_by_name(handle: Handle, name: String) -> Result<(), Error> { async fn dump_links(handle: Handle) -> Result<(), Error> { let mut links = handle.link().get().execute(); 'outer: while let Some(msg) = links.try_next().await? { - for nla in msg.nlas.into_iter() { - if let Nla::IfName(name) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::IfName(name) = nla { println!("found link {} ({})", msg.header.index, name); continue 'outer; } @@ -94,11 +94,11 @@ async fn dump_bridge_filter_info(handle: Handle) -> Result<(), Error> { let mut links = handle .link() .get() - .set_filter_mask(AF_BRIDGE as u8, RTEXT_FILTER_BRVLAN) + .set_filter_mask(AddressFamily::Bridge, vec![LinkExtentMask::Brvlan]) .execute(); 'outer: while let Some(msg) = links.try_next().await? { - for nla in msg.nlas.into_iter() { - if let Nla::AfSpecBridge(data) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::AfSpecBridge(data) = nla { println!( "found interface {} with AfSpecBridge data {:?})", msg.header.index, data diff --git a/examples/get_links_thread_builder.rs b/examples/get_links_thread_builder.rs index 22dfc20..41669b1 100644 --- a/examples/get_links_thread_builder.rs +++ b/examples/get_links_thread_builder.rs @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT use futures::stream::TryStreamExt; -use netlink_packet_route::{link::nlas::Nla, AF_BRIDGE, RTEXT_FILTER_BRVLAN}; +use netlink_packet_route::{ + link::{LinkAttribute, LinkExtentMask}, + AddressFamily, +}; use rtnetlink::{new_connection, Error, Handle}; async fn do_it(rt: &tokio::runtime::Runtime) -> Result<(), ()> { @@ -48,8 +51,8 @@ async fn get_link_by_index(handle: Handle, index: u32) -> Result<(), Error> { // We should have received only one message assert!(links.try_next().await?.is_none()); - for nla in msg.nlas.into_iter() { - if let Nla::IfName(name) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::IfName(name) = nla { println!("found link with index {index} (name = {name})"); return Ok(()); } @@ -75,8 +78,8 @@ async fn get_link_by_name(handle: Handle, name: String) -> Result<(), Error> { async fn dump_links(handle: Handle) -> Result<(), Error> { let mut links = handle.link().get().execute(); 'outer: while let Some(msg) = links.try_next().await? { - for nla in msg.nlas.into_iter() { - if let Nla::IfName(name) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::IfName(name) = nla { println!("found link {} ({})", msg.header.index, name); continue 'outer; } @@ -90,11 +93,11 @@ async fn dump_bridge_filter_info(handle: Handle) -> Result<(), Error> { let mut links = handle .link() .get() - .set_filter_mask(AF_BRIDGE as u8, RTEXT_FILTER_BRVLAN) + .set_filter_mask(AddressFamily::Bridge, vec![LinkExtentMask::Brvlan]) .execute(); 'outer: while let Some(msg) = links.try_next().await? { - for nla in msg.nlas.into_iter() { - if let Nla::AfSpecBridge(data) = nla { + for nla in msg.attributes.into_iter() { + if let LinkAttribute::AfSpecBridge(data) = nla { println!( "found interface {} with AfSpecBridge data {:?})", msg.header.index, data diff --git a/examples/ip_monitor.rs b/examples/ip_monitor.rs index ad78bf0..44110b3 100644 --- a/examples/ip_monitor.rs +++ b/examples/ip_monitor.rs @@ -2,10 +2,25 @@ use futures::stream::StreamExt; -use netlink_packet_route::constants::*; use netlink_sys::{AsyncSocket, SocketAddr}; use rtnetlink::new_connection; +const RTNLGRP_LINK: u32 = 1; +const RTNLGRP_NEIGH: u32 = 3; +const RTNLGRP_IPV4_IFADDR: u32 = 5; +const RTNLGRP_IPV4_MROUTE: u32 = 6; +const RTNLGRP_IPV4_ROUTE: u32 = 7; +const RTNLGRP_IPV4_RULE: u32 = 8; +const RTNLGRP_IPV6_IFADDR: u32 = 9; +const RTNLGRP_IPV6_MROUTE: u32 = 10; +const RTNLGRP_IPV6_ROUTE: u32 = 11; +const RTNLGRP_IPV6_RULE: u32 = 19; +const RTNLGRP_IPV4_NETCONF: u32 = 24; +const RTNLGRP_IPV6_NETCONF: u32 = 25; +const RTNLGRP_MPLS_ROUTE: u32 = 27; +const RTNLGRP_NSID: u32 = 28; +const RTNLGRP_MPLS_NETCONF: u32 = 29; + const fn nl_mgrp(group: u32) -> u32 { if group > 31 { panic!("use netlink_sys::Socket::add_membership() for this group"); diff --git a/examples/property_altname.rs b/examples/property_altname.rs index f635593..4fb3e9e 100644 --- a/examples/property_altname.rs +++ b/examples/property_altname.rs @@ -1,10 +1,7 @@ // SPDX-License-Identifier: MIT use futures::stream::TryStreamExt; -use netlink_packet_route::{ - link::nlas::{Nla, Prop}, - LinkMessage, -}; +use netlink_packet_route::link::{LinkAttribute, LinkMessage, Prop}; use rtnetlink::{new_connection, Error, Handle}; use std::env; @@ -66,8 +63,8 @@ async fn show_property_alt_ifnames( link_name: &str, handle: Handle, ) -> Result<(), Error> { - for nla in get_link(link_name, handle).await?.nlas.into_iter() { - if let Nla::PropList(ref prop_list) = nla { + for nla in get_link(link_name, handle).await?.attributes.into_iter() { + if let LinkAttribute::PropList(ref prop_list) = nla { for prop in prop_list { if let Prop::AltIfName(altname) = prop { println!("altname: {altname}"); diff --git a/src/addr/add.rs b/src/addr/add.rs index 7a35483..2825648 100644 --- a/src/addr/add.rs +++ b/src/addr/add.rs @@ -9,7 +9,8 @@ use netlink_packet_core::{ }; use netlink_packet_route::{ - nlas::address::Nla, AddressMessage, RtnlMessage, AF_INET, AF_INET6, + address::{AddressAttribute, AddressMessage}, + AddressFamily, RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -34,46 +35,35 @@ impl AddressAddRequest { message.header.prefix_len = prefix_len; message.header.index = index; - let address_vec = match address { - IpAddr::V4(ipv4) => { - message.header.family = AF_INET as u8; - ipv4.octets().to_vec() - } - IpAddr::V6(ipv6) => { - message.header.family = AF_INET6 as u8; - ipv6.octets().to_vec() - } + message.header.family = match address { + IpAddr::V4(_) => AddressFamily::Inet, + IpAddr::V6(_) => AddressFamily::Inet6, }; if address.is_multicast() { - message.nlas.push(Nla::Multicast(address_vec)); - } else if address.is_unspecified() { - message.nlas.push(Nla::Unspec(address_vec)); - } else if address.is_ipv6() { - message.nlas.push(Nla::Address(address_vec)); + if let IpAddr::V6(a) = address { + message.attributes.push(AddressAttribute::Multicast(a)); + } } else { - message.nlas.push(Nla::Address(address_vec.clone())); + message.attributes.push(AddressAttribute::Address(address)); // for IPv4 the IFA_LOCAL address can be set to the same value as // IFA_ADDRESS - message.nlas.push(Nla::Local(address_vec.clone())); + message.attributes.push(AddressAttribute::Local(address)); // set the IFA_BROADCAST address as well (IPv6 does not support // broadcast) - if prefix_len == 32 { - message.nlas.push(Nla::Broadcast(address_vec)); - } else { - let ip_addr: u32 = u32::from(Ipv4Addr::new( - address_vec[0], - address_vec[1], - address_vec[2], - address_vec[3], - )); - let brd = Ipv4Addr::from( - (0xffff_ffff_u32) >> u32::from(prefix_len) | ip_addr, - ); - message.nlas.push(Nla::Broadcast(brd.octets().to_vec())); - }; + if let IpAddr::V4(a) = address { + if prefix_len == 32 { + message.attributes.push(AddressAttribute::Broadcast(a)); + } else { + let ip_addr = u32::from(a); + let brd = Ipv4Addr::from( + (0xffff_ffff_u32) >> u32::from(prefix_len) | ip_addr, + ); + message.attributes.push(AddressAttribute::Broadcast(brd)); + }; + } } AddressAddRequest { handle, @@ -97,7 +87,8 @@ impl AddressAddRequest { message, replace, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::NewAddress(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewAddress(message)); let replace = if replace { NLM_F_REPLACE } else { NLM_F_EXCL }; req.header.flags = NLM_F_REQUEST | NLM_F_ACK | replace | NLM_F_CREATE; diff --git a/src/addr/del.rs b/src/addr/del.rs index 5161bba..53b06c6 100644 --- a/src/addr/del.rs +++ b/src/addr/del.rs @@ -2,7 +2,7 @@ use futures::stream::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; -use netlink_packet_route::{AddressMessage, RtnlMessage}; +use netlink_packet_route::{address::AddressMessage, RouteNetlinkMessage}; use crate::{try_nl, Error, Handle}; @@ -23,7 +23,8 @@ impl AddressDelRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::DelAddress(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::DelAddress(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; while let Some(msg) = response.next().await { diff --git a/src/addr/get.rs b/src/addr/get.rs index 1f0f98f..cec0b0b 100644 --- a/src/addr/get.rs +++ b/src/addr/get.rs @@ -8,7 +8,10 @@ use futures::{ use std::net::IpAddr; use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST}; -use netlink_packet_route::{nlas::address::Nla, AddressMessage, RtnlMessage}; +use netlink_packet_route::{ + address::{AddressAttribute, AddressMessage}, + RouteNetlinkMessage, +}; use crate::{try_rtnl, Error, Handle}; @@ -38,14 +41,17 @@ impl AddressGetRequest { filter_builder, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::GetAddress(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::GetAddress(message)); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; let filter = filter_builder.build(); match handle.request(req) { Ok(response) => Either::Left( response - .map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewAddress))) + .map(move |msg| { + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewAddress)) + }) .try_filter(move |msg| future::ready(filter(msg))), ), Err(e) => Either::Right( @@ -92,7 +98,7 @@ impl AddressFilterBuilder { } fn build(self) -> impl Fn(&AddressMessage) -> bool { - use Nla::*; + use AddressAttribute::*; move |msg: &AddressMessage| { if let Some(index) = self.index { @@ -108,19 +114,13 @@ impl AddressFilterBuilder { } if let Some(address) = self.address { - for nla in msg.nlas.iter() { - if let Unspec(x) | Address(x) | Local(x) | Multicast(x) - | Anycast(x) = nla - { - let is_match = match address { - IpAddr::V4(address) => { - x[..] == address.octets()[..] - } - IpAddr::V6(address) => { - x[..] == address.octets()[..] - } - }; - if is_match { + for nla in msg.attributes.iter() { + if let Address(x) | Local(x) = nla { + if x == &address { + return true; + } + } else if let Multicast(x) | Anycast(x) = nla { + if IpAddr::V6(*x) == address { return true; } } diff --git a/src/addr/handle.rs b/src/addr/handle.rs index 75c69a0..a29863d 100644 --- a/src/addr/handle.rs +++ b/src/addr/handle.rs @@ -5,7 +5,7 @@ use std::net::IpAddr; use super::{AddressAddRequest, AddressDelRequest, AddressGetRequest}; use crate::Handle; -use netlink_packet_route::AddressMessage; +use netlink_packet_route::address::AddressMessage; pub struct AddressHandle(Handle); diff --git a/src/connection.rs b/src/connection.rs index 52923bf..097b8ba 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -4,7 +4,7 @@ use std::io; use futures::channel::mpsc::UnboundedReceiver; use netlink_packet_core::NetlinkMessage; -use netlink_packet_route::RtnlMessage; +use netlink_packet_route::RouteNetlinkMessage; use netlink_proto::Connection; use netlink_sys::{protocols::NETLINK_ROUTE, AsyncSocket, SocketAddr}; @@ -13,18 +13,18 @@ use crate::Handle; #[cfg(feature = "tokio_socket")] #[allow(clippy::type_complexity)] pub fn new_connection() -> io::Result<( - Connection, + Connection, Handle, - UnboundedReceiver<(NetlinkMessage, SocketAddr)>, + UnboundedReceiver<(NetlinkMessage, SocketAddr)>, )> { new_connection_with_socket() } #[allow(clippy::type_complexity)] pub fn new_connection_with_socket() -> io::Result<( - Connection, + Connection, Handle, - UnboundedReceiver<(NetlinkMessage, SocketAddr)>, + UnboundedReceiver<(NetlinkMessage, SocketAddr)>, )> where S: AsyncSocket, diff --git a/src/errors.rs b/src/errors.rs index 97975d3..090ae10 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT use netlink_packet_core::{ErrorMessage, NetlinkMessage}; -use netlink_packet_route::RtnlMessage; +use netlink_packet_route::RouteNetlinkMessage; use thiserror::Error; #[derive(Clone, Eq, PartialEq, Debug, Error)] pub enum Error { #[error("Received an unexpected message {0:?}")] - UnexpectedMessage(NetlinkMessage), + UnexpectedMessage(NetlinkMessage), #[error("Received a netlink error message {0}")] NetlinkError(ErrorMessage), diff --git a/src/handle.rs b/src/handle.rs index 116883d..1249ee9 100644 --- a/src/handle.rs +++ b/src/handle.rs @@ -2,7 +2,7 @@ use futures::Stream; use netlink_packet_core::NetlinkMessage; -use netlink_packet_route::RtnlMessage; +use netlink_packet_route::RouteNetlinkMessage; use netlink_proto::{sys::SocketAddr, ConnectionHandle}; use crate::{ @@ -12,17 +12,18 @@ use crate::{ }; #[derive(Clone, Debug)] -pub struct Handle(ConnectionHandle); +pub struct Handle(ConnectionHandle); impl Handle { - pub(crate) fn new(conn: ConnectionHandle) -> Self { + pub(crate) fn new(conn: ConnectionHandle) -> Self { Handle(conn) } pub fn request( &mut self, - message: NetlinkMessage, - ) -> Result>, Error> { + message: NetlinkMessage, + ) -> Result>, Error> + { self.0 .request(message, SocketAddr::new(0, 0)) .map_err(|_| Error::RequestFailed) @@ -30,7 +31,7 @@ impl Handle { pub fn notify( &mut self, - msg: NetlinkMessage, + msg: NetlinkMessage, ) -> Result<(), Error> { self.0 .notify(msg, SocketAddr::new(0, 0)) diff --git a/src/link/add.rs b/src/link/add.rs index d72b48e..bf319e7 100644 --- a/src/link/add.rs +++ b/src/link/add.rs @@ -12,11 +12,12 @@ use netlink_packet_core::{ }; use netlink_packet_route::{ - link::nlas::{ - Info, InfoBond, InfoData, InfoKind, InfoMacVlan, InfoMacVtap, InfoVlan, - InfoVxlan, InfoXfrmTun, Nla, VethInfo, VlanQosMapping, + link::{ + InfoBond, InfoData, InfoKind, InfoMacVlan, InfoMacVtap, InfoVeth, + InfoVlan, InfoVxlan, InfoXfrm, LinkAttribute, LinkFlag, LinkInfo, + LinkMessage, VlanQosMapping, }, - LinkMessage, RtnlMessage, IFF_UP, + RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -444,7 +445,7 @@ impl VxlanAddRequest { /// [no]learning`. [no]learning - specifies if unknown source link layer /// addresses and IP addresses are entered into the VXLAN /// device forwarding database. - pub fn learning(mut self, learning: u8) -> Self { + pub fn learning(mut self, learning: bool) -> Self { self.info_data.push(InfoVxlan::Learning(learning)); self } @@ -480,7 +481,7 @@ impl VxlanAddRequest { /// Adds the `proxy` attribute to the VXLAN /// This is equivalent to `ip link add name NAME type vxlan id VNI /// [no]proxy`. [no]proxy - specifies ARP proxy is turned on. - pub fn proxy(mut self, proxy: u8) -> Self { + pub fn proxy(mut self, proxy: bool) -> Self { self.info_data.push(InfoVxlan::Proxy(proxy)); self } @@ -488,7 +489,7 @@ impl VxlanAddRequest { /// Adds the `rsc` attribute to the VXLAN /// This is equivalent to `ip link add name NAME type vxlan id VNI [no]rsc`. /// [no]rsc - specifies if route short circuit is turned on. - pub fn rsc(mut self, rsc: u8) -> Self { + pub fn rsc(mut self, rsc: bool) -> Self { self.info_data.push(InfoVxlan::Rsc(rsc)); self } @@ -497,7 +498,7 @@ impl VxlanAddRequest { /// This is equivalent to `ip link add name NAME type vxlan id VNI /// [no]l2miss`. [no]l2miss - specifies if netlink LLADDR miss /// notifications are generated. - pub fn l2miss(mut self, l2miss: u8) -> Self { + pub fn l2miss(mut self, l2miss: bool) -> Self { self.info_data.push(InfoVxlan::L2Miss(l2miss)); self } @@ -506,12 +507,12 @@ impl VxlanAddRequest { /// This is equivalent to `ip link add name NAME type vxlan id VNI /// [no]l3miss`. [no]l3miss - specifies if netlink IP ADDR miss /// notifications are generated. - pub fn l3miss(mut self, l3miss: u8) -> Self { + pub fn l3miss(mut self, l3miss: bool) -> Self { self.info_data.push(InfoVxlan::L3Miss(l3miss)); self } - pub fn collect_metadata(mut self, collect_metadata: u8) -> Self { + pub fn collect_metadata(mut self, collect_metadata: bool) -> Self { self.info_data .push(InfoVxlan::CollectMetadata(collect_metadata)); self @@ -521,7 +522,7 @@ impl VxlanAddRequest { /// This is equivalent to `ip link add name NAME type vxlan id VNI /// [no]udp_csum`. [no]udpcsum - specifies if UDP checksum is calculated /// for transmitted packets over IPv4. - pub fn udp_csum(mut self, udp_csum: u8) -> Self { + pub fn udp_csum(mut self, udp_csum: bool) -> Self { self.info_data.push(InfoVxlan::UDPCsum(udp_csum)); self } @@ -549,7 +550,7 @@ pub struct QosMapping { impl From for VlanQosMapping { fn from(QosMapping { from, to }: QosMapping) -> Self { - Self::Mapping { from, to } + Self::Mapping(from, to) } } @@ -569,7 +570,8 @@ impl LinkAddRequest { message, replace, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::NewLink(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewLink(message)); let replace = if replace { NLM_F_REPLACE } else { NLM_F_EXCL }; req.header.flags = NLM_F_REQUEST | NLM_F_ACK | replace | NLM_F_CREATE; @@ -586,22 +588,23 @@ impl LinkAddRequest { /// /// Let's say we want to create a vlan interface on a link with id 6. By /// default, the [`vlan()`](#method.vlan) method would create a request - /// with the `IFF_UP` link set, so that the interface is up after + /// with the `LinkFlag::Up` link set, so that the interface is up after /// creation. If we want to create a interface that is down by default we /// could do: /// /// ```rust,no_run /// use futures::Future; - /// use netlink_packet_route::IFF_UP; + /// use netlink_packet_route::link::LinkFlag; /// use rtnetlink::{Handle, new_connection}; /// /// async fn run(handle: Handle) -> Result<(), String> { /// let vlan_id = 100; /// let link_id = 6; - /// let mut request = handle.link().add().vlan("my-vlan-itf".into(), link_id, vlan_id); - /// // unset the IFF_UP flag before sending the request - /// request.message_mut().header.flags &= !IFF_UP; - /// request.message_mut().header.change_mask &= !IFF_UP; + /// let mut request = handle.link().add().vlan("my-vlan-itf".into(), + /// link_id, vlan_id); + /// request.message_mut().header.flags.push(LinkFlag::Up); + /// request.message_mut().header.change_mask.retain( + /// |f| *f != LinkFlag::Up); /// // send the request /// request.execute().await.map_err(|e| format!("{}", e)) /// } @@ -619,16 +622,16 @@ impl LinkAddRequest { /// This is equivalent to `ip link add NAME1 type veth peer name NAME2`. pub fn veth(self, name: String, peer_name: String) -> Self { // NOTE: `name` is the name of the peer in the netlink message (ie the - // link created via the VethInfo::Peer attribute, and + // link created via the InfoVeth::Peer attribute, and // `peer_name` is the name in the main netlink message. // This is a bit weird, but it's all hidden from the user. let mut peer = LinkMessage::default(); // FIXME: we get a -107 (ENOTCONN) (???) when trying to set `name` up. - // peer.header.flags = LinkFlags::from(IFF_UP); - // peer.header.change_mask = LinkFlags::from(IFF_UP); - peer.nlas.push(Nla::IfName(name)); - let link_info_data = InfoData::Veth(VethInfo::Peer(peer)); + // peer.header.flags.push(LinkFlag::Up); + // peer.header.change_mask.push(LinkFlag::Up); + peer.attributes.push(LinkAttribute::IfName(name)); + let link_info_data = InfoData::Veth(InfoVeth::Peer(peer)); self.name(peer_name) .up() // iproute2 does not set this one up .link_info(InfoKind::Veth, Some(link_info_data)) @@ -673,7 +676,7 @@ impl LinkAddRequest { self.name(name) .link_info(InfoKind::Vlan, Some(InfoData::Vlan(info))) - .append_nla(Nla::Link(index)) + .append_nla(LinkAttribute::Link(index)) .up() } @@ -690,7 +693,7 @@ impl LinkAddRequest { InfoKind::MacVlan, Some(InfoData::MacVlan(vec![InfoMacVlan::Mode(mode)])), ) - .append_nla(Nla::Link(index)) + .append_nla(LinkAttribute::Link(index)) .up() } @@ -707,7 +710,7 @@ impl LinkAddRequest { InfoKind::MacVtap, Some(InfoData::MacVtap(vec![InfoMacVtap::Mode(mode)])), ) - .append_nla(Nla::Link(index)) + .append_nla(LinkAttribute::Link(index)) .up() } @@ -730,7 +733,7 @@ impl LinkAddRequest { self.name(name) .link_info( InfoKind::Xfrm, - Some(InfoData::Xfrm(vec![InfoXfrmTun::IfId(ifid)])), + Some(InfoData::Xfrm(vec![InfoXfrm::IfId(ifid)])), ) .up() } @@ -750,7 +753,7 @@ impl LinkAddRequest { pub fn bridge(self, name: String) -> Self { self.name(name.clone()) .link_info(InfoKind::Bridge, None) - .append_nla(Nla::IfName(name)) + .append_nla(LinkAttribute::IfName(name)) } /// Replace existing matching link. @@ -762,26 +765,26 @@ impl LinkAddRequest { } fn up(mut self) -> Self { - self.message.header.flags = IFF_UP; - self.message.header.change_mask = IFF_UP; + self.message.header.flags.push(LinkFlag::Up); + self.message.header.change_mask.push(LinkFlag::Up); self } fn link_info(self, kind: InfoKind, data: Option) -> Self { - let mut link_info_nlas = vec![Info::Kind(kind)]; + let mut link_info_nlas = vec![LinkInfo::Kind(kind)]; if let Some(data) = data { - link_info_nlas.push(Info::Data(data)); + link_info_nlas.push(LinkInfo::Data(data)); } - self.append_nla(Nla::Info(link_info_nlas)) + self.append_nla(LinkAttribute::LinkInfo(link_info_nlas)) } fn name(mut self, name: String) -> Self { - self.message.nlas.push(Nla::IfName(name)); + self.message.attributes.push(LinkAttribute::IfName(name)); self } - fn append_nla(mut self, nla: Nla) -> Self { - self.message.nlas.push(nla); + fn append_nla(mut self, nla: LinkAttribute) -> Self { + self.message.attributes.push(nla); self } } diff --git a/src/link/del.rs b/src/link/del.rs index 36d821a..530ca92 100644 --- a/src/link/del.rs +++ b/src/link/del.rs @@ -2,7 +2,7 @@ use futures::stream::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; -use netlink_packet_route::{LinkMessage, RtnlMessage}; +use netlink_packet_route::{link::LinkMessage, RouteNetlinkMessage}; use crate::{try_nl, Error, Handle}; @@ -24,7 +24,8 @@ impl LinkDelRequest { mut handle, message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::DelLink(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::DelLink(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; diff --git a/src/link/get.rs b/src/link/get.rs index 07dd345..8ab9c0f 100644 --- a/src/link/get.rs +++ b/src/link/get.rs @@ -6,7 +6,10 @@ use futures::{ FutureExt, }; use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST}; -use netlink_packet_route::{link::nlas::Nla, LinkMessage, RtnlMessage}; +use netlink_packet_route::{ + link::{LinkAttribute, LinkExtentMask, LinkMessage}, + AddressFamily, RouteNetlinkMessage, +}; use crate::{try_rtnl, Error, Handle}; @@ -31,10 +34,16 @@ impl LinkGetRequest { } } - /// Setting filter mask(e.g. RTEXT_FILTER_BRVLAN and etc) - pub fn set_filter_mask(mut self, family: u8, filter_mask: u32) -> Self { + /// Setting filter mask + pub fn set_filter_mask( + mut self, + family: AddressFamily, + filter_mask: Vec, + ) -> Self { self.message.header.interface_family = family; - self.message.nlas.push(Nla::ExtMask(filter_mask)); + self.message + .attributes + .push(LinkAttribute::ExtMask(filter_mask)); self } @@ -46,7 +55,8 @@ impl LinkGetRequest { dump, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::GetLink(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::GetLink(message)); if dump { req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; @@ -55,10 +65,9 @@ impl LinkGetRequest { } match handle.request(req) { - Ok(response) => Either::Left( - response - .map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewLink))), - ), + Ok(response) => Either::Left(response.map(move |msg| { + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewLink)) + })), Err(e) => Either::Right( future::err::(e).into_stream(), ), @@ -83,7 +92,7 @@ impl LinkGetRequest { /// older, consider filtering the resulting stream of links. pub fn match_name(mut self, name: String) -> Self { self.dump = false; - self.message.nlas.push(Nla::IfName(name)); + self.message.attributes.push(LinkAttribute::IfName(name)); self } } diff --git a/src/link/property_add.rs b/src/link/property_add.rs index eeb56c4..9213fe7 100644 --- a/src/link/property_add.rs +++ b/src/link/property_add.rs @@ -6,8 +6,8 @@ use netlink_packet_core::{ NLM_F_EXCL, NLM_F_REQUEST, }; use netlink_packet_route::{ - link::nlas::{Nla, Prop}, - LinkMessage, RtnlMessage, + link::{LinkAttribute, LinkMessage, Prop}, + RouteNetlinkMessage, }; use crate::{Error, Handle}; @@ -30,7 +30,8 @@ impl LinkNewPropRequest { mut handle, message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::NewLinkProp(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewLinkProp(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL @@ -59,7 +60,7 @@ impl LinkNewPropRequest { props.push(Prop::AltIfName(alt_ifname.to_string())); } - self.message.nlas.push(Nla::PropList(props)); + self.message.attributes.push(LinkAttribute::PropList(props)); self } } diff --git a/src/link/property_del.rs b/src/link/property_del.rs index 29c3fe9..74f51cd 100644 --- a/src/link/property_del.rs +++ b/src/link/property_del.rs @@ -5,8 +5,8 @@ use netlink_packet_core::{ NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_EXCL, NLM_F_REQUEST, }; use netlink_packet_route::{ - link::nlas::{Nla, Prop}, - LinkMessage, RtnlMessage, + link::{LinkAttribute, LinkMessage, Prop}, + RouteNetlinkMessage, }; use crate::{Error, Handle}; @@ -29,7 +29,8 @@ impl LinkDelPropRequest { mut handle, message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::DelLinkProp(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::DelLinkProp(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL; let mut response = handle.request(req)?; @@ -54,7 +55,7 @@ impl LinkDelPropRequest { props.push(Prop::AltIfName(alt_ifname.to_string())); } - self.message.nlas.push(Nla::PropList(props)); + self.message.attributes.push(LinkAttribute::PropList(props)); self } } diff --git a/src/link/set.rs b/src/link/set.rs index 895fd63..a2c61e8 100644 --- a/src/link/set.rs +++ b/src/link/set.rs @@ -7,7 +7,8 @@ use netlink_packet_core::{ NetlinkMessage, NLM_F_ACK, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REQUEST, }; use netlink_packet_route::{ - link::nlas::Nla, LinkMessage, RtnlMessage, IFF_NOARP, IFF_PROMISC, IFF_UP, + link::{LinkAttribute, LinkFlag, LinkMessage}, + RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -30,7 +31,8 @@ impl LinkSetRequest { mut handle, message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::SetLink(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::SetLink(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE; @@ -52,32 +54,67 @@ impl LinkSetRequest { /// /// To Remove a link from a bridge, set its master to zero. /// This is equvalent to `ip link set LINK nomaster` - pub fn master(mut self, master_index: u32) -> Self { - self.message.nlas.push(Nla::Master(master_index)); + #[deprecated( + since = "0.14.0", + note = "Please use `LinkSetRequest::controller()` instead" + )] + pub fn master(mut self, ctrl_index: u32) -> Self { + self.message + .attributes + .push(LinkAttribute::Controller(ctrl_index)); + self + } + + /// Attach the link to a bridge (its _controller_). This is equivalent to + /// `ip link set LINK master BRIDGE`. To succeed, both the bridge and the + /// link that is being attached must be UP. + /// + /// To Remove a link from a bridge, set its master to zero. + /// This is equvalent to `ip link set LINK nomaster` + pub fn controller(mut self, ctrl_index: u32) -> Self { + self.message + .attributes + .push(LinkAttribute::Controller(ctrl_index)); self } /// Detach the link from its _master_. This is equivalent to `ip link set /// LINK nomaster`. To succeed, the link that is being detached must be /// UP. + #[deprecated( + since = "0.14.0", + note = "Please use `LinkSetRequest::nocontroller()` instead" + )] pub fn nomaster(mut self) -> Self { - self.message.nlas.push(Nla::Master(0u32)); + self.message + .attributes + .push(LinkAttribute::Controller(0u32)); + self + } + + /// Detach the link from its _controller_. This is equivalent to `ip link + /// set LINK nomaster`. To succeed, the link that is being detached must be + /// UP. + pub fn nocontroller(mut self) -> Self { + self.message + .attributes + .push(LinkAttribute::Controller(0u32)); self } /// Set the link with the given index up (equivalent to `ip link set dev DEV /// up`) pub fn up(mut self) -> Self { - self.message.header.flags |= IFF_UP; - self.message.header.change_mask |= IFF_UP; + self.message.header.flags.push(LinkFlag::Up); + self.message.header.change_mask.push(LinkFlag::Up); self } /// Set the link with the given index down (equivalent to `ip link set dev /// DEV down`) pub fn down(mut self) -> Self { - self.message.header.flags &= !IFF_UP; - self.message.header.change_mask |= IFF_UP; + self.message.header.flags.retain(|f| *f != LinkFlag::Up); + self.message.header.change_mask.push(LinkFlag::Up); self } @@ -85,11 +122,14 @@ impl LinkSetRequest { /// (equivalent to `ip link set dev DEV promisc on/off`) pub fn promiscuous(mut self, enable: bool) -> Self { if enable { - self.message.header.flags |= IFF_PROMISC; + self.message.header.flags.push(LinkFlag::Promisc); } else { - self.message.header.flags &= !IFF_PROMISC; + self.message + .header + .flags + .retain(|f| *f != LinkFlag::Promisc); } - self.message.header.change_mask |= IFF_PROMISC; + self.message.header.change_mask.push(LinkFlag::Promisc); self } @@ -97,46 +137,48 @@ impl LinkSetRequest { /// (equivalent to `ip link set dev DEV arp on/off`) pub fn arp(mut self, enable: bool) -> Self { if enable { - self.message.header.flags &= !IFF_NOARP; + self.message.header.flags.retain(|f| *f != LinkFlag::Noarp); } else { - self.message.header.flags |= IFF_NOARP; + self.message.header.flags.push(LinkFlag::Noarp); } - self.message.header.change_mask |= IFF_NOARP; + self.message.header.change_mask.push(LinkFlag::Noarp); self } /// Set the name of the link with the given index (equivalent to `ip link /// set DEV name NAME`) pub fn name(mut self, name: String) -> Self { - self.message.nlas.push(Nla::IfName(name)); + self.message.attributes.push(LinkAttribute::IfName(name)); self } /// Set the mtu of the link with the given index (equivalent to `ip link set /// DEV mtu MTU`) pub fn mtu(mut self, mtu: u32) -> Self { - self.message.nlas.push(Nla::Mtu(mtu)); + self.message.attributes.push(LinkAttribute::Mtu(mtu)); self } /// Set the hardware address of the link with the given index (equivalent to /// `ip link set DEV address ADDRESS`) pub fn address(mut self, address: Vec) -> Self { - self.message.nlas.push(Nla::Address(address)); + self.message + .attributes + .push(LinkAttribute::Address(address)); self } /// Move this network device into the network namespace of the process with /// the given `pid`. pub fn setns_by_pid(mut self, pid: u32) -> Self { - self.message.nlas.push(Nla::NetNsPid(pid)); + self.message.attributes.push(LinkAttribute::NetNsPid(pid)); self } /// Move this network device into the network namespace corresponding to the /// given file descriptor. pub fn setns_by_fd(mut self, fd: RawFd) -> Self { - self.message.nlas.push(Nla::NetNsFd(fd)); + self.message.attributes.push(LinkAttribute::NetNsFd(fd)); self } } diff --git a/src/link/set_bond_port.rs b/src/link/set_bond_port.rs index ac03193..0ead017 100644 --- a/src/link/set_bond_port.rs +++ b/src/link/set_bond_port.rs @@ -3,8 +3,11 @@ use futures::stream::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; use netlink_packet_route::{ - link::nlas::{Info, InfoBondPort, InfoPortData, InfoPortKind, Nla}, - LinkMessage, RtnlMessage, + link::{ + InfoBondPort, InfoPortData, InfoPortKind, LinkAttribute, LinkInfo, + LinkMessage, + }, + RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -34,12 +37,13 @@ impl BondPortSetRequest { let mut message = LinkMessage::default(); message.header.index = index; - message.nlas.push(Nla::Info(vec![ - Info::PortKind(InfoPortKind::Bond), - Info::PortData(InfoPortData::BondPort(port_nlas)), + message.attributes.push(LinkAttribute::LinkInfo(vec![ + LinkInfo::PortKind(InfoPortKind::Bond), + LinkInfo::PortData(InfoPortData::BondPort(port_nlas)), ])); - let mut req = NetlinkMessage::from(RtnlMessage::NewLink(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewLink(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; diff --git a/src/link/test.rs b/src/link/test.rs index 1032053..a3cbf2a 100644 --- a/src/link/test.rs +++ b/src/link/test.rs @@ -2,8 +2,7 @@ use futures::stream::TryStreamExt; use netlink_packet_route::link::{ - nlas::{Info, InfoKind, Nla}, - LinkMessage, + InfoKind, LinkAttribute, LinkInfo, LinkMessage, }; use tokio::runtime::Runtime; @@ -22,13 +21,13 @@ fn create_get_delete_wg() { let msg = msg.unwrap(); assert!(has_nla( &msg, - &Nla::Info(vec![Info::Kind(InfoKind::Wireguard)]) + &LinkAttribute::LinkInfo(vec![LinkInfo::Kind(InfoKind::Wireguard)]) )); rt.block_on(_del_wg(&mut handle, msg.header.index)).unwrap(); } -fn has_nla(msg: &LinkMessage, nla: &Nla) -> bool { - msg.nlas.iter().any(|x| x == nla) +fn has_nla(msg: &LinkMessage, nla: &LinkAttribute) -> bool { + msg.attributes.iter().any(|x| x == nla) } async fn _create_wg() -> Result { @@ -37,9 +36,12 @@ async fn _create_wg() -> Result { let link_handle = handle.link(); let mut req = link_handle.add(); let mutator = req.message_mut(); - let info = Nla::Info(vec![Info::Kind(InfoKind::Wireguard)]); - mutator.nlas.push(info); - mutator.nlas.push(Nla::IfName(IFACE_NAME.to_owned())); + let info = + LinkAttribute::LinkInfo(vec![LinkInfo::Kind(InfoKind::Wireguard)]); + mutator.attributes.push(info); + mutator + .attributes + .push(LinkAttribute::IfName(IFACE_NAME.to_owned())); req.execute().await?; Ok(link_handle) } diff --git a/src/macros.rs b/src/macros.rs index 8a90649..64a12fa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -4,7 +4,7 @@ macro_rules! try_rtnl { ($msg: expr, $message_type:path) => {{ use netlink_packet_core::{NetlinkMessage, NetlinkPayload}; - use netlink_packet_route::RtnlMessage; + use netlink_packet_route::RouteNetlinkMessage; use $crate::Error; let (header, payload) = $msg.into_parts(); diff --git a/src/neighbour/add.rs b/src/neighbour/add.rs index 483a382..55abf22 100644 --- a/src/neighbour/add.rs +++ b/src/neighbour/add.rs @@ -7,9 +7,12 @@ use netlink_packet_core::{ NLM_F_REPLACE, NLM_F_REQUEST, }; use netlink_packet_route::{ - constants::*, - neighbour::{NeighbourMessage, Nla}, - RtnlMessage, + neighbour::{ + NeighbourAddress, NeighbourAttribute, NeighbourFlag, NeighbourMessage, + NeighbourState, + }, + route::RouteType, + AddressFamily, RouteNetlinkMessage, }; use crate::{Error, Handle}; @@ -26,18 +29,20 @@ impl NeighbourAddRequest { let mut message = NeighbourMessage::default(); message.header.family = match destination { - IpAddr::V4(_) => AF_INET as u8, - IpAddr::V6(_) => AF_INET6 as u8, + IpAddr::V4(_) => AddressFamily::Inet, + IpAddr::V6(_) => AddressFamily::Inet6, }; message.header.ifindex = index; - message.header.state = IFA_F_PERMANENT as u16; - message.header.ntype = NDA_UNSPEC as u8; + message.header.state = NeighbourState::Permanent; + message.header.kind = RouteType::Unspec; - message.nlas.push(Nla::Destination(match destination { - IpAddr::V4(v4) => v4.octets().to_vec(), - IpAddr::V6(v6) => v6.octets().to_vec(), - })); + message.attributes.push(NeighbourAttribute::Destination( + match destination { + IpAddr::V4(v4) => NeighbourAddress::Inet(v4), + IpAddr::V6(v6) => NeighbourAddress::Inet6(v6), + }, + )); NeighbourAddRequest { handle, @@ -49,12 +54,14 @@ impl NeighbourAddRequest { pub(crate) fn new_bridge(handle: Handle, index: u32, lla: &[u8]) -> Self { let mut message = NeighbourMessage::default(); - message.header.family = AF_BRIDGE as u8; + message.header.family = AddressFamily::Bridge; message.header.ifindex = index; - message.header.state = NUD_PERMANENT; - message.header.ntype = NDA_UNSPEC as u8; + message.header.state = NeighbourState::Permanent; + message.header.kind = RouteType::Unspec; - message.nlas.push(Nla::LinkLocalAddress(lla.to_vec())); + message + .attributes + .push(NeighbourAttribute::LinkLocalAddress(lla.to_vec())); NeighbourAddRequest { handle, @@ -65,36 +72,42 @@ impl NeighbourAddRequest { /// Set a bitmask of states for the neighbor cache entry. /// It should be a combination of `NUD_*` constants. - pub fn state(mut self, state: u16) -> Self { + pub fn state(mut self, state: NeighbourState) -> Self { self.message.header.state = state; self } /// Set flags for the neighbor cache entry. /// It should be a combination of `NTF_*` constants. - pub fn flags(mut self, flags: u8) -> Self { + pub fn flags(mut self, flags: Vec) -> Self { self.message.header.flags = flags; self } /// Set attributes applicable to the the neighbor cache entry. /// It should be one of `NDA_*` constants. - pub fn ntype(mut self, ntype: u8) -> Self { - self.message.header.ntype = ntype; + pub fn kind(mut self, kind: RouteType) -> Self { + self.message.header.kind = kind; self } /// Set a neighbor cache link layer address (see `NDA_LLADDR` for details). pub fn link_local_address(mut self, addr: &[u8]) -> Self { - let lla = self.message.nlas.iter_mut().find_map(|nla| match nla { - Nla::LinkLocalAddress(lla) => Some(lla), - _ => None, - }); + let lla = + self.message + .attributes + .iter_mut() + .find_map(|nla| match nla { + NeighbourAttribute::LinkLocalAddress(lla) => Some(lla), + _ => None, + }); if let Some(lla) = lla { *lla = addr.to_vec(); } else { - self.message.nlas.push(Nla::LinkLocalAddress(addr.to_vec())); + self.message + .attributes + .push(NeighbourAttribute::LinkLocalAddress(addr.to_vec())); } self @@ -103,20 +116,26 @@ impl NeighbourAddRequest { /// Set the destination address for the neighbour (see `NDA_DST` for /// details). pub fn destination(mut self, addr: IpAddr) -> Self { - let dst = self.message.nlas.iter_mut().find_map(|nla| match nla { - Nla::Destination(dst) => Some(dst), - _ => None, - }); + let dst = + self.message + .attributes + .iter_mut() + .find_map(|nla| match nla { + NeighbourAttribute::Destination(dst) => Some(dst), + _ => None, + }); let addr = match addr { - IpAddr::V4(v4) => v4.octets().to_vec(), - IpAddr::V6(v6) => v6.octets().to_vec(), + IpAddr::V4(v4) => NeighbourAddress::Inet(v4), + IpAddr::V6(v6) => NeighbourAddress::Inet6(v6), }; if let Some(dst) = dst { *dst = addr; } else { - self.message.nlas.push(Nla::Destination(addr)); + self.message + .attributes + .push(NeighbourAttribute::Destination(addr)); } self @@ -138,7 +157,8 @@ impl NeighbourAddRequest { replace, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::NewNeighbour(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewNeighbour(message)); let replace = if replace { NLM_F_REPLACE } else { NLM_F_EXCL }; req.header.flags = NLM_F_REQUEST | NLM_F_ACK | replace | NLM_F_CREATE; diff --git a/src/neighbour/del.rs b/src/neighbour/del.rs index 2f48d2c..d50ee85 100644 --- a/src/neighbour/del.rs +++ b/src/neighbour/del.rs @@ -4,7 +4,7 @@ use futures::stream::StreamExt; use netlink_packet_core::{ NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_REQUEST, }; -use netlink_packet_route::{neighbour::NeighbourMessage, RtnlMessage}; +use netlink_packet_route::{neighbour::NeighbourMessage, RouteNetlinkMessage}; use crate::{Error, Handle}; @@ -25,7 +25,8 @@ impl NeighbourDelRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::DelNeighbour(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::DelNeighbour(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; while let Some(msg) = response.next().await { diff --git a/src/neighbour/get.rs b/src/neighbour/get.rs index 8514426..7e50a7a 100644 --- a/src/neighbour/get.rs +++ b/src/neighbour/get.rs @@ -9,7 +9,8 @@ use netlink_packet_core::{ NetlinkMessage, NetlinkPayload, NLM_F_DUMP, NLM_F_REQUEST, }; use netlink_packet_route::{ - neighbour::NeighbourMessage, RtnlMessage, NTF_PROXY, + neighbour::{NeighbourFlag, NeighbourMessage}, + RouteNetlinkMessage, }; use crate::{Error, Handle, IpVersion}; @@ -28,7 +29,7 @@ impl NeighbourGetRequest { /// List neighbor proxies in the system (equivalent to: `ip neighbor show /// proxy`). pub fn proxies(mut self) -> Self { - self.message.header.flags |= NTF_PROXY; + self.message.header.flags.push(NeighbourFlag::Proxy); self } @@ -46,7 +47,8 @@ impl NeighbourGetRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::GetNeighbour(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::GetNeighbour(message)); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { @@ -54,7 +56,7 @@ impl NeighbourGetRequest { let (header, payload) = msg.into_parts(); match payload { NetlinkPayload::InnerMessage( - RtnlMessage::NewNeighbour(msg), + RouteNetlinkMessage::NewNeighbour(msg), ) => Ok(msg), NetlinkPayload::Error(err) => Err(Error::NetlinkError(err)), _ => Err(Error::UnexpectedMessage(NetlinkMessage::new( diff --git a/src/neighbour/handle.rs b/src/neighbour/handle.rs index ec39e9a..15da656 100644 --- a/src/neighbour/handle.rs +++ b/src/neighbour/handle.rs @@ -3,7 +3,7 @@ use crate::{ Handle, NeighbourAddRequest, NeighbourDelRequest, NeighbourGetRequest, }; -use netlink_packet_route::NeighbourMessage; +use netlink_packet_route::neighbour::NeighbourMessage; use std::net::IpAddr; pub struct NeighbourHandle(Handle); diff --git a/src/route/add.rs b/src/route/add.rs index f485dcb..ab1224d 100644 --- a/src/route/add.rs +++ b/src/route/add.rs @@ -11,8 +11,11 @@ use netlink_packet_core::{ NLM_F_REQUEST, }; use netlink_packet_route::{ - nlas::route::Nla, RouteMessage, RtnlMessage, AF_INET, AF_INET6, - RTN_UNICAST, RTPROT_STATIC, RT_SCOPE_UNIVERSE, RT_TABLE_MAIN, + route::{ + RouteAddress, RouteAttribute, RouteHeader, RouteMessage, RouteProtocol, + RouteScope, RouteType, + }, + AddressFamily, RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -30,10 +33,10 @@ impl RouteAddRequest { pub(crate) fn new(handle: Handle) -> Self { let mut message = RouteMessage::default(); - message.header.table = RT_TABLE_MAIN; - message.header.protocol = RTPROT_STATIC; - message.header.scope = RT_SCOPE_UNIVERSE; - message.header.kind = RTN_UNICAST; + message.header.table = RouteHeader::RT_TABLE_MAIN; + message.header.protocol = RouteProtocol::Static; + message.header.scope = RouteScope::Universe; + message.header.kind = RouteType::Unicast; RouteAddRequest { handle, @@ -45,13 +48,13 @@ impl RouteAddRequest { /// Sets the input interface index. pub fn input_interface(mut self, index: u32) -> Self { - self.message.nlas.push(Nla::Iif(index)); + self.message.attributes.push(RouteAttribute::Iif(index)); self } /// Sets the output interface index. pub fn output_interface(mut self, index: u32) -> Self { - self.message.nlas.push(Nla::Oif(index)); + self.message.attributes.push(RouteAttribute::Oif(index)); self } @@ -69,7 +72,7 @@ impl RouteAddRequest { /// Default is main route table. pub fn table_id(mut self, table: u32) -> Self { if table > 255 { - self.message.nlas.push(Nla::Table(table)); + self.message.attributes.push(RouteAttribute::Table(table)); } else { self.message.header.table = table as u8; } @@ -79,7 +82,7 @@ impl RouteAddRequest { /// Sets the route protocol. /// /// Default is static route protocol. - pub fn protocol(mut self, protocol: u8) -> Self { + pub fn protocol(mut self, protocol: RouteProtocol) -> Self { self.message.header.protocol = protocol; self } @@ -87,7 +90,7 @@ impl RouteAddRequest { /// Sets the route scope. /// /// Default is universe route scope. - pub fn scope(mut self, scope: u8) -> Self { + pub fn scope(mut self, scope: RouteScope) -> Self { self.message.header.scope = scope; self } @@ -95,14 +98,14 @@ impl RouteAddRequest { /// Sets the route kind. /// /// Default is unicast route kind. - pub fn kind(mut self, kind: u8) -> Self { + pub fn kind(mut self, kind: RouteType) -> Self { self.message.header.kind = kind; self } /// Build an IP v4 route request pub fn v4(mut self) -> RouteAddRequest { - self.message.header.address_family = AF_INET as u8; + self.message.header.address_family = AddressFamily::Inet; RouteAddRequest { handle: self.handle, message: self.message, @@ -113,7 +116,7 @@ impl RouteAddRequest { /// Build an IP v6 route request pub fn v6(mut self) -> RouteAddRequest { - self.message.header.address_family = AF_INET6 as u8; + self.message.header.address_family = AddressFamily::Inet6; RouteAddRequest { handle: self.handle, message: self.message, @@ -138,7 +141,8 @@ impl RouteAddRequest { replace, .. } = self; - let mut req = NetlinkMessage::from(RtnlMessage::NewRoute(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewRoute(message)); let replace = if replace { NLM_F_REPLACE } else { NLM_F_EXCL }; req.header.flags = NLM_F_REQUEST | NLM_F_ACK | replace | NLM_F_CREATE; @@ -159,15 +163,17 @@ impl RouteAddRequest { /// Sets the source address prefix. pub fn source_prefix(mut self, addr: Ipv4Addr, prefix_length: u8) -> Self { self.message.header.source_prefix_length = prefix_length; - let src = addr.octets().to_vec(); - self.message.nlas.push(Nla::Source(src)); + self.message + .attributes + .push(RouteAttribute::Source(RouteAddress::Inet(addr))); self } /// Sets the preferred source address. pub fn pref_source(mut self, addr: Ipv4Addr) -> Self { - let src = addr.octets().to_vec(); - self.message.nlas.push(Nla::PrefSource(src)); + self.message + .attributes + .push(RouteAttribute::PrefSource(RouteAddress::Inet(addr))); self } @@ -178,15 +184,17 @@ impl RouteAddRequest { prefix_length: u8, ) -> Self { self.message.header.destination_prefix_length = prefix_length; - let dst = addr.octets().to_vec(); - self.message.nlas.push(Nla::Destination(dst)); + self.message + .attributes + .push(RouteAttribute::Destination(RouteAddress::Inet(addr))); self } /// Sets the gateway (via) address. pub fn gateway(mut self, addr: Ipv4Addr) -> Self { - let gtw = addr.octets().to_vec(); - self.message.nlas.push(Nla::Gateway(gtw)); + self.message + .attributes + .push(RouteAttribute::Gateway(RouteAddress::Inet(addr))); self } } @@ -195,15 +203,17 @@ impl RouteAddRequest { /// Sets the source address prefix. pub fn source_prefix(mut self, addr: Ipv6Addr, prefix_length: u8) -> Self { self.message.header.source_prefix_length = prefix_length; - let src = addr.octets().to_vec(); - self.message.nlas.push(Nla::Source(src)); + self.message + .attributes + .push(RouteAttribute::Source(RouteAddress::Inet6(addr))); self } /// Sets the preferred source address. pub fn pref_source(mut self, addr: Ipv6Addr) -> Self { - let src = addr.octets().to_vec(); - self.message.nlas.push(Nla::PrefSource(src)); + self.message + .attributes + .push(RouteAttribute::PrefSource(RouteAddress::Inet6(addr))); self } @@ -214,15 +224,17 @@ impl RouteAddRequest { prefix_length: u8, ) -> Self { self.message.header.destination_prefix_length = prefix_length; - let dst = addr.octets().to_vec(); - self.message.nlas.push(Nla::Destination(dst)); + self.message + .attributes + .push(RouteAttribute::Destination(RouteAddress::Inet6(addr))); self } /// Sets the gateway (via) address. pub fn gateway(mut self, addr: Ipv6Addr) -> Self { - let gtw = addr.octets().to_vec(); - self.message.nlas.push(Nla::Gateway(gtw)); + self.message + .attributes + .push(RouteAttribute::Gateway(RouteAddress::Inet6(addr))); self } } diff --git a/src/route/del.rs b/src/route/del.rs index dc2a903..049484b 100644 --- a/src/route/del.rs +++ b/src/route/del.rs @@ -4,7 +4,7 @@ use futures::stream::StreamExt; use netlink_packet_core::{ NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_REQUEST, }; -use netlink_packet_route::{RouteMessage, RtnlMessage}; +use netlink_packet_route::{route::RouteMessage, RouteNetlinkMessage}; use crate::{Error, Handle}; @@ -25,7 +25,8 @@ impl RouteDelRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::DelRoute(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::DelRoute(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; while let Some(msg) = response.next().await { diff --git a/src/route/get.rs b/src/route/get.rs index f3cdf47..e870057 100644 --- a/src/route/get.rs +++ b/src/route/get.rs @@ -8,8 +8,8 @@ use futures::{ use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST}; use netlink_packet_route::{ - RouteMessage, RtnlMessage, AF_INET, AF_INET6, RTN_UNSPEC, RTPROT_UNSPEC, - RT_SCOPE_UNIVERSE, RT_TABLE_UNSPEC, + route::{RouteHeader, RouteMessage, RouteProtocol, RouteScope, RouteType}, + AddressFamily, RouteNetlinkMessage, }; use crate::{try_rtnl, Error, Handle}; @@ -29,10 +29,10 @@ pub enum IpVersion { } impl IpVersion { - pub(crate) fn family(self) -> u8 { + pub(crate) fn family(self) -> AddressFamily { match self { - IpVersion::V4 => AF_INET as u8, - IpVersion::V6 => AF_INET6 as u8, + IpVersion::V4 => AddressFamily::Inet, + IpVersion::V6 => AddressFamily::Inet6, } } } @@ -51,12 +51,12 @@ impl RouteGetRequest { // > is the wildcard. message.header.destination_prefix_length = 0; message.header.source_prefix_length = 0; - message.header.scope = RT_SCOPE_UNIVERSE; - message.header.kind = RTN_UNSPEC; + message.header.scope = RouteScope::Universe; + message.header.kind = RouteType::Unspec; // I don't know if these two fields matter - message.header.table = RT_TABLE_UNSPEC; - message.header.protocol = RTPROT_UNSPEC; + message.header.table = RouteHeader::RT_TABLE_UNSPEC; + message.header.protocol = RouteProtocol::Unspec; RouteGetRequest { handle, message } } @@ -71,14 +71,14 @@ impl RouteGetRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::GetRoute(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::GetRoute(message)); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { - Ok(response) => Either::Left( - response - .map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewRoute))), - ), + Ok(response) => Either::Left(response.map(move |msg| { + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewRoute)) + })), Err(e) => Either::Right( future::err::(e).into_stream(), ), diff --git a/src/route/handle.rs b/src/route/handle.rs index 2b9488e..e2d2116 100644 --- a/src/route/handle.rs +++ b/src/route/handle.rs @@ -3,7 +3,7 @@ use crate::{ Handle, IpVersion, RouteAddRequest, RouteDelRequest, RouteGetRequest, }; -use netlink_packet_route::RouteMessage; +use netlink_packet_route::route::RouteMessage; pub struct RouteHandle(Handle); diff --git a/src/rule/add.rs b/src/rule/add.rs index 27172ce..40b315a 100644 --- a/src/rule/add.rs +++ b/src/rule/add.rs @@ -12,8 +12,9 @@ use netlink_packet_core::{ }; use netlink_packet_route::{ - nlas::rule::Nla, RtnlMessage, RuleMessage, AF_INET, AF_INET6, - FR_ACT_UNSPEC, RT_TABLE_MAIN, + route::RouteHeader, + rule::{RuleAction, RuleAttribute, RuleMessage}, + AddressFamily, RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -31,8 +32,8 @@ impl RuleAddRequest { pub(crate) fn new(handle: Handle) -> Self { let mut message = RuleMessage::default(); - message.header.table = RT_TABLE_MAIN; - message.header.action = FR_ACT_UNSPEC; + message.header.table = RouteHeader::RT_TABLE_MAIN; + message.header.action = RuleAction::Unspec; RuleAddRequest { handle, @@ -44,13 +45,13 @@ impl RuleAddRequest { /// Sets the input interface name. pub fn input_interface(mut self, ifname: String) -> Self { - self.message.nlas.push(Nla::Iifname(ifname)); + self.message.attributes.push(RuleAttribute::Iifname(ifname)); self } /// Sets the output interface name. pub fn output_interface(mut self, ifname: String) -> Self { - self.message.nlas.push(Nla::OifName(ifname)); + self.message.attributes.push(RuleAttribute::Oifname(ifname)); self } @@ -68,7 +69,7 @@ impl RuleAddRequest { /// Default is main rule table. pub fn table_id(mut self, table: u32) -> Self { if table > 255 { - self.message.nlas.push(Nla::Table(table)); + self.message.attributes.push(RuleAttribute::Table(table)); } else { self.message.header.table = table as u8; } @@ -82,26 +83,28 @@ impl RuleAddRequest { } /// Set action. - pub fn action(mut self, action: u8) -> Self { + pub fn action(mut self, action: RuleAction) -> Self { self.message.header.action = action; self } /// Set the priority. pub fn priority(mut self, priority: u32) -> Self { - self.message.nlas.push(Nla::Priority(priority)); + self.message + .attributes + .push(RuleAttribute::Priority(priority)); self } /// Set the fwmark pub fn fw_mark(mut self, fw_mark: u32) -> Self { - self.message.nlas.push(Nla::FwMark(fw_mark)); + self.message.attributes.push(RuleAttribute::FwMark(fw_mark)); self } /// Build an IP v4 rule pub fn v4(mut self) -> RuleAddRequest { - self.message.header.family = AF_INET as u8; + self.message.header.family = AddressFamily::Inet; RuleAddRequest { handle: self.handle, message: self.message, @@ -112,7 +115,7 @@ impl RuleAddRequest { /// Build an IP v6 rule pub fn v6(mut self) -> RuleAddRequest { - self.message.header.family = AF_INET6 as u8; + self.message.header.family = AddressFamily::Inet6; RuleAddRequest { handle: self.handle, message: self.message, @@ -137,7 +140,8 @@ impl RuleAddRequest { replace, .. } = self; - let mut req = NetlinkMessage::from(RtnlMessage::NewRule(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::NewRule(message)); let replace = if replace { NLM_F_REPLACE } else { NLM_F_EXCL }; req.header.flags = NLM_F_REQUEST | NLM_F_ACK | replace | NLM_F_CREATE; @@ -158,8 +162,9 @@ impl RuleAddRequest { /// Sets the source address prefix. pub fn source_prefix(mut self, addr: Ipv4Addr, prefix_length: u8) -> Self { self.message.header.src_len = prefix_length; - let src = addr.octets().to_vec(); - self.message.nlas.push(Nla::Source(src)); + self.message + .attributes + .push(RuleAttribute::Source(addr.into())); self } @@ -170,8 +175,9 @@ impl RuleAddRequest { prefix_length: u8, ) -> Self { self.message.header.dst_len = prefix_length; - let dst = addr.octets().to_vec(); - self.message.nlas.push(Nla::Destination(dst)); + self.message + .attributes + .push(RuleAttribute::Destination(addr.into())); self } } @@ -180,8 +186,9 @@ impl RuleAddRequest { /// Sets the source address prefix. pub fn source_prefix(mut self, addr: Ipv6Addr, prefix_length: u8) -> Self { self.message.header.src_len = prefix_length; - let src = addr.octets().to_vec(); - self.message.nlas.push(Nla::Source(src)); + self.message + .attributes + .push(RuleAttribute::Source(addr.into())); self } @@ -192,8 +199,9 @@ impl RuleAddRequest { prefix_length: u8, ) -> Self { self.message.header.dst_len = prefix_length; - let dst = addr.octets().to_vec(); - self.message.nlas.push(Nla::Destination(dst)); + self.message + .attributes + .push(RuleAttribute::Destination(addr.into())); self } } diff --git a/src/rule/del.rs b/src/rule/del.rs index 95d5304..f1fbd0d 100644 --- a/src/rule/del.rs +++ b/src/rule/del.rs @@ -2,7 +2,7 @@ use futures::stream::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; -use netlink_packet_route::{RtnlMessage, RuleMessage}; +use netlink_packet_route::{rule::RuleMessage, RouteNetlinkMessage}; use crate::{try_nl, Error, Handle}; @@ -23,7 +23,8 @@ impl RuleDelRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::DelRule(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::DelRule(message)); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; while let Some(msg) = response.next().await { diff --git a/src/rule/get.rs b/src/rule/get.rs index 05d8a61..ee3d50d 100644 --- a/src/rule/get.rs +++ b/src/rule/get.rs @@ -7,7 +7,9 @@ use futures::{ }; use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST}; use netlink_packet_route::{ - RtnlMessage, RuleMessage, FR_ACT_UNSPEC, RT_TABLE_UNSPEC, + route::RouteHeader, + rule::{RuleAction, RuleMessage}, + RouteNetlinkMessage, }; use crate::{try_rtnl, Error, Handle, IpVersion}; @@ -25,8 +27,8 @@ impl RuleGetRequest { message.header.dst_len = 0; message.header.src_len = 0; message.header.tos = 0; - message.header.action = FR_ACT_UNSPEC; - message.header.table = RT_TABLE_UNSPEC; + message.header.action = RuleAction::Unspec; + message.header.table = RouteHeader::RT_TABLE_UNSPEC; RuleGetRequest { handle, message } } @@ -41,14 +43,14 @@ impl RuleGetRequest { message, } = self; - let mut req = NetlinkMessage::from(RtnlMessage::GetRule(message)); + let mut req = + NetlinkMessage::from(RouteNetlinkMessage::GetRule(message)); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { - Ok(response) => Either::Left( - response - .map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewRule))), - ), + Ok(response) => Either::Left(response.map(move |msg| { + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewRule)) + })), Err(e) => Either::Right( future::err::(e).into_stream(), ), diff --git a/src/rule/handle.rs b/src/rule/handle.rs index e2113cb..cf847b0 100644 --- a/src/rule/handle.rs +++ b/src/rule/handle.rs @@ -3,7 +3,7 @@ use crate::{ Handle, IpVersion, RuleAddRequest, RuleDelRequest, RuleGetRequest, }; -use netlink_packet_route::RuleMessage; +use netlink_packet_route::rule::RuleMessage; pub struct RuleHandle(Handle); diff --git a/src/traffic_control/add_filter.rs b/src/traffic_control/add_filter.rs index 64c50d7..73a5e6e 100644 --- a/src/traffic_control/add_filter.rs +++ b/src/traffic_control/add_filter.rs @@ -4,14 +4,13 @@ use futures::stream::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; use netlink_packet_route::{ tc::{ - self, - constants::{ - TCA_ACT_TAB, TCA_EGRESS_REDIR, TC_ACT_STOLEN, TC_H_CLSACT, - TC_H_MAJ_MASK, TC_H_MIN_EGRESS, TC_H_MIN_INGRESS, TC_H_MIN_MASK, - TC_H_ROOT, TC_U32_TERMINAL, - }, + TcAction, TcActionAttribute, TcActionGeneric, TcActionMirror, + TcActionMirrorOption, TcActionOption, TcActionType, TcAttribute, + TcFilterU32, TcFilterU32Option, TcHandle, TcHeader, TcMessage, + TcMirror, TcMirrorActionType, TcOption, TcU32Key, TcU32Selector, + TcU32SelectorFlag, }, - RtnlMessage, TcMessage, TCM_IFINDEX_MAGIC_BLOCK, TC_H_MAKE, + RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -39,8 +38,9 @@ impl TrafficFilterNewRequest { flags, } = self; - let mut req = - NetlinkMessage::from(RtnlMessage::NewTrafficFilter(message)); + let mut req = NetlinkMessage::from( + RouteNetlinkMessage::NewTrafficFilter(message), + ); req.header.flags = NLM_F_ACK | flags; let mut response = handle.request(req)?; @@ -60,42 +60,50 @@ impl TrafficFilterNewRequest { /// Set block index. /// Equivalent to `block BLOCK_INDEX`. pub fn block(mut self, block_index: u32) -> Self { - self.message.header.index = TCM_IFINDEX_MAGIC_BLOCK as i32; - self.message.header.parent = block_index; + self.message.header.index = TcHeader::TCM_IFINDEX_MAGIC_BLOCK as i32; + self.message.header.parent = block_index.into(); self } /// Set parent. /// Equivalent to `[ root | ingress | egress | parent CLASSID ]` - /// command args. They are mutually exlusive. + /// command args. They are mutually exclusive. pub fn parent(mut self, parent: u32) -> Self { - self.message.header.parent = parent; + self.message.header.parent = parent.into(); self } /// Set parent to root. pub fn root(mut self) -> Self { - self.message.header.parent = TC_H_ROOT; + self.message.header.parent = TcHandle::ROOT; self } /// Set parent to ingress. pub fn ingress(mut self) -> Self { - self.message.header.parent = TC_H_MAKE!(TC_H_CLSACT, TC_H_MIN_INGRESS); + self.message.header.parent = TcHandle { + major: 0xffff, + minor: TcHandle::MIN_INGRESS, + }; self } /// Set parent to egress. pub fn egress(mut self) -> Self { - self.message.header.parent = TC_H_MAKE!(TC_H_CLSACT, TC_H_MIN_EGRESS); + self.message.header.parent = TcHandle { + major: 0xffff, + minor: TcHandle::MIN_EGRESS, + }; self } /// Set priority. /// Equivalent to `priority PRIO` or `pref PRIO`. pub fn priority(mut self, priority: u16) -> Self { - self.message.header.info = - TC_H_MAKE!((priority as u32) << 16, self.message.header.info); + self.message.header.info = u32::from(TcHandle { + major: priority, + minor: priority, + }); self } @@ -103,60 +111,64 @@ impl TrafficFilterNewRequest { /// Equivalent to `protocol PROT`. /// Default: ETH_P_ALL 0x0003, see llproto_names at iproute2/lib/ll_proto.c. pub fn protocol(mut self, protocol: u16) -> Self { - self.message.header.info = - TC_H_MAKE!(self.message.header.info, protocol as u32); + self.message.header.info = u32::from(TcHandle { + major: (self.message.header.info >> 16) as u16, + minor: protocol, + }); self } /// The 32bit filter allows to match arbitrary bitfields in the packet. /// Equivalent to `tc filter ... u32`. - pub fn u32(mut self, data: Vec) -> Result { + pub fn u32(mut self, options: &[TcFilterU32Option]) -> Result { if self .message - .nlas + .attributes .iter() - .any(|nla| matches!(nla, tc::Nla::Kind(_))) + .any(|nla| matches!(nla, TcAttribute::Kind(_))) { return Err(Error::InvalidNla( "message kind has already been set.".to_string(), )); } self.message - .nlas - .push(tc::Nla::Kind(tc::u32::KIND.to_string())); - self.message.nlas.push(tc::Nla::Options( - data.into_iter().map(tc::TcOpt::U32).collect(), - )); + .attributes + .push(TcAttribute::Kind(TcFilterU32::KIND.to_string())); + let mut nla_opts = Vec::new(); + for opt in options { + nla_opts.push(TcOption::U32(opt.clone())); + } + self.message.attributes.push(TcAttribute::Options(nla_opts)); Ok(self) } /// Use u32 to implement traffic redirect. /// Equivalent to - /// `tc filter add [dev source] [parent ffff:] [protocol all] u32 match u8 0 - /// 0 action mirred egress redirect dev dest` You need to set the - /// `parent` and `protocol` before call redirect. + /// `tc filter add [dev source] [parent ffff:] [protocol all] \ + /// u32 match u8 0 0 action mirred egress redirect dev dest` + /// You need to set the `parent` and `protocol` before call redirect. pub fn redirect(self, dst_index: u32) -> Result { - let mut sel_na = tc::u32::Sel::default(); - sel_na.flags = TC_U32_TERMINAL; + let mut sel_na = TcU32Selector::default(); + sel_na.flags = vec![TcU32SelectorFlag::Terminal]; sel_na.nkeys = 1; - sel_na.keys = vec![tc::u32::Key::default()]; - let mut tc_mirror_nla = tc::mirred::TcMirred::default(); - tc_mirror_nla.action = TC_ACT_STOLEN; - tc_mirror_nla.eaction = TCA_EGRESS_REDIR; + sel_na.keys = vec![TcU32Key::default()]; + let mut tc_mirror_nla = TcMirror::default(); + tc_mirror_nla.generic = TcActionGeneric::default(); + tc_mirror_nla.generic.action = TcActionType::Stolen; + tc_mirror_nla.eaction = TcMirrorActionType::EgressRedir; tc_mirror_nla.ifindex = dst_index; - let mut action_nla = tc::Action::default(); - action_nla.tab = TCA_ACT_TAB; - action_nla.nlas = vec![ - tc::ActNla::Kind(tc::mirred::KIND.to_string()), - tc::ActNla::Options(vec![tc::ActOpt::Mirred( - tc::mirred::Nla::Parms(tc_mirror_nla), + let mut action_nla = TcAction::default(); + action_nla.attributes = vec![ + TcActionAttribute::Kind(TcActionMirror::KIND.to_string()), + TcActionAttribute::Options(vec![TcActionOption::Mirror( + TcActionMirrorOption::Parms(tc_mirror_nla), )]), ]; let u32_nla = vec![ - tc::u32::Nla::Sel(sel_na), - tc::u32::Nla::Act(vec![action_nla]), + TcFilterU32Option::Selector(sel_na), + TcFilterU32Option::Action(vec![action_nla]), ]; - self.u32(u32_nla) + self.u32(&u32_nla) } } @@ -165,12 +177,19 @@ mod test { use std::{fs::File, os::fd::AsFd, path::Path}; use futures::stream::TryStreamExt; - use netlink_packet_route::LinkMessage; + use netlink_packet_route::{ + link::LinkMessage, + tc::{ + TcAttribute, TcFilterU32, TcFilterU32Option, TcOption, TcU32Key, + TcU32SelectorFlag, + }, + }; use nix::sched::{setns, CloneFlags}; use tokio::runtime::Runtime; - use super::*; - use crate::{new_connection, NetworkNamespace, NETNS_PATH, SELF_NS_PATH}; + use crate::{ + new_connection, Handle, NetworkNamespace, NETNS_PATH, SELF_NS_PATH, + }; const TEST_NS: &str = "netlink_test_filter_ns"; const TEST_VETH_1: &str = "test_veth_1"; @@ -297,37 +316,37 @@ mod test { let mut found = false; while let Some(nl_msg) = filters_iter.try_next().await.unwrap() { //filters.push(nl_msg.clone()); - if nl_msg.header.handle == 0x80000800 { - let mut iter = nl_msg.nlas.iter(); + if nl_msg.header.handle == 0x80000800.into() { + let mut iter = nl_msg.attributes.iter(); assert_eq!( iter.next().unwrap(), - &tc::Nla::Kind(String::from(tc::u32::KIND)) + &TcAttribute::Kind(TcFilterU32::KIND.to_string()), ); - assert!(matches!(iter.next().unwrap(), &tc::Nla::Chain(_))); + assert!(matches!(iter.next().unwrap(), &TcAttribute::Chain(_))); // TCA_OPTIONS let nla = iter.next().unwrap(); - let filter = if let tc::Nla::Options(f) = nla { + let filter = if let TcAttribute::Options(f) = nla { f } else { panic!("expect options nla"); }; let mut fi = filter.iter(); let fa = fi.next().unwrap(); - let ua = if let tc::TcOpt::U32(u) = fa { + let ua = if let TcOption::U32(u) = fa { u } else { panic!("expect u32 nla"); }; // TCA_U32_SEL - let sel = if let tc::u32::Nla::Sel(s) = ua { + let sel = if let TcFilterU32Option::Selector(s) = ua { s } else { panic!("expect sel nla"); }; - assert_eq!(sel.flags, TC_U32_TERMINAL); + assert_eq!(sel.flags, vec![TcU32SelectorFlag::Terminal]); assert_eq!(sel.nkeys, 1); assert_eq!(sel.keys.len(), 1); - assert_eq!(sel.keys[0], tc::u32::Key::default()); + assert_eq!(sel.keys[0], TcU32Key::default()); found = true; break; } diff --git a/src/traffic_control/add_qdisc.rs b/src/traffic_control/add_qdisc.rs index 1325cfb..362b132 100644 --- a/src/traffic_control/add_qdisc.rs +++ b/src/traffic_control/add_qdisc.rs @@ -3,9 +3,8 @@ use futures::stream::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; use netlink_packet_route::{ - tc::constants::{TC_H_INGRESS, TC_H_MAJ_MASK, TC_H_MIN_MASK, TC_H_ROOT}, - tc::nlas::Nla, - RtnlMessage, TcMessage, TC_H_MAKE, + tc::{TcAttribute, TcHandle, TcMessage}, + RouteNetlinkMessage, }; use crate::{try_nl, Error, Handle}; @@ -33,8 +32,9 @@ impl QDiscNewRequest { flags, } = self; - let mut req = - NetlinkMessage::from(RtnlMessage::NewQueueDiscipline(message)); + let mut req = NetlinkMessage::from( + RouteNetlinkMessage::NewQueueDiscipline(message), + ); req.header.flags = NLM_F_ACK | flags; let mut response = handle.request(req)?; @@ -45,28 +45,30 @@ impl QDiscNewRequest { } /// Set handle, - pub fn handle(mut self, maj: u16, min: u16) -> Self { - self.message.header.handle = TC_H_MAKE!((maj as u32) << 16, min as u32); + pub fn handle(mut self, major: u16, minor: u16) -> Self { + self.message.header.handle = TcHandle { major, minor }; self } /// Set parent to root. pub fn root(mut self) -> Self { - self.message.header.parent = TC_H_ROOT; + self.message.header.parent = TcHandle::ROOT; self } /// Set parent pub fn parent(mut self, parent: u32) -> Self { - self.message.header.parent = parent; + self.message.header.parent = parent.into(); self } /// New a ingress qdisc pub fn ingress(mut self) -> Self { - self.message.header.parent = TC_H_INGRESS; - self.message.header.handle = 0xffff0000; - self.message.nlas.push(Nla::Kind("ingress".to_string())); + self.message.header.parent = TcHandle::INGRESS; + self.message.header.handle = TcHandle::from(0xffff0000); + self.message + .attributes + .push(TcAttribute::Kind("ingress".to_string())); self } } @@ -82,8 +84,7 @@ mod test { use super::*; use crate::{new_connection, NetworkNamespace, NETNS_PATH, SELF_NS_PATH}; use netlink_packet_route::{ - tc::nlas::Nla::{HwOffload, Kind}, - LinkMessage, AF_UNSPEC, + link::LinkMessage, tc::TcAttribute, AddressFamily, }; const TEST_NS: &str = "netlink_test_qdisc_ns"; @@ -173,14 +174,17 @@ mod test { let mut found = false; while let Some(nl_msg) = qdiscs_iter.try_next().await.unwrap() { if nl_msg.header.index == test_link.header.index as i32 - && nl_msg.header.handle == 0xffff0000 + && nl_msg.header.handle == 0xffff0000.into() { - assert_eq!(nl_msg.header.family, AF_UNSPEC as u8); - assert_eq!(nl_msg.header.handle, 0xffff0000); - assert_eq!(nl_msg.header.parent, TC_H_INGRESS); + assert_eq!(nl_msg.header.family, AddressFamily::Unspec); + assert_eq!(nl_msg.header.handle, 0xffff0000.into()); + assert_eq!(nl_msg.header.parent, TcHandle::INGRESS); assert_eq!(nl_msg.header.info, 1); // refcount - assert_eq!(nl_msg.nlas[0], Kind("ingress".to_string())); - assert_eq!(nl_msg.nlas[2], HwOffload(0)); + assert_eq!( + nl_msg.attributes[0], + TcAttribute::Kind("ingress".to_string()) + ); + assert_eq!(nl_msg.attributes[2], TcAttribute::HwOffload(0)); found = true; break; } diff --git a/src/traffic_control/del_qdisc.rs b/src/traffic_control/del_qdisc.rs index 2e5c977..a0fcd8d 100644 --- a/src/traffic_control/del_qdisc.rs +++ b/src/traffic_control/del_qdisc.rs @@ -2,7 +2,7 @@ use futures::StreamExt; use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; -use netlink_packet_route::{RtnlMessage, TcMessage}; +use netlink_packet_route::{tc::TcMessage, RouteNetlinkMessage}; use crate::{try_nl, Error, Handle}; @@ -23,8 +23,9 @@ impl QDiscDelRequest { message, } = self; - let mut req = - NetlinkMessage::from(RtnlMessage::DelQueueDiscipline(message)); + let mut req = NetlinkMessage::from( + RouteNetlinkMessage::DelQueueDiscipline(message), + ); req.header.flags = NLM_F_REQUEST | NLM_F_ACK; let mut response = handle.request(req)?; diff --git a/src/traffic_control/get.rs b/src/traffic_control/get.rs index 345c4ed..01cb262 100644 --- a/src/traffic_control/get.rs +++ b/src/traffic_control/get.rs @@ -7,8 +7,8 @@ use futures::{ }; use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST}; use netlink_packet_route::{ - tc::constants::{TC_H_INGRESS, TC_H_ROOT}, - RtnlMessage, TcMessage, + tc::{TcHandle, TcMessage}, + RouteNetlinkMessage, }; use crate::{try_rtnl, Error, Handle}; @@ -33,13 +33,14 @@ impl QDiscGetRequest { message, } = self; - let mut req = - NetlinkMessage::from(RtnlMessage::GetQueueDiscipline(message)); + let mut req = NetlinkMessage::from( + RouteNetlinkMessage::GetQueueDiscipline(message), + ); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { Ok(response) => Either::Left(response.map(move |msg| { - Ok(try_rtnl!(msg, RtnlMessage::NewQueueDiscipline)) + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewQueueDiscipline)) })), Err(e) => { Either::Right(future::err::(e).into_stream()) @@ -54,7 +55,7 @@ impl QDiscGetRequest { /// Get ingress qdisc pub fn ingress(mut self) -> Self { - self.message.header.parent = TC_H_INGRESS; + self.message.header.parent = TcHandle::INGRESS; self } } @@ -79,12 +80,12 @@ impl TrafficClassGetRequest { } = self; let mut req = - NetlinkMessage::from(RtnlMessage::GetTrafficClass(message)); + NetlinkMessage::from(RouteNetlinkMessage::GetTrafficClass(message)); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { Ok(response) => Either::Left(response.map(move |msg| { - Ok(try_rtnl!(msg, RtnlMessage::NewTrafficClass)) + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewTrafficClass)) })), Err(e) => { Either::Right(future::err::(e).into_stream()) @@ -112,13 +113,14 @@ impl TrafficFilterGetRequest { message, } = self; - let mut req = - NetlinkMessage::from(RtnlMessage::GetTrafficFilter(message)); + let mut req = NetlinkMessage::from( + RouteNetlinkMessage::GetTrafficFilter(message), + ); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { Ok(response) => Either::Left(response.map(move |msg| { - Ok(try_rtnl!(msg, RtnlMessage::NewTrafficFilter)) + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewTrafficFilter)) })), Err(e) => { Either::Right(future::err::(e).into_stream()) @@ -128,7 +130,7 @@ impl TrafficFilterGetRequest { /// Set parent to root. pub fn root(mut self) -> Self { - self.message.header.parent = TC_H_ROOT; + self.message.header.parent = TcHandle::ROOT; self } } @@ -153,12 +155,12 @@ impl TrafficChainGetRequest { } = self; let mut req = - NetlinkMessage::from(RtnlMessage::GetTrafficChain(message)); + NetlinkMessage::from(RouteNetlinkMessage::GetTrafficChain(message)); req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; match handle.request(req) { Ok(response) => Either::Left(response.map(move |msg| { - Ok(try_rtnl!(msg, RtnlMessage::NewTrafficChain)) + Ok(try_rtnl!(msg, RouteNetlinkMessage::NewTrafficChain)) })), Err(e) => { Either::Right(future::err::(e).into_stream()) diff --git a/src/traffic_control/handle.rs b/src/traffic_control/handle.rs index 9e2ab04..3d0b24a 100644 --- a/src/traffic_control/handle.rs +++ b/src/traffic_control/handle.rs @@ -7,7 +7,7 @@ use super::{ use crate::Handle; use netlink_packet_core::{NLM_F_CREATE, NLM_F_EXCL, NLM_F_REPLACE}; -use netlink_packet_route::TcMessage; +use netlink_packet_route::tc::TcMessage; pub struct QDiscHandle(Handle); diff --git a/src/traffic_control/test.rs b/src/traffic_control/test.rs index 64b63ed..02c95f5 100644 --- a/src/traffic_control/test.rs +++ b/src/traffic_control/test.rs @@ -5,8 +5,8 @@ use std::process::Command; use futures::stream::TryStreamExt; use netlink_packet_core::ErrorMessage; use netlink_packet_route::{ - tc::nlas::Nla::{Chain, HwOffload, Kind}, - TcMessage, AF_UNSPEC, + tc::{TcAttribute, TcMessage}, + AddressFamily, }; use tokio::runtime::Runtime; @@ -29,13 +29,19 @@ async fn _get_qdiscs() -> Vec { fn test_get_qdiscs() { let qdiscs = Runtime::new().unwrap().block_on(_get_qdiscs()); let qdisc_of_loopback_nic = &qdiscs[0]; - assert_eq!(qdisc_of_loopback_nic.header.family, AF_UNSPEC as u8); + assert_eq!(qdisc_of_loopback_nic.header.family, AddressFamily::Unspec); assert_eq!(qdisc_of_loopback_nic.header.index, 1); - assert_eq!(qdisc_of_loopback_nic.header.handle, 0); - assert_eq!(qdisc_of_loopback_nic.header.parent, u32::MAX); + assert_eq!(qdisc_of_loopback_nic.header.handle, 0.into()); + assert_eq!(qdisc_of_loopback_nic.header.parent, u32::MAX.into()); assert_eq!(qdisc_of_loopback_nic.header.info, 2); // refcount - assert_eq!(qdisc_of_loopback_nic.nlas[0], Kind("noqueue".to_string())); - assert_eq!(qdisc_of_loopback_nic.nlas[1], HwOffload(0)); + assert_eq!( + qdisc_of_loopback_nic.attributes[0], + TcAttribute::Kind("noqueue".to_string()) + ); + assert_eq!( + qdisc_of_loopback_nic.attributes[1], + TcAttribute::HwOffload(0) + ); } async fn _get_tclasses(ifindex: i32) -> Vec { @@ -264,24 +270,30 @@ fn test_get_traffic_classes_filters_and_chains() { _remove_test_dummy_interface(); assert_eq!(tclasses.len(), 1); let tclass = &tclasses[0]; - assert_eq!(tclass.header.family, AF_UNSPEC as u8); + assert_eq!(tclass.header.family, AddressFamily::Unspec); assert_eq!(tclass.header.index, ifindex); - assert_eq!(tclass.header.parent, u32::MAX); - assert_eq!(tclass.nlas[0], Kind("htb".to_string())); + assert_eq!(tclass.header.parent, u32::MAX.into()); + assert_eq!(tclass.attributes[0], TcAttribute::Kind("htb".to_string())); assert_eq!(filters.len(), 2); - assert_eq!(filters[0].header.family, AF_UNSPEC as u8); + assert_eq!(filters[0].header.family, AddressFamily::Unspec); assert_eq!(filters[0].header.index, ifindex); - assert_eq!(filters[0].header.parent, u16::MAX as u32 + 1); - assert_eq!(filters[0].nlas[0], Kind("basic".to_string())); - assert_eq!(filters[1].header.family, AF_UNSPEC as u8); + assert_eq!(filters[0].header.parent, (u16::MAX as u32 + 1).into()); + assert_eq!( + filters[0].attributes[0], + TcAttribute::Kind("basic".to_string()) + ); + assert_eq!(filters[1].header.family, AddressFamily::Unspec); assert_eq!(filters[1].header.index, ifindex); - assert_eq!(filters[1].header.parent, u16::MAX as u32 + 1); - assert_eq!(filters[1].nlas[0], Kind("basic".to_string())); + assert_eq!(filters[1].header.parent, (u16::MAX as u32 + 1).into()); + assert_eq!( + filters[1].attributes[0], + TcAttribute::Kind("basic".to_string()) + ); assert!(chains.len() <= 1); if chains.len() == 1 { - assert_eq!(chains[0].header.family, AF_UNSPEC as u8); + assert_eq!(chains[0].header.family, AddressFamily::Unspec); assert_eq!(chains[0].header.index, ifindex); - assert_eq!(chains[0].header.parent, u16::MAX as u32 + 1); - assert_eq!(chains[0].nlas[0], Chain([0u8, 0, 0, 0].to_vec())); + assert_eq!(chains[0].header.parent, (u16::MAX as u32 + 1).into()); + assert_eq!(chains[0].attributes[0], TcAttribute::Chain(0),); } } From e31996aef2b305331220870b0c4696423cc91d6b Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Tue, 5 Dec 2023 22:42:17 +0800 Subject: [PATCH 5/8] New release 0.14.0 === Breaking changes - Many `VxlanAddRequest` functions changed from u8 to bool. (ba4825a) - Deprecated `LinkSetRequest::master()` in the favor of `LinkSetRequest::controller()`. (ba4825a) - Deprecated `LinkSetRequest::nomaster()` in the favor of `LinkSetRequest::nocontroller()`. (ba4825a) - Many `NeighbourAddRequest` functions changed from u8/u16 to enum. (ba4825a) - Many `TrafficFilterNewRequest` functions changed from u8/u16 to enum. (ba4825a) === New features - Rule: function to set fw_mark when adding rule. (dabef43) === Bug fixes - N/A --- CHANGELOG | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 73f6c40..0759790 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,21 @@ # Changelog +## [0.14.0] - 2023-12-05 +### Breaking changes + - Many `VxlanAddRequest` functions changed from u8 to bool. (ba4825a) + - Deprecated `LinkSetRequest::master()` in the favor of + `LinkSetRequest::controller()`. (ba4825a) + - Deprecated `LinkSetRequest::nomaster()` in the favor of + `LinkSetRequest::nocontroller()`. (ba4825a) + - Many `NeighbourAddRequest` functions changed from u8/u16 to enum. (ba4825a) + - Many `TrafficFilterNewRequest` functions changed from u8/u16 to enum. + (ba4825a) + +### New features + - Rule: function to set fw_mark when adding rule. (dabef43) + +### Bug fixes + - N/A + ## [0.13.1] - 2023-07-18 ### Breaking changes - Deprecated `BondAddRequest::active_slave()` in the favor of From 006a348ad2ddc538ede9a71e8fdf582ed3ccb7bb Mon Sep 17 00:00:00 2001 From: Malte Janduda Date: Tue, 12 Dec 2023 13:22:38 +0100 Subject: [PATCH 6/8] Fixing docs of AddressGetRequest::set_address_filter --- src/addr/get.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addr/get.rs b/src/addr/get.rs index cec0b0b..c64d86d 100644 --- a/src/addr/get.rs +++ b/src/addr/get.rs @@ -72,7 +72,7 @@ impl AddressGetRequest { self } - /// Return only the addresses of the given prefix length. + /// Return only AddressMessages filtered by the given address. pub fn set_address_filter(mut self, address: IpAddr) -> Self { self.filter_builder.address = Some(address); self From c840e78f02b6616efa81dc1eb78fb4c1b213dcb0 Mon Sep 17 00:00:00 2001 From: Reed Morrison Date: Wed, 10 Jan 2024 20:19:03 +0800 Subject: [PATCH 7/8] Add pub function for setting route priority. Signed-off-by: Gris Ge Signed-off-by: Reed Morrison --- src/route/add.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/route/add.rs b/src/route/add.rs index ab1224d..1416049 100644 --- a/src/route/add.rs +++ b/src/route/add.rs @@ -58,6 +58,14 @@ impl RouteAddRequest { self } + /// Sets the route priority (metric) + pub fn priority(mut self, priority: u32) -> Self { + self.message + .attributes + .push(RouteAttribute::Priority(priority)); + self + } + /// Sets the route table. /// /// Default is main route table. From 24982ec617f397935a66569d5674ac59d054bb3b Mon Sep 17 00:00:00 2001 From: Dmitri Toubelis Date: Wed, 10 Jan 2024 20:27:58 +0800 Subject: [PATCH 8/8] Add wireguard link --- src/link/add.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/link/add.rs b/src/link/add.rs index bf319e7..f998fb0 100644 --- a/src/link/add.rs +++ b/src/link/add.rs @@ -756,6 +756,18 @@ impl LinkAddRequest { .append_nla(LinkAttribute::IfName(name)) } + /// Create a wireguard link. + /// This is equivalent to `ip link add NAME type wireguard`. + pub fn wireguard(self, name: String) -> Self { + let mut request = self.name(name).link_info(InfoKind::Wireguard, None); + request + .message_mut() + .header + .flags + .retain(|f| *f != LinkFlag::Up); + request + } + /// Replace existing matching link. pub fn replace(self) -> Self { Self {