network_device/
routing.rs1use crate::IpPrefix;
4use std::fmt;
5use std::net::IpAddr;
6
7#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub struct StaticRoute {
10 destination: IpPrefix,
12 next_hop: IpAddr,
14}
15
16impl StaticRoute {
17 pub fn new(destination: IpPrefix, next_hop: IpAddr) -> Result<Self, StaticRouteError> {
19 if destination.address().is_ipv4() != next_hop.is_ipv4() {
20 return Err(StaticRouteError::AddressFamilyMismatch);
21 }
22 Ok(Self {
23 destination,
24 next_hop,
25 })
26 }
27
28 pub const fn destination(self) -> IpPrefix {
30 self.destination
31 }
32
33 pub const fn next_hop(self) -> IpAddr {
35 self.next_hop
36 }
37}
38
39#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41pub enum StaticRouteError {
42 AddressFamilyMismatch,
44}
45
46impl fmt::Display for StaticRouteError {
47 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48 formatter
49 .write_str("static-route destination and next hop must use the same address family")
50 }
51}
52
53impl std::error::Error for StaticRouteError {}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use std::net::{Ipv4Addr, Ipv6Addr};
59
60 #[test]
61 fn route_rejects_a_next_hop_from_another_address_family() {
62 let destination = "192.0.2.0/24".parse::<IpPrefix>().unwrap();
63 assert_eq!(
64 StaticRoute::new(destination, IpAddr::V6(Ipv6Addr::LOCALHOST)),
65 Err(StaticRouteError::AddressFamilyMismatch)
66 );
67 assert!(StaticRoute::new(destination, IpAddr::V4(Ipv4Addr::LOCALHOST)).is_ok());
68 }
69}