Skip to content

Commit e2bcfc8

Browse files
committed
Get default route example
This example was created in response to [issue #63](#63)
1 parent 6896bae commit e2bcfc8

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

examples/get_route_default.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
//! To find the default route for a given ip address family (i.e., IPv4 or IPv6),
4+
//!
5+
//! 1. pick a routing table (in Linux this is almost always table `254` unless
6+
//! you are using VRFs or something)
7+
//! 1. find all routes in the routing table with
8+
//! `.header.destination_prefix_length == 0` (that is, routes which are
9+
//! either `0.0.0.0/0` for IPv4 or `::/0` for IPv6)
10+
//! 2. take the route with the _lowest_ priority among those.
11+
12+
use std::collections::BTreeMap;
13+
14+
use futures::stream::TryStreamExt;
15+
use netlink_packet_route::route::{RouteAttribute, RouteMessage, RouteType};
16+
17+
use rtnetlink::{new_connection, IpVersion};
18+
19+
type RouteTableId = u8;
20+
type RoutePriority = Option<u32>;
21+
22+
#[tokio::main]
23+
async fn main() -> Result<(), ()> {
24+
let (connection, handle, _) = new_connection().unwrap();
25+
tokio::spawn(connection);
26+
27+
let mut default_routes: BTreeMap<
28+
RouteTableId,
29+
BTreeMap<RoutePriority, RouteMessage>,
30+
> = BTreeMap::new();
31+
32+
// Change to `IpVersion::V6` and this will work for the IPv6 routing tables
33+
let mut all_routes = handle.clone().route().get(IpVersion::V4).execute();
34+
35+
while let Ok(Some(route)) = all_routes.try_next().await {
36+
if route.header.destination_prefix_length != 0 {
37+
continue;
38+
}
39+
if route.header.kind != RouteType::Unicast {
40+
continue;
41+
}
42+
let prio = route.attributes.iter().find_map(|attr| match attr {
43+
RouteAttribute::Priority(prio) => Some(*prio),
44+
_ => None,
45+
});
46+
if let Some(prio_map) = default_routes.get_mut(&route.header.table) {
47+
prio_map.insert(prio, route);
48+
} else {
49+
let mut prio_map = BTreeMap::new();
50+
let table_id = route.header.table;
51+
prio_map.insert(prio, route);
52+
default_routes.insert(table_id, prio_map);
53+
}
54+
}
55+
56+
for (table, prio_map) in default_routes.iter() {
57+
println!("Default routes:");
58+
println!("Table: {table}");
59+
for (_, route) in prio_map.iter() {
60+
println!("\t{route:?}");
61+
}
62+
}
63+
64+
Ok(())
65+
}

0 commit comments

Comments
 (0)