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