From 2c20dc2932696cb87ea7e6eb5327b7dccf0e9b1b Mon Sep 17 00:00:00 2001 From: HimbeerserverDE Date: Fri, 17 Nov 2023 18:07:39 +0100 Subject: add function to get all ip addresses of an interface, replacing the linkaddrs crate --- src/addr.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/blocking.rs | 7 +++++++ 2 files changed, 61 insertions(+), 3 deletions(-) (limited to 'src') 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> { + 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::() + .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> { + tokio::runtime::Runtime::new()? + .block_on(async { addr::get(link).await?.try_collect().await }) + } } #[cfg(feature = "status")] -- cgit v1.2.3