netlink_packet_route/rtnl/route/
message.rs1use crate::{
4 nlas::route::Nla,
5 traits::{Emitable, Parseable},
6 DecodeError,
7 RouteHeader,
8 RouteMessageBuffer,
9};
10use anyhow::Context;
11use std::net::IpAddr;
12
13#[derive(Debug, PartialEq, Eq, Clone, Default)]
14pub struct RouteMessage {
15 pub header: RouteHeader,
16 pub nlas: Vec<Nla>,
17}
18
19impl Emitable for RouteMessage {
20 fn buffer_len(&self) -> usize {
21 self.header.buffer_len() + self.nlas.as_slice().buffer_len()
22 }
23
24 fn emit(&self, buffer: &mut [u8]) {
25 self.header.emit(buffer);
26 self.nlas
27 .as_slice()
28 .emit(&mut buffer[self.header.buffer_len()..]);
29 }
30}
31
32impl<'a, T: AsRef<[u8]> + 'a> Parseable<RouteMessageBuffer<&'a T>> for RouteMessage {
33 fn parse(buf: &RouteMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
34 Ok(RouteMessage {
35 header: RouteHeader::parse(buf).context("failed to parse route message header")?,
36 nlas: Vec::<Nla>::parse(buf).context("failed to parse route message NLAs")?,
37 })
38 }
39}
40
41impl<'a, T: AsRef<[u8]> + 'a> Parseable<RouteMessageBuffer<&'a T>> for Vec<Nla> {
42 fn parse(buf: &RouteMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
43 let mut nlas = vec![];
44 for nla_buf in buf.nlas() {
45 nlas.push(Nla::parse(&nla_buf?)?);
46 }
47 Ok(nlas)
48 }
49}
50
51fn octets_to_addr(octets: &[u8]) -> Result<IpAddr, DecodeError> {
52 if octets.len() == 4 {
53 let mut ary: [u8; 4] = Default::default();
54 ary.copy_from_slice(octets);
55 Ok(IpAddr::from(ary))
56 } else if octets.len() == 16 {
57 let mut ary: [u8; 16] = Default::default();
58 ary.copy_from_slice(octets);
59 Ok(IpAddr::from(ary))
60 } else {
61 Err(DecodeError::from("Cannot decode IP address"))
62 }
63}
64
65impl RouteMessage {
66 pub fn input_interface(&self) -> Option<u32> {
68 self.nlas.iter().find_map(|nla| {
69 if let Nla::Iif(v) = nla {
70 Some(*v)
71 } else {
72 None
73 }
74 })
75 }
76
77 pub fn output_interface(&self) -> Option<u32> {
79 self.nlas.iter().find_map(|nla| {
80 if let Nla::Oif(v) = nla {
81 Some(*v)
82 } else {
83 None
84 }
85 })
86 }
87
88 pub fn source_prefix(&self) -> Option<(IpAddr, u8)> {
90 self.nlas.iter().find_map(|nla| {
91 if let Nla::Source(v) = nla {
92 octets_to_addr(v)
93 .ok()
94 .map(|addr| (addr, self.header.source_prefix_length))
95 } else {
96 None
97 }
98 })
99 }
100
101 pub fn destination_prefix(&self) -> Option<(IpAddr, u8)> {
103 self.nlas.iter().find_map(|nla| {
104 if let Nla::Destination(v) = nla {
105 octets_to_addr(v)
106 .ok()
107 .map(|addr| (addr, self.header.destination_prefix_length))
108 } else {
109 None
110 }
111 })
112 }
113
114 pub fn gateway(&self) -> Option<IpAddr> {
116 self.nlas.iter().find_map(|nla| {
117 if let Nla::Gateway(v) = nla {
118 octets_to_addr(v).ok()
119 } else {
120 None
121 }
122 })
123 }
124}