|
| 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