netlink_packet_route/route/
via.rs1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4
5use netlink_packet_core::{DecodeError, Emitable, Parseable};
6
7use crate::{
8 ip::{parse_ipv4_addr, parse_ipv6_addr, IPV4_ADDR_LEN, IPV6_ADDR_LEN},
9 AddressFamily,
10};
11
12#[derive(Debug, PartialEq, Eq, Clone)]
13#[non_exhaustive]
14pub enum RouteVia {
19 Inet(Ipv4Addr),
20 Inet6(Ipv6Addr),
21 #[cfg(any(target_os = "linux", target_os = "fuchsia"))]
22 Packet(Vec<u8>),
23 Other((AddressFamily, Vec<u8>)),
24}
25
26const RTVIA_LEN: usize = 2;
27
28buffer!(RouteViaBuffer(RTVIA_LEN) {
29 address_family: (u16, 0..2),
30 address: (slice, RTVIA_LEN..),
31});
32
33impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<RouteViaBuffer<&'a T>>
34 for RouteVia
35{
36 fn parse(buf: &RouteViaBuffer<&'a T>) -> Result<Self, DecodeError> {
37 let address_family: AddressFamily = (buf.address_family() as u8).into();
38 Ok(match address_family {
39 AddressFamily::Inet => Self::Inet(parse_ipv4_addr(buf.address())?),
40 AddressFamily::Inet6 => {
41 Self::Inet6(parse_ipv6_addr(buf.address())?)
42 }
43 #[cfg(any(target_os = "linux", target_os = "fuchsia"))]
44 AddressFamily::Packet => Self::Packet(buf.address().to_vec()),
45 _ => Self::Other((address_family, buf.address().to_vec())),
46 })
47 }
48}
49
50impl Emitable for RouteVia {
51 fn buffer_len(&self) -> usize {
52 match self {
53 Self::Inet(_) => IPV4_ADDR_LEN + 2,
54 Self::Inet6(_) => IPV6_ADDR_LEN + 2,
55 #[cfg(any(target_os = "linux", target_os = "fuchsia"))]
56 Self::Packet(a) => a.len() + 2,
57 Self::Other((_, a)) => a.len() + 2,
58 }
59 }
60
61 fn emit(&self, buffer: &mut [u8]) {
62 let mut buffer = RouteViaBuffer::new(buffer);
63 let (address_family, addr) = match self {
64 Self::Inet(ip) => (AddressFamily::Inet, ip.octets().to_vec()),
65 Self::Inet6(ip) => (AddressFamily::Inet6, ip.octets().to_vec()),
66 #[cfg(any(target_os = "linux", target_os = "fuchsia"))]
67 Self::Packet(a) => (AddressFamily::Packet, a.to_vec()),
68 Self::Other((f, a)) => (*f, a.to_vec()),
69 };
70 buffer.set_address_family(u8::from(address_family).into());
71 buffer.address_mut().copy_from_slice(addr.as_slice());
72 }
73}
74
75impl From<Ipv4Addr> for RouteVia {
76 fn from(v: Ipv4Addr) -> Self {
77 Self::Inet(v)
78 }
79}
80
81impl From<Ipv6Addr> for RouteVia {
82 fn from(v: Ipv6Addr) -> Self {
83 Self::Inet6(v)
84 }
85}
86
87impl From<IpAddr> for RouteVia {
88 fn from(ip: IpAddr) -> Self {
89 match ip {
90 IpAddr::V4(ipv4) => Self::Inet(ipv4),
91 IpAddr::V6(ipv6) => Self::Inet6(ipv6),
92 }
93 }
94}