diff --git a/src/network/dhcpv6.rs b/src/network/dhcpv6.rs index 488a24b..d0c53d2 100644 --- a/src/network/dhcpv6.rs +++ b/src/network/dhcpv6.rs @@ -936,6 +936,7 @@ pub async fn add_ipv6_route( prefix_length: u8, gateway: Option, metric: u32, + route_type: RouteType, ) -> Result<(), Error> { let mut links = handle .link() @@ -950,13 +951,12 @@ pub async fn add_ipv6_route( }; let mut route_add_request = handle.route().add(); - let route_msg = route_add_request.message_mut(); route_msg.header.address_family = AddressFamily::Inet6; route_msg.header.scope = RouteScope::Universe; route_msg.header.protocol = RouteProtocol::Static; - route_msg.header.kind = RouteType::Unicast; + route_msg.header.kind = route_type; route_msg.header.destination_prefix_length = prefix_length; route_msg.header.table = RouteHeader::RT_TABLE_MAIN; @@ -964,10 +964,12 @@ pub async fn add_ipv6_route( .attributes .push(RouteAttribute::Destination(RouteAddress::from(destination))); - if let Some(gw) = gateway { - route_msg - .attributes - .push(RouteAttribute::Gateway(RouteAddress::from(gw))); + if route_type == RouteType::Unicast { + if let Some(gw) = gateway { + route_msg + .attributes + .push(RouteAttribute::Gateway(RouteAddress::from(gw))); + } } route_msg diff --git a/src/network/mod.rs b/src/network/mod.rs index 642ba74..e4f9531 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -1,4 +1,5 @@ use log::{debug, error, info}; +use netlink_packet_route::route::RouteType; use rtnetlink::new_connection; use std::collections::HashMap; use std::net::Ipv6Addr; @@ -17,7 +18,7 @@ use crate::network::dhcpv6::{ }; use radv::start_radv_server; pub use utils::_configure_sriov; -pub use utils::configure_network_devices; +pub use utils::{configure_network_devices, INTERFACE_NAME}; #[derive(Debug)] pub enum Error { @@ -125,32 +126,31 @@ impl Manager { }) }; - let mut instances = self.instances.lock().unwrap(); - instances.insert( - id, - Handles { - radv_handle: Arc::new(radv_handle), - dhcpv6_handle: Arc::new(dhcpv6_handle), - }, - ); + { + let mut instances = self.instances.lock().unwrap(); + instances.insert( + id, + Handles { + radv_handle: Arc::new(radv_handle), + dhcpv6_handle: Arc::new(dhcpv6_handle), + }, + ); + } let (connection, handle, _) = new_connection().map_err(|_| Error::Failed)?; spawn(connection); - spawn(async move { - if let Err(e) = add_ipv6_route( - &handle, - &interface_name, - adjusted_base_ip, - new_prefix_length, - None, - 1024, - ) - .await - { - error!("Failed to add ipv6 route: {}", e); - } - }); + add_ipv6_route( + &handle, + &interface_name, + adjusted_base_ip, + new_prefix_length, + None, + 1024, + RouteType::Unicast, + ) + .await + .map_err(|_| Error::Failed)?; Ok(()) } diff --git a/src/network/utils.rs b/src/network/utils.rs index ceb8e81..95c2e64 100644 --- a/src/network/utils.rs +++ b/src/network/utils.rs @@ -4,7 +4,7 @@ use std::io::Write; use crate::network::dhcpv6::*; use futures::stream::TryStreamExt; -use log::{debug, info, warn}; +use log::{debug, error, info, warn}; use rtnetlink::{new_connection, Handle, IpVersion}; use std::net::Ipv6Addr; use tokio::fs::{read_link, OpenOptions}; @@ -22,9 +22,9 @@ use pnet::packet::udp::UdpPacket; use pnet::packet::Packet; use netlink_packet_route::neighbour::*; -use netlink_packet_route::route::{RouteAddress, RouteAttribute}; +use netlink_packet_route::route::{RouteAddress, RouteAttribute, RouteType}; -const INTERFACE_NAME: &str = "eth0"; +pub const INTERFACE_NAME: &str = "eth0"; pub async fn configure_network_devices() -> Result, String> { let ignore_ra_flag = true; // Till the RA has the correct flags (O or M), ignore the flag @@ -124,6 +124,19 @@ pub async fn configure_network_devices() -> Result, Strin delegated_prefix, prefix_length ); delegated_prefix_option = Some((delegated_prefix, prefix_length)); + if let Err(e) = add_ipv6_route( + &handle, + INTERFACE_NAME, + delegated_prefix, + prefix_length, + None, + 1024, + RouteType::Unreachable, + ) + .await + { + error!("Failed to add unreachable IPv6 route: {}", e); + } } else { info!("No prefix delegation received."); } @@ -227,36 +240,35 @@ async fn _print_ipv6_routes( } } - RouteAttribute::Gateway(gw) => { - match gw { - RouteAddress::Inet6(addr) => { - gateway = Some(addr.to_string()); - debug!("Parsed IPv6 Gateway: {}", addr); - } - RouteAddress::Other(v) => { - // Some other form of gateway, handle if needed - if v.is_empty() { - debug!("Parsed Empty Gateway"); - } else { - let hex_str = v - .iter() - .map(|b| format!("{:02x}", b)) - .collect::>() - .join(":"); - gateway = Some(format!("unknown({})", hex_str)); - debug!("Parsed Unknown Gateway: {}", hex_str); - } - } - _ => { - debug!("Unhandled Gateway variant"); + RouteAttribute::Gateway(gw) => match gw { + RouteAddress::Inet6(addr) => { + gateway = Some(addr.to_string()); + debug!("Parsed IPv6 Gateway: {}", addr); + } + RouteAddress::Other(v) => { + if v.is_empty() { + debug!("Parsed Empty Gateway"); + } else { + let hex_str = v + .iter() + .map(|b| format!("{:02x}", b)) + .collect::>() + .join(":"); + gateway = Some(format!("unknown({})", hex_str)); + debug!("Parsed Unknown Gateway: {}", hex_str); } } - } + _ => { + debug!("Unhandled Gateway variant"); + } + }, _ => {} } } - if oif != Some(iface_index) { + let is_unreachable = route_msg.header.kind == RouteType::Unreachable; + + if !is_unreachable && oif != Some(iface_index) { debug!( "Skipping route not associated with interface '{}'", interface_name @@ -269,12 +281,29 @@ async fn _print_ipv6_routes( debug!("Default route detected (no destination attribute)"); } - let dest_str = destination.unwrap_or_else(|| "unknown".to_string()); + let dest_str = destination.unwrap_or_else(|| { + if is_unreachable { + "unreachable".to_string() + } else { + "unknown".to_string() + } + }); + let mut route_str = dest_str.to_string(); + if let Some(gw) = gateway { route_str.push_str(&format!(" via {}", gw)); } - route_str.push_str(&format!(" dev {}", interface_name)); + + if oif.is_some() { + if is_unreachable { + route_str.push_str(&format!(" dev {} [unreachable]", interface_name)); + } else { + route_str.push_str(&format!(" dev {}", interface_name)); + } + } else if is_unreachable { + route_str.push_str(" [unreachable]"); + } info!("- {}", route_str); }