Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions src/linux/async_route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::linux::{
};
use crate::AsyncRoute;
use crate::{Route, RouteChange};
use netlink_packet_route::AddressFamily;
use std::collections::VecDeque;
use std::io;
/// AsyncRouteListener for asynchronously receiving route change events.
Expand Down Expand Up @@ -57,14 +58,13 @@ impl AsyncRouteManager {
pub fn listener() -> io::Result<AsyncRouteListener> {
AsyncRouteListener::new()
}
/// Asynchronously lists all current routes.
pub async fn list(&mut self) -> io::Result<Vec<Route>> {
let req = list_route_req();
let mut socket = AsyncRoute::new(RouteSocket::new()?)?;
socket.write_with(|s| s.send(&req)).await?;

/// Asynchronously lists routes for a specific address family.
async fn list_family(socket: &mut AsyncRoute<RouteSocket>, family: AddressFamily) -> io::Result<Vec<RouteChange>> {
let mut buf = vec![0; 4096];
let mut list = Vec::new();

let req = list_route_req(family);
socket.write_with(|s| s.send(&req)).await?;
loop {
let len = socket.read_with(|s| s.recv(&mut buf)).await?;
let rs = deserialize_res(
Expand All @@ -77,6 +77,26 @@ impl AsyncRouteManager {
break;
}
}
Ok(list)
}

/// Asynchronously lists all current routes.
pub async fn list(&mut self) -> io::Result<Vec<Route>> {
let mut socket = AsyncRoute::new(RouteSocket::new()?)?;

// Query IPv4 routes
let v4_result = Self::list_family(&mut socket, AddressFamily::Inet).await;

// Query IPv6 routes
let v6_result = Self::list_family(&mut socket, AddressFamily::Inet6).await;

// Only fail if both queries failed. If at least one succeeded, return partial results.
let list = match (v4_result, v6_result) {
(Ok(v4), Ok(v6)) => [v4, v6].concat(),
(Ok(v4), Err(_)) => v4, // IPv4 succeeded
(Err(_), Ok(v6)) => v6, // IPv6 succeeded
(Err(e), Err(_)) => return Err(e), // Both failed, return first error
};
Ok(convert_add_route(list))
}
/// Asynchronously adds a new route.
Expand Down
37 changes: 30 additions & 7 deletions src/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,12 @@ impl RouteManager {
RouteListener::new()
}

/// Lists all current routes.
pub fn list(&mut self) -> io::Result<Vec<Route>> {
let req = list_route_req();
let socket = RouteSocket::new()?;
socket.send(&req)?;
/// Lists routes for a specific address family.
fn list_family(socket: &RouteSocket, family: AddressFamily) -> io::Result<Vec<RouteChange>> {
let mut buf = vec![0; 4096];
let mut list = Vec::new();
let req = list_route_req(family);
socket.send(&req)?;
loop {
let len = socket.recv(&mut buf)?;
let rs = deserialize_res(
Expand All @@ -158,6 +157,26 @@ impl RouteManager {
break;
}
}
Ok(list)
}

/// Lists all current routes.
pub fn list(&mut self) -> io::Result<Vec<Route>> {
let socket = RouteSocket::new()?;

// Query IPv4 routes
let v4_result = Self::list_family(&socket, AddressFamily::Inet);

// Query IPv6 routes
let v6_result = Self::list_family(&socket, AddressFamily::Inet6);

// Only fail if both queries failed. If at least one succeeded, return partial results.
let list = match (v4_result, v6_result) {
(Ok(v4), Ok(v6)) => [v4, v6].concat(),
(Ok(v4), Err(_)) => v4, // IPv4 succeeded
(Err(_), Ok(v6)) => v6, // IPv6 succeeded
(Err(e), Err(_)) => return Err(e), // Both failed, return first error
};
Ok(convert_add_route(list))
}
/// Adds a new route.
Expand Down Expand Up @@ -365,12 +384,16 @@ impl TryFrom<&Route> for RouteMessage {
}
}

pub(crate) fn list_route_req() -> Vec<u8> {
pub(crate) fn list_route_req(family: AddressFamily) -> Vec<u8> {
let mut nl_hdr = NetlinkHeader::default();
nl_hdr.flags = NLM_F_REQUEST | NLM_F_DUMP;

let mut route_msg = RouteMessage::default();
route_msg.header.address_family = family;

let mut packet = NetlinkMessage::new(
nl_hdr,
NetlinkPayload::from(RouteNetlinkMessage::GetRoute(RouteMessage::default())),
NetlinkPayload::from(RouteNetlinkMessage::GetRoute(route_msg)),
);

packet.finalize();
Expand Down