diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-11-17 18:07:39 +0100 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-11-17 18:07:39 +0100 |
commit | 2c20dc2932696cb87ea7e6eb5327b7dccf0e9b1b (patch) | |
tree | 1d6a940d19d8e73aa86a63445d0caad9689ae509 | |
parent | e90ee46c1aeb83973da25e9b104c896baddc475d (diff) |
add function to get all ip addresses of an interface, replacing the linkaddrs crate0.3.0
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/addr.rs | 57 | ||||
-rw-r--r-- | src/blocking.rs | 7 |
3 files changed, 62 insertions, 4 deletions
@@ -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")] |