Skip to content

Commit c995a06

Browse files
committed
Insert unreachable route for the received delegated prefix
Signed-off-by: Guvenc Gulce <guevenc.guelce@sap.com>
1 parent 21a57d9 commit c995a06

File tree

3 files changed

+89
-58
lines changed

3 files changed

+89
-58
lines changed

src/network/dhcpv6.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,7 @@ pub async fn add_ipv6_route(
936936
prefix_length: u8,
937937
gateway: Option<Ipv6Addr>,
938938
metric: u32,
939+
route_type: RouteType,
939940
) -> Result<(), Error> {
940941
let mut links = handle
941942
.link()
@@ -950,24 +951,25 @@ pub async fn add_ipv6_route(
950951
};
951952

952953
let mut route_add_request = handle.route().add();
953-
954954
let route_msg = route_add_request.message_mut();
955955

956956
route_msg.header.address_family = AddressFamily::Inet6;
957957
route_msg.header.scope = RouteScope::Universe;
958958
route_msg.header.protocol = RouteProtocol::Static;
959-
route_msg.header.kind = RouteType::Unicast;
959+
route_msg.header.kind = route_type;
960960
route_msg.header.destination_prefix_length = prefix_length;
961961
route_msg.header.table = RouteHeader::RT_TABLE_MAIN;
962962

963963
route_msg
964964
.attributes
965965
.push(RouteAttribute::Destination(RouteAddress::from(destination)));
966966

967-
if let Some(gw) = gateway {
968-
route_msg
969-
.attributes
970-
.push(RouteAttribute::Gateway(RouteAddress::from(gw)));
967+
if route_type == RouteType::Unicast {
968+
if let Some(gw) = gateway {
969+
route_msg
970+
.attributes
971+
.push(RouteAttribute::Gateway(RouteAddress::from(gw)));
972+
}
971973
}
972974

973975
route_msg

src/network/mod.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use log::{debug, error, info};
2+
use netlink_packet_route::route::RouteType;
23
use rtnetlink::new_connection;
34
use std::collections::HashMap;
45
use std::net::Ipv6Addr;
@@ -17,7 +18,7 @@ use crate::network::dhcpv6::{
1718
};
1819
use radv::start_radv_server;
1920
pub use utils::_configure_sriov;
20-
pub use utils::configure_network_devices;
21+
pub use utils::{configure_network_devices, INTERFACE_NAME};
2122

2223
#[derive(Debug)]
2324
pub enum Error {
@@ -125,32 +126,31 @@ impl Manager {
125126
})
126127
};
127128

128-
let mut instances = self.instances.lock().unwrap();
129-
instances.insert(
130-
id,
131-
Handles {
132-
radv_handle: Arc::new(radv_handle),
133-
dhcpv6_handle: Arc::new(dhcpv6_handle),
134-
},
135-
);
129+
{
130+
let mut instances = self.instances.lock().unwrap();
131+
instances.insert(
132+
id,
133+
Handles {
134+
radv_handle: Arc::new(radv_handle),
135+
dhcpv6_handle: Arc::new(dhcpv6_handle),
136+
},
137+
);
138+
}
136139

137140
let (connection, handle, _) = new_connection().map_err(|_| Error::Failed)?;
138141
spawn(connection);
139142

140-
spawn(async move {
141-
if let Err(e) = add_ipv6_route(
142-
&handle,
143-
&interface_name,
144-
adjusted_base_ip,
145-
new_prefix_length,
146-
None,
147-
1024,
148-
)
149-
.await
150-
{
151-
error!("Failed to add ipv6 route: {}", e);
152-
}
153-
});
143+
add_ipv6_route(
144+
&handle,
145+
&interface_name,
146+
adjusted_base_ip,
147+
new_prefix_length,
148+
None,
149+
1024,
150+
RouteType::Unicast,
151+
)
152+
.await
153+
.map_err(|_| Error::Failed)?;
154154

155155
Ok(())
156156
}

src/network/utils.rs

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::io::Write;
44

55
use crate::network::dhcpv6::*;
66
use futures::stream::TryStreamExt;
7-
use log::{debug, info, warn};
7+
use log::{debug, error, info, warn};
88
use rtnetlink::{new_connection, Handle, IpVersion};
99
use std::net::Ipv6Addr;
1010
use tokio::fs::{read_link, OpenOptions};
@@ -22,9 +22,9 @@ use pnet::packet::udp::UdpPacket;
2222
use pnet::packet::Packet;
2323

2424
use netlink_packet_route::neighbour::*;
25-
use netlink_packet_route::route::{RouteAddress, RouteAttribute};
25+
use netlink_packet_route::route::{RouteAddress, RouteAttribute, RouteType};
2626

27-
const INTERFACE_NAME: &str = "eth0";
27+
pub const INTERFACE_NAME: &str = "eth0";
2828

2929
pub async fn configure_network_devices() -> Result<Option<(Ipv6Addr, u8)>, String> {
3030
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<Option<(Ipv6Addr, u8)>, Strin
124124
delegated_prefix, prefix_length
125125
);
126126
delegated_prefix_option = Some((delegated_prefix, prefix_length));
127+
if let Err(e) = add_ipv6_route(
128+
&handle,
129+
INTERFACE_NAME,
130+
delegated_prefix,
131+
prefix_length,
132+
None,
133+
1024,
134+
RouteType::Unreachable,
135+
)
136+
.await
137+
{
138+
error!("Failed to add unreachable IPv6 route: {}", e);
139+
}
127140
} else {
128141
info!("No prefix delegation received.");
129142
}
@@ -227,36 +240,35 @@ async fn _print_ipv6_routes(
227240
}
228241
}
229242

230-
RouteAttribute::Gateway(gw) => {
231-
match gw {
232-
RouteAddress::Inet6(addr) => {
233-
gateway = Some(addr.to_string());
234-
debug!("Parsed IPv6 Gateway: {}", addr);
235-
}
236-
RouteAddress::Other(v) => {
237-
// Some other form of gateway, handle if needed
238-
if v.is_empty() {
239-
debug!("Parsed Empty Gateway");
240-
} else {
241-
let hex_str = v
242-
.iter()
243-
.map(|b| format!("{:02x}", b))
244-
.collect::<Vec<String>>()
245-
.join(":");
246-
gateway = Some(format!("unknown({})", hex_str));
247-
debug!("Parsed Unknown Gateway: {}", hex_str);
248-
}
249-
}
250-
_ => {
251-
debug!("Unhandled Gateway variant");
243+
RouteAttribute::Gateway(gw) => match gw {
244+
RouteAddress::Inet6(addr) => {
245+
gateway = Some(addr.to_string());
246+
debug!("Parsed IPv6 Gateway: {}", addr);
247+
}
248+
RouteAddress::Other(v) => {
249+
if v.is_empty() {
250+
debug!("Parsed Empty Gateway");
251+
} else {
252+
let hex_str = v
253+
.iter()
254+
.map(|b| format!("{:02x}", b))
255+
.collect::<Vec<String>>()
256+
.join(":");
257+
gateway = Some(format!("unknown({})", hex_str));
258+
debug!("Parsed Unknown Gateway: {}", hex_str);
252259
}
253260
}
254-
}
261+
_ => {
262+
debug!("Unhandled Gateway variant");
263+
}
264+
},
255265
_ => {}
256266
}
257267
}
258268

259-
if oif != Some(iface_index) {
269+
let is_unreachable = route_msg.header.kind == RouteType::Unreachable;
270+
271+
if !is_unreachable && oif != Some(iface_index) {
260272
debug!(
261273
"Skipping route not associated with interface '{}'",
262274
interface_name
@@ -269,12 +281,29 @@ async fn _print_ipv6_routes(
269281
debug!("Default route detected (no destination attribute)");
270282
}
271283

272-
let dest_str = destination.unwrap_or_else(|| "unknown".to_string());
284+
let dest_str = destination.unwrap_or_else(|| {
285+
if is_unreachable {
286+
"unreachable".to_string()
287+
} else {
288+
"unknown".to_string()
289+
}
290+
});
291+
273292
let mut route_str = dest_str.to_string();
293+
274294
if let Some(gw) = gateway {
275295
route_str.push_str(&format!(" via {}", gw));
276296
}
277-
route_str.push_str(&format!(" dev {}", interface_name));
297+
298+
if oif.is_some() {
299+
if is_unreachable {
300+
route_str.push_str(&format!(" dev {} [unreachable]", interface_name));
301+
} else {
302+
route_str.push_str(&format!(" dev {}", interface_name));
303+
}
304+
} else if is_unreachable {
305+
route_str.push_str(" [unreachable]");
306+
}
278307

279308
info!("- {}", route_str);
280309
}

0 commit comments

Comments
 (0)