aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-11-17 18:07:39 +0100
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-11-17 18:07:39 +0100
commit2c20dc2932696cb87ea7e6eb5327b7dccf0e9b1b (patch)
tree1d6a940d19d8e73aa86a63445d0caad9689ae509
parente90ee46c1aeb83973da25e9b104c896baddc475d (diff)
add function to get all ip addresses of an interface, replacing the linkaddrs crate0.3.0
-rw-r--r--Cargo.toml2
-rw-r--r--src/addr.rs57
-rw-r--r--src/blocking.rs7
3 files changed, 62 insertions, 4 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 39950b6..e028539 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rsdsl_netlinklib"
-version = "0.2.1"
+version = "0.3.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/addr.rs b/src/addr.rs
index 72b63c4..36efe1a 100644
--- a/src/addr.rs
+++ b/src/addr.rs
@@ -2,10 +2,12 @@
use crate::{Error, Result};
-use std::net::IpAddr;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-use futures::{future, TryStreamExt};
-use netlink_packet_route::{AddressMessage, AF_INET, AF_INET6, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE};
+use futures::{future, TryStream, TryStreamExt};
+use netlink_packet_route::{
+ address::Nla, AddressMessage, AF_INET, AF_INET6, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE,
+};
/// Flushes all addresses of an interface.
pub async fn flush(link: String) -> Result<()> {
@@ -171,3 +173,52 @@ pub async fn add_link_local(link: String, addr: IpAddr, prefix_len: u8) -> Resul
Ok(())
}
+
+/// Returns an iterator over the IP addresses of an interface.
+pub async fn get(link: String) -> Result<impl TryStream<Ok = IpAddr, Error = Error>> {
+ let (conn, handle, _) = rtnetlink::new_connection()?;
+ tokio::spawn(conn);
+
+ let link = handle
+ .link()
+ .get()
+ .match_name(link.clone())
+ .execute()
+ .try_next()
+ .await?
+ .ok_or(Error::LinkNotFound(link))?;
+
+ Ok(handle
+ .address()
+ .get()
+ .set_link_index_filter(link.header.index)
+ .execute()
+ .err_into::<Error>()
+ .try_filter_map(|msg| {
+ future::ready(Ok(if let Some(Nla::Address(bytes)) = msg.nlas.first() {
+ match msg.header.family as u16 {
+ AF_INET => {
+ let octets: [u8; 4] = (*bytes)
+ .clone()
+ .try_into()
+ .expect("nla does not match ipv4 address length");
+ let ip = IpAddr::from(Ipv4Addr::from(octets));
+
+ Some(ip)
+ }
+ AF_INET6 => {
+ let octets: [u8; 16] = (*bytes)
+ .clone()
+ .try_into()
+ .expect("nla does not match ipv6 address length");
+ let ip = IpAddr::from(Ipv6Addr::from(octets));
+
+ Some(ip)
+ }
+ _ => None,
+ }
+ } else {
+ None
+ }))
+ }))
+}
diff --git a/src/blocking.rs b/src/blocking.rs
index 8483452..f66a096 100644
--- a/src/blocking.rs
+++ b/src/blocking.rs
@@ -33,12 +33,19 @@ pub mod addr {
use std::net::IpAddr;
+ use futures::TryStreamExt;
+
blockify!(flush, addr::flush, link: String);
blockify!(flush4, addr::flush4, link: String);
blockify!(flush6, addr::flush6, link: String);
blockify!(flush6_global, addr::flush6_global);
blockify!(add, addr::add, link: String, addr: IpAddr, prefix_len: u8);
blockify!(add_link_local, addr::add_link_local, link: String, addr: IpAddr, prefix_len: u8);
+
+ pub fn get(link: String) -> crate::Result<Vec<IpAddr>> {
+ tokio::runtime::Runtime::new()?
+ .block_on(async { addr::get(link).await?.try_collect().await })
+ }
}
#[cfg(feature = "status")]