diff --git a/rtnetlink/Cargo.toml b/rtnetlink/Cargo.toml index 337f1871..cbff579f 100644 --- a/rtnetlink/Cargo.toml +++ b/rtnetlink/Cargo.toml @@ -26,6 +26,7 @@ netlink-proto = { default-features = false, version = "0.9" } nix = "0.22.0" tokio = { version = "1.0.1", features = ["rt"], optional = true} async-global-executor = { version = "2.0.2", optional = true } +bitflags = "1.3.2" [dev-dependencies] env_logger = "0.8.2" diff --git a/rtnetlink/src/addr/add.rs b/rtnetlink/src/addr/add.rs index 7f73768d..b64f0b08 100644 --- a/rtnetlink/src/addr/add.rs +++ b/rtnetlink/src/addr/add.rs @@ -3,27 +3,19 @@ use futures::stream::StreamExt; use std::net::{IpAddr, Ipv4Addr}; -use netlink_packet_route::{ - nlas::address::Nla, - AddressMessage, - NetlinkMessage, - RtnlMessage, - AF_INET, - AF_INET6, - NLM_F_ACK, - NLM_F_CREATE, - NLM_F_EXCL, - NLM_F_REPLACE, - NLM_F_REQUEST, +use crate::{ + flags::NewFlags, + packet::{nlas::address::Nla, AddressMessage, NetlinkMessage, RtnlMessage, AF_INET, AF_INET6}, + try_nl, + Error, + Handle, }; -use crate::{try_nl, Error, Handle}; - /// A request to create a new address. This is equivalent to the `ip address add` commands. pub struct AddressAddRequest { handle: Handle, message: AddressMessage, - replace: bool, + flags: NewFlags, } impl AddressAddRequest { @@ -73,15 +65,7 @@ impl AddressAddRequest { AddressAddRequest { handle, message, - replace: false, - } - } - - /// Replace existing matching address. - pub fn replace(self) -> Self { - Self { - replace: true, - ..self + flags: NewFlags::new() | NewFlags::EXCL, } } @@ -90,11 +74,10 @@ impl AddressAddRequest { let AddressAddRequest { mut handle, message, - replace, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::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; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -107,4 +90,15 @@ impl AddressAddRequest { pub fn message_mut(&mut self) -> &mut AddressMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/addr/del.rs b/rtnetlink/src/addr/del.rs index 9f581185..a895f070 100644 --- a/rtnetlink/src/addr/del.rs +++ b/rtnetlink/src/addr/del.rs @@ -3,7 +3,8 @@ use futures::stream::StreamExt; use crate::{ - packet::{AddressMessage, NetlinkMessage, RtnlMessage, NLM_F_ACK, NLM_F_REQUEST}, + flags::DelFlags, + packet::{AddressMessage, NetlinkMessage, RtnlMessage}, try_nl, Error, Handle, @@ -12,11 +13,16 @@ use crate::{ pub struct AddressDelRequest { handle: Handle, message: AddressMessage, + flags: DelFlags, } impl AddressDelRequest { pub(crate) fn new(handle: Handle, message: AddressMessage) -> Self { - AddressDelRequest { handle, message } + AddressDelRequest { + handle, + message, + flags: DelFlags::new(), + } } /// Execute the request @@ -24,10 +30,11 @@ impl AddressDelRequest { let AddressDelRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::DelAddress(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(msg) = response.next().await { try_nl!(msg); @@ -38,4 +45,15 @@ impl AddressDelRequest { pub fn message_mut(&mut self) -> &mut AddressMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: DelFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/addr/get.rs b/rtnetlink/src/addr/get.rs index 6b279067..f7704f85 100644 --- a/rtnetlink/src/addr/get.rs +++ b/rtnetlink/src/addr/get.rs @@ -7,21 +7,19 @@ use futures::{ }; use std::net::IpAddr; -use netlink_packet_route::{ - nlas::address::Nla, - AddressMessage, - NetlinkMessage, - RtnlMessage, - NLM_F_DUMP, - NLM_F_REQUEST, +use crate::{ + flags::GetFlags, + packet::{nlas::address::Nla, AddressMessage, NetlinkMessage, RtnlMessage}, + try_rtnl, + Error, + Handle, }; -use crate::{try_rtnl, Error, Handle}; - pub struct AddressGetRequest { handle: Handle, message: AddressMessage, filter_builder: AddressFilterBuilder, + flags: GetFlags, } impl AddressGetRequest { @@ -30,6 +28,7 @@ impl AddressGetRequest { handle, message: AddressMessage::default(), filter_builder: AddressFilterBuilder::new(), + flags: GetFlags::new() | GetFlags::DUMP, } } @@ -37,15 +36,27 @@ impl AddressGetRequest { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: GetFlags) -> Self { + self.flags = flags; + self + } + pub fn execute(self) -> impl TryStream { let AddressGetRequest { mut handle, message, filter_builder, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::GetAddress(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; + req.header.flags = flags.bits(); let filter = filter_builder.build(); match handle.request(req) { diff --git a/rtnetlink/src/flags.rs b/rtnetlink/src/flags.rs new file mode 100644 index 00000000..6cea75c0 --- /dev/null +++ b/rtnetlink/src/flags.rs @@ -0,0 +1,132 @@ +bitflags::bitflags! { + pub struct GetFlags: u16 { + /// Must be set on all request messages (typically from user + /// space to kernel space) + /// + /// **This flag is set by default** + const REQUEST = 1; + /// Indicates the message is part of a multipart message + /// terminated by NLMSG_DONE + const MULTIPART = 2; + /// Request for an acknowledgment on success. Typical + /// direction of request is from user space (CPC) to kernel + /// space (FEC). + const ACK = 4; + /// Echo this request. Typical direction of request is from + /// user space (CPC) to kernel space (FEC). + const ECHO = 8; + /// Return the complete table instead of a single entry. + const ROOT = 256; + /// Return all entries matching criteria passed in message + /// content. + const MATCH = 512; + /// Return an atomic snapshot of the table. Requires + /// `CAP_NET_ADMIN` capability or a effective UID of 0. + const ATOMIC = 1024; + /// Equivalent to `ROOT|MATCH`. + const DUMP = 768; + } +} + +impl GetFlags { + /// Create new `GetFlags` with only `GetFlags::REQUEST`. + pub fn new() -> Self { + GetFlags::REQUEST + } +} + +impl Default for GetFlags { + /// Create new `GetFlags` with only `GetFlags::REQUEST`. + fn default() -> Self { + Self::new() + } +} + +bitflags::bitflags! { + pub struct NewFlags: u16 { + /// Must be set on all request messages (typically from user + /// space to kernel space). + /// + /// **This flag is set by default** + const REQUEST = 1; + /// Indicates the message is part of a multipart message + /// terminated by NLMSG_DONE + const MULTIPART = 2; + /// Request for an acknowledgment on success. Typical + /// direction of request is from user space (CPC) to kernel + /// space (FEC). + /// + /// **This flag is set by default** + const ACK = 4; + /// Echo this request. Typical direction of request is from + /// user space (CPC) to kernel space (FEC). + const ECHO = 8; + /// Replace existing matching object. + const REPLACE = 256; + /// Don't replace if the object already exists. + /// + /// This flag is not set by default but can is pretty commonly + /// used. + const EXCL = 512; + /// Create object if it doesn't already exist. + /// + /// **This flag is set by default** + const CREATE = 1024; + /// Add to the end of the object list. + const APPEND = 2048; + /// Do not delete recursively + const NONREC = 256; + } +} + +impl NewFlags { + /// Create new `NewFlags` with `REQUEST | ACK | CREATE` set. + pub fn new() -> Self { + Self::REQUEST | Self::ACK | Self::CREATE + } +} + +impl Default for NewFlags { + /// Create new `NewFlags` with `REQUEST | ACK | CREATE` set. + fn default() -> Self { + Self::new() + } +} + +bitflags::bitflags! { + pub struct DelFlags: u16 { + /// Must be set on all request messages (typically from user + /// space to kernel space) + /// + /// **This flag is set by default** + const REQUEST = 1; + /// Indicates the message is part of a multipart message + /// terminated by NLMSG_DONE + const MULTIPART = 2; + /// Request for an acknowledgment on success. Typical + /// direction of request is from user space (CPC) to kernel + /// space (FEC). + /// + /// **This flag is set by default** + const ACK = 4; + /// Echo this request. Typical direction of request is from + /// user space (CPC) to kernel space (FEC). + const ECHO = 8; + /// Do not delete recursively + const NONREC = 256; + } +} + +impl DelFlags { + /// Create a new `DelFlags` with `REQUEST | ACK` set + pub fn new() -> Self { + Self::REQUEST | Self::ACK + } +} + +impl Default for DelFlags { + /// Create a new `DelFlags` with `REQUEST | ACK` set + fn default() -> Self { + Self::new() + } +} diff --git a/rtnetlink/src/lib.rs b/rtnetlink/src/lib.rs index c4aa3f08..997f71a9 100644 --- a/rtnetlink/src/lib.rs +++ b/rtnetlink/src/lib.rs @@ -48,4 +48,5 @@ pub mod proto { } pub use netlink_proto::sys; +pub mod flags; mod macros; diff --git a/rtnetlink/src/link/add.rs b/rtnetlink/src/link/add.rs index c8cf73ad..4c3e1708 100644 --- a/rtnetlink/src/link/add.rs +++ b/rtnetlink/src/link/add.rs @@ -3,17 +3,13 @@ use futures::stream::StreamExt; use crate::{ + flags::NewFlags, packet::{ nlas::link::{Info, InfoData, InfoKind, InfoMacVlan, InfoVlan, InfoVxlan, Nla, VethInfo}, LinkMessage, NetlinkMessage, RtnlMessage, IFF_UP, - NLM_F_ACK, - NLM_F_CREATE, - NLM_F_EXCL, - NLM_F_REPLACE, - NLM_F_REQUEST, }, try_nl, Error, @@ -247,7 +243,7 @@ impl VxlanAddRequest { pub struct LinkAddRequest { handle: Handle, message: LinkMessage, - replace: bool, + flags: NewFlags, } impl LinkAddRequest { @@ -255,7 +251,7 @@ impl LinkAddRequest { LinkAddRequest { handle, message: LinkMessage::default(), - replace: false, + flags: NewFlags::new(), } } @@ -264,11 +260,10 @@ impl LinkAddRequest { let LinkAddRequest { mut handle, message, - replace, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::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; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -304,6 +299,17 @@ impl LinkAddRequest { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } + /// Create a dummy link. /// This is equivalent to `ip link add NAME type dummy`. pub fn dummy(self, name: String) -> Self { @@ -376,14 +382,6 @@ impl LinkAddRequest { .append_nla(Nla::IfName(name)) } - /// Replace existing matching link. - pub fn replace(self) -> Self { - Self { - replace: true, - ..self - } - } - fn up(mut self) -> Self { self.message.header.flags = IFF_UP; self.message.header.change_mask = IFF_UP; diff --git a/rtnetlink/src/link/del.rs b/rtnetlink/src/link/del.rs index 298d37f2..ecd6ca1d 100644 --- a/rtnetlink/src/link/del.rs +++ b/rtnetlink/src/link/del.rs @@ -3,15 +3,8 @@ use futures::stream::StreamExt; use crate::{ - packet::{ - LinkMessage, - NetlinkMessage, - RtnlMessage, - NLM_F_ACK, - NLM_F_CREATE, - NLM_F_EXCL, - NLM_F_REQUEST, - }, + flags::DelFlags, + packet::{LinkMessage, NetlinkMessage, RtnlMessage}, try_nl, Error, Handle, @@ -20,13 +13,18 @@ use crate::{ pub struct LinkDelRequest { handle: Handle, message: LinkMessage, + flags: DelFlags, } impl LinkDelRequest { pub(crate) fn new(handle: Handle, index: u32) -> Self { let mut message = LinkMessage::default(); message.header.index = index; - LinkDelRequest { handle, message } + LinkDelRequest { + handle, + message, + flags: DelFlags::new(), + } } /// Execute the request @@ -34,9 +32,10 @@ impl LinkDelRequest { let LinkDelRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::DelLink(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -49,4 +48,15 @@ impl LinkDelRequest { pub fn message_mut(&mut self) -> &mut LinkMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: DelFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/link/get.rs b/rtnetlink/src/link/get.rs index 4ed4d706..41a3ad80 100644 --- a/rtnetlink/src/link/get.rs +++ b/rtnetlink/src/link/get.rs @@ -7,7 +7,8 @@ use futures::{ }; use crate::{ - packet::{constants::*, nlas::link::Nla, LinkMessage, NetlinkMessage, RtnlMessage}, + flags::GetFlags, + packet::{nlas::link::Nla, LinkMessage, NetlinkMessage, RtnlMessage}, try_rtnl, Error, Handle, @@ -16,13 +17,7 @@ use crate::{ pub struct LinkGetRequest { handle: Handle, message: LinkMessage, - // There are two ways to retrieve links: we can either dump them - // all and filter the result, or if we already know the index or - // the name of the link we're looking for, we can just retrieve - // that one. If `dump` is `true`, all the links are fetched. - // Otherwise, only the link that match the given index or name - // is fetched. - dump: bool, + flags: GetFlags, } impl LinkGetRequest { @@ -30,7 +25,7 @@ impl LinkGetRequest { LinkGetRequest { handle, message: LinkMessage::default(), - dump: true, + flags: GetFlags::new() | GetFlags::DUMP, } } @@ -46,16 +41,11 @@ impl LinkGetRequest { let LinkGetRequest { mut handle, message, - dump, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::GetLink(message)); - - if dump { - req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; - } else { - req.header.flags = NLM_F_REQUEST; - } + req.header.flags = flags.bits(); match handle.request(req) { Ok(response) => { @@ -72,7 +62,7 @@ impl LinkGetRequest { /// Lookup a link by index pub fn match_index(mut self, index: u32) -> Self { - self.dump = false; + self.flags.remove(GetFlags::DUMP); self.message.header.index = index; self } @@ -82,8 +72,19 @@ impl LinkGetRequest { /// This function requires support from your kernel (>= 2.6.33). If yours is /// older, consider filtering the resulting stream of links. pub fn match_name(mut self, name: String) -> Self { - self.dump = false; + self.flags.remove(GetFlags::DUMP); self.message.nlas.push(Nla::IfName(name)); self } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: GetFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/link/property_add.rs b/rtnetlink/src/link/property_add.rs index 5780a3c0..ece659c5 100644 --- a/rtnetlink/src/link/property_add.rs +++ b/rtnetlink/src/link/property_add.rs @@ -1,17 +1,13 @@ // SPDX-License-Identifier: MIT use crate::{ + flags::NewFlags, packet::{ nlas::link::{Nla, Prop}, LinkMessage, NetlinkMessage, NetlinkPayload, RtnlMessage, - NLM_F_ACK, - NLM_F_APPEND, - NLM_F_CREATE, - NLM_F_EXCL, - NLM_F_REQUEST, }, Error, Handle, @@ -21,13 +17,19 @@ use futures::stream::StreamExt; pub struct LinkNewPropRequest { handle: Handle, message: LinkMessage, + flags: NewFlags, } impl LinkNewPropRequest { pub(crate) fn new(handle: Handle, index: u32) -> Self { let mut message = LinkMessage::default(); message.header.index = index; - LinkNewPropRequest { handle, message } + let flags = NewFlags::new() | NewFlags::EXCL | NewFlags::APPEND; + LinkNewPropRequest { + handle, + message, + flags, + } } /// Execute the request @@ -35,9 +37,10 @@ impl LinkNewPropRequest { let LinkNewPropRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::NewLinkProp(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -53,6 +56,17 @@ impl LinkNewPropRequest { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } + /// Add alternative name to the link. This is equivalent to `ip link property add altname /// ALT_IFNAME dev LINK`. pub fn alt_ifname(mut self, alt_ifnames: &[&str]) -> Self { diff --git a/rtnetlink/src/link/property_del.rs b/rtnetlink/src/link/property_del.rs index aa5edd1b..d0b80920 100644 --- a/rtnetlink/src/link/property_del.rs +++ b/rtnetlink/src/link/property_del.rs @@ -1,15 +1,13 @@ // SPDX-License-Identifier: MIT use crate::{ + flags::NewFlags, packet::{ nlas::link::{Nla, Prop}, LinkMessage, NetlinkMessage, NetlinkPayload, RtnlMessage, - NLM_F_ACK, - NLM_F_EXCL, - NLM_F_REQUEST, }, Error, Handle, @@ -19,13 +17,19 @@ use futures::stream::StreamExt; pub struct LinkDelPropRequest { handle: Handle, message: LinkMessage, + flags: NewFlags, } impl LinkDelPropRequest { pub(crate) fn new(handle: Handle, index: u32) -> Self { let mut message = LinkMessage::default(); message.header.index = index; - LinkDelPropRequest { handle, message } + let flags = NewFlags::new() | NewFlags::EXCL | NewFlags::APPEND; + LinkDelPropRequest { + handle, + message, + flags, + } } /// Execute the request @@ -33,9 +37,10 @@ impl LinkDelPropRequest { let LinkDelPropRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::DelLinkProp(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -51,6 +56,17 @@ impl LinkDelPropRequest { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } + /// Remove alternative name to the link. This is equivalent to `ip link property del altname /// ALT_IFNAME dev LINK`. pub fn alt_ifname(mut self, alt_ifnames: &[&str]) -> Self { diff --git a/rtnetlink/src/link/set.rs b/rtnetlink/src/link/set.rs index 43f9fe72..80a0489b 100644 --- a/rtnetlink/src/link/set.rs +++ b/rtnetlink/src/link/set.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT use crate::{ + flags::NewFlags, packet::{ nlas::link::Nla, LinkMessage, @@ -9,10 +10,6 @@ use crate::{ IFF_NOARP, IFF_PROMISC, IFF_UP, - NLM_F_ACK, - NLM_F_CREATE, - NLM_F_EXCL, - NLM_F_REQUEST, }, try_nl, Error, @@ -24,13 +21,19 @@ use std::os::unix::io::RawFd; pub struct LinkSetRequest { handle: Handle, message: LinkMessage, + flags: NewFlags, } impl LinkSetRequest { pub(crate) fn new(handle: Handle, index: u32) -> Self { let mut message = LinkMessage::default(); message.header.index = index; - LinkSetRequest { handle, message } + let flags = NewFlags::new() | NewFlags::EXCL; + LinkSetRequest { + handle, + message, + flags, + } } /// Execute the request @@ -38,9 +41,10 @@ impl LinkSetRequest { let LinkSetRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::SetLink(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -54,6 +58,17 @@ impl LinkSetRequest { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } + /// Attach the link to a bridge (its _master_). 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. /// diff --git a/rtnetlink/src/neighbour/add.rs b/rtnetlink/src/neighbour/add.rs index 49cf243a..a827c456 100644 --- a/rtnetlink/src/neighbour/add.rs +++ b/rtnetlink/src/neighbour/add.rs @@ -11,13 +11,13 @@ use netlink_packet_route::{ use netlink_proto::packet::NetlinkMessage; -use crate::{Error, Handle}; +use crate::{flags::NewFlags, Error, Handle}; use std::net::IpAddr; pub struct NeighbourAddRequest { handle: Handle, message: NeighbourMessage, - replace: bool, + flags: NewFlags, } impl NeighbourAddRequest { @@ -41,7 +41,7 @@ impl NeighbourAddRequest { NeighbourAddRequest { handle, message, - replace: false, + flags: NewFlags::new() | NewFlags::EXCL, } } @@ -58,7 +58,7 @@ impl NeighbourAddRequest { NeighbourAddRequest { handle, message, - replace: false, + flags: NewFlags::new() | NewFlags::EXCL, } } @@ -120,25 +120,16 @@ impl NeighbourAddRequest { self } - /// Replace existing matching neighbor. - pub fn replace(self) -> Self { - Self { - replace: true, - ..self - } - } - /// Execute the request. pub async fn execute(self) -> Result<(), Error> { let NeighbourAddRequest { mut handle, message, - replace, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::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; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -154,4 +145,15 @@ impl NeighbourAddRequest { pub fn message_mut(&mut self) -> &mut NeighbourMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/neighbour/del.rs b/rtnetlink/src/neighbour/del.rs index ee13c6f7..4dd4d625 100644 --- a/rtnetlink/src/neighbour/del.rs +++ b/rtnetlink/src/neighbour/del.rs @@ -2,25 +2,26 @@ use futures::stream::StreamExt; -use netlink_packet_route::{ - constants::*, - neighbour::NeighbourMessage, - NetlinkPayload, - RtnlMessage, +use crate::{ + flags::DelFlags, + packet::{neighbour::NeighbourMessage, NetlinkMessage, NetlinkPayload, RtnlMessage}, + Error, + Handle, }; -use netlink_proto::packet::NetlinkMessage; - -use crate::{Error, Handle}; - pub struct NeighbourDelRequest { handle: Handle, message: NeighbourMessage, + flags: DelFlags, } impl NeighbourDelRequest { pub(crate) fn new(handle: Handle, message: NeighbourMessage) -> Self { - NeighbourDelRequest { handle, message } + NeighbourDelRequest { + handle, + message, + flags: DelFlags::new(), + } } /// Execute the request @@ -28,10 +29,11 @@ impl NeighbourDelRequest { let NeighbourDelRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::DelNeighbour(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(msg) = response.next().await { if let NetlinkPayload::Error(e) = msg.payload { @@ -44,4 +46,15 @@ impl NeighbourDelRequest { pub fn message_mut(&mut self) -> &mut NeighbourMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: DelFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/neighbour/get.rs b/rtnetlink/src/neighbour/get.rs index df2c9efa..da2c8273 100644 --- a/rtnetlink/src/neighbour/get.rs +++ b/rtnetlink/src/neighbour/get.rs @@ -6,26 +6,34 @@ use futures::{ FutureExt, }; -use netlink_packet_route::{ - constants::*, - neighbour::NeighbourMessage, - NetlinkPayload, - RtnlMessage, +use crate::{ + flags::GetFlags, + packet::{ + constants::*, + neighbour::NeighbourMessage, + NetlinkMessage, + NetlinkPayload, + RtnlMessage, + }, + Error, + Handle, + IpVersion, }; -use netlink_proto::packet::NetlinkMessage; - -use crate::{Error, Handle, IpVersion}; - pub struct NeighbourGetRequest { handle: Handle, message: NeighbourMessage, + flags: GetFlags, } impl NeighbourGetRequest { pub(crate) fn new(handle: Handle) -> Self { let message = NeighbourMessage::default(); - NeighbourGetRequest { handle, message } + NeighbourGetRequest { + handle, + message, + flags: GetFlags::new() | GetFlags::DUMP, + } } /// List neighbor proxies in the system (equivalent to: `ip neighbor show proxy`). @@ -44,10 +52,11 @@ impl NeighbourGetRequest { let NeighbourGetRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::GetNeighbour(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; + req.header.flags = flags.bits(); match handle.request(req) { Ok(response) => Either::Left(response.map(move |msg| { @@ -68,4 +77,15 @@ impl NeighbourGetRequest { pub fn message_mut(&mut self) -> &mut NeighbourMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: GetFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/route/add.rs b/rtnetlink/src/route/add.rs index d6d7c5cd..98887e37 100644 --- a/rtnetlink/src/route/add.rs +++ b/rtnetlink/src/route/add.rs @@ -1,26 +1,25 @@ // SPDX-License-Identifier: MIT -use futures::stream::StreamExt; use std::{ marker::PhantomData, net::{Ipv4Addr, Ipv6Addr}, }; -use netlink_packet_route::{ - constants::*, - nlas::route::Nla, - NetlinkMessage, - RouteMessage, - RtnlMessage, -}; +use futures::stream::StreamExt; -use crate::{try_nl, Error, Handle}; +use crate::{ + flags::NewFlags, + packet::{constants::*, nlas::route::Nla, NetlinkMessage, RouteMessage, RtnlMessage}, + try_nl, + Error, + Handle, +}; /// A request to create a new route. This is equivalent to the `ip route add` commands. pub struct RouteAddRequest { handle: Handle, message: RouteMessage, - replace: bool, + flags: NewFlags, _phantom: PhantomData, } @@ -36,7 +35,7 @@ impl RouteAddRequest { RouteAddRequest { handle, message, - replace: false, + flags: NewFlags::new() | NewFlags::EXCL, _phantom: Default::default(), } } @@ -91,7 +90,7 @@ impl RouteAddRequest { RouteAddRequest { handle: self.handle, message: self.message, - replace: false, + flags: self.flags, _phantom: Default::default(), } } @@ -102,30 +101,21 @@ impl RouteAddRequest { RouteAddRequest { handle: self.handle, message: self.message, - replace: false, + flags: self.flags, _phantom: Default::default(), } } - /// Replace existing matching route. - pub fn replace(self) -> Self { - Self { - replace: true, - ..self - } - } - /// Execute the request. pub async fn execute(self) -> Result<(), Error> { let RouteAddRequest { mut handle, message, - replace, + flags, .. } = self; let mut req = NetlinkMessage::from(RtnlMessage::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; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -138,6 +128,17 @@ impl RouteAddRequest { pub fn message_mut(&mut self) -> &mut RouteMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } } impl RouteAddRequest { diff --git a/rtnetlink/src/route/del.rs b/rtnetlink/src/route/del.rs index c10bcbf6..d295a125 100644 --- a/rtnetlink/src/route/del.rs +++ b/rtnetlink/src/route/del.rs @@ -3,7 +3,8 @@ use futures::stream::StreamExt; use crate::{ - packet::{NetlinkMessage, NetlinkPayload, RouteMessage, RtnlMessage, NLM_F_ACK, NLM_F_REQUEST}, + flags::DelFlags, + packet::{NetlinkMessage, NetlinkPayload, RouteMessage, RtnlMessage}, Error, Handle, }; @@ -11,11 +12,16 @@ use crate::{ pub struct RouteDelRequest { handle: Handle, message: RouteMessage, + flags: DelFlags, } impl RouteDelRequest { pub(crate) fn new(handle: Handle, message: RouteMessage) -> Self { - RouteDelRequest { handle, message } + RouteDelRequest { + handle, + message, + flags: DelFlags::new(), + } } /// Execute the request @@ -23,10 +29,11 @@ impl RouteDelRequest { let RouteDelRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::DelRoute(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(msg) = response.next().await { if let NetlinkPayload::Error(e) = msg.payload { @@ -39,4 +46,15 @@ impl RouteDelRequest { pub fn message_mut(&mut self) -> &mut RouteMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: DelFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/route/get.rs b/rtnetlink/src/route/get.rs index 8429f674..3a384ee6 100644 --- a/rtnetlink/src/route/get.rs +++ b/rtnetlink/src/route/get.rs @@ -6,13 +6,18 @@ use futures::{ FutureExt, }; -use netlink_packet_route::{constants::*, NetlinkMessage, RouteMessage, RtnlMessage}; - -use crate::{try_rtnl, Error, Handle}; +use crate::{ + flags::GetFlags, + packet::{constants::*, NetlinkMessage, RouteMessage, RtnlMessage}, + try_rtnl, + Error, + Handle, +}; pub struct RouteGetRequest { handle: Handle, message: RouteMessage, + flags: GetFlags, } /// Internet Protocol (IP) version. @@ -54,21 +59,37 @@ impl RouteGetRequest { message.header.table = RT_TABLE_UNSPEC; message.header.protocol = RTPROT_UNSPEC; - RouteGetRequest { handle, message } + RouteGetRequest { + handle, + message, + flags: GetFlags::new() | GetFlags::DUMP, + } } pub fn message_mut(&mut self) -> &mut RouteMessage { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: GetFlags) -> Self { + self.flags = flags; + self + } + pub fn execute(self) -> impl TryStream { let RouteGetRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::GetRoute(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; + req.header.flags = flags.bits(); match handle.request(req) { Ok(response) => { diff --git a/rtnetlink/src/rule/add.rs b/rtnetlink/src/rule/add.rs index 1de05e61..13d10733 100644 --- a/rtnetlink/src/rule/add.rs +++ b/rtnetlink/src/rule/add.rs @@ -1,26 +1,25 @@ // SPDX-License-Identifier: MIT -use futures::stream::StreamExt; use std::{ marker::PhantomData, net::{Ipv4Addr, Ipv6Addr}, }; -use netlink_packet_route::{ - constants::*, - nlas::rule::Nla, - NetlinkMessage, - RtnlMessage, - RuleMessage, -}; +use futures::stream::StreamExt; -use crate::{try_nl, Error, Handle}; +use crate::{ + flags::NewFlags, + packet::{constants::*, nlas::rule::Nla, NetlinkMessage, RtnlMessage, RuleMessage}, + try_nl, + Error, + Handle, +}; /// A request to create a new rule. This is equivalent to the `ip rule add` command. pub struct RuleAddRequest { handle: Handle, message: RuleMessage, - replace: bool, + flags: NewFlags, _phantom: PhantomData, } @@ -34,7 +33,7 @@ impl RuleAddRequest { RuleAddRequest { handle, message, - replace: false, + flags: NewFlags::new() | NewFlags::EXCL, _phantom: Default::default(), } } @@ -77,7 +76,7 @@ impl RuleAddRequest { RuleAddRequest { handle: self.handle, message: self.message, - replace: false, + flags: self.flags, _phantom: Default::default(), } } @@ -88,30 +87,21 @@ impl RuleAddRequest { RuleAddRequest { handle: self.handle, message: self.message, - replace: false, + flags: self.flags, _phantom: Default::default(), } } - /// Replace existing matching rule. - pub fn replace(self) -> Self { - Self { - replace: true, - ..self - } - } - /// Execute the request. pub async fn execute(self) -> Result<(), Error> { let RuleAddRequest { mut handle, message, - replace, + flags, .. } = self; let mut req = NetlinkMessage::from(RtnlMessage::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; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(message) = response.next().await { @@ -124,6 +114,17 @@ impl RuleAddRequest { pub fn message_mut(&mut self) -> &mut RuleMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: NewFlags) -> Self { + self.flags = flags; + self + } } impl RuleAddRequest { diff --git a/rtnetlink/src/rule/del.rs b/rtnetlink/src/rule/del.rs index a296b37c..205fc9f4 100644 --- a/rtnetlink/src/rule/del.rs +++ b/rtnetlink/src/rule/del.rs @@ -3,7 +3,8 @@ use futures::stream::StreamExt; use crate::{ - packet::{NetlinkMessage, RtnlMessage, RuleMessage, NLM_F_ACK, NLM_F_REQUEST}, + flags::DelFlags, + packet::{NetlinkMessage, RtnlMessage, RuleMessage}, try_nl, Error, Handle, @@ -12,11 +13,16 @@ use crate::{ pub struct RuleDelRequest { handle: Handle, message: RuleMessage, + flags: DelFlags, } impl RuleDelRequest { pub(crate) fn new(handle: Handle, message: RuleMessage) -> Self { - RuleDelRequest { handle, message } + RuleDelRequest { + handle, + message, + flags: DelFlags::new(), + } } /// Execute the request @@ -24,10 +30,11 @@ impl RuleDelRequest { let RuleDelRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::DelRule(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_ACK; + req.header.flags = flags.bits(); let mut response = handle.request(req)?; while let Some(msg) = response.next().await { try_nl!(msg); @@ -38,4 +45,15 @@ impl RuleDelRequest { pub fn message_mut(&mut self) -> &mut RuleMessage { &mut self.message } + + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: DelFlags) -> Self { + self.flags = flags; + self + } } diff --git a/rtnetlink/src/rule/get.rs b/rtnetlink/src/rule/get.rs index 4d28a848..2da5df7e 100644 --- a/rtnetlink/src/rule/get.rs +++ b/rtnetlink/src/rule/get.rs @@ -1,19 +1,24 @@ // SPDX-License-Identifier: MIT -use crate::IpVersion; use futures::{ future::{self, Either}, stream::{StreamExt, TryStream}, FutureExt, }; -use netlink_packet_route::{constants::*, NetlinkMessage, RtnlMessage, RuleMessage}; - -use crate::{try_rtnl, Error, Handle}; +use crate::{ + flags::GetFlags, + packet::{constants::*, NetlinkMessage, RtnlMessage, RuleMessage}, + try_rtnl, + Error, + Handle, + IpVersion, +}; pub struct RuleGetRequest { handle: Handle, message: RuleMessage, + flags: GetFlags, } impl RuleGetRequest { @@ -27,21 +32,37 @@ impl RuleGetRequest { message.header.action = FR_ACT_UNSPEC; message.header.table = RT_TABLE_UNSPEC; - RuleGetRequest { handle, message } + RuleGetRequest { + handle, + message, + flags: GetFlags::new() | GetFlags::DUMP, + } } pub fn message_mut(&mut self) -> &mut RuleMessage { &mut self.message } + /// Set the netlink header flags. + /// + /// # Warning + /// + /// Altering the request's flags may render the request + /// ineffective. Only set the flags if you know what you're doing. + pub fn set_flags(mut self, flags: GetFlags) -> Self { + self.flags = flags; + self + } + pub fn execute(self) -> impl TryStream { let RuleGetRequest { mut handle, message, + flags, } = self; let mut req = NetlinkMessage::from(RtnlMessage::GetRule(message)); - req.header.flags = NLM_F_REQUEST | NLM_F_DUMP; + req.header.flags = flags.bits(); match handle.request(req) { Ok(response) => {