netlink_packet_route/neighbour_discovery_user_option/
message.rs
1use netlink_packet_utils::traits::{Emitable, Parseable};
4use std::convert::TryFrom as _;
5
6use super::buffer::{
7 NeighbourDiscoveryUserOptionMessageBuffer, NEIGHBOUR_DISCOVERY_USER_OPTION_HEADER_LEN,
8};
9use super::header::NeighbourDiscoveryUserOptionHeader;
10use super::nla::Nla;
11use super::NeighbourDiscoveryUserOptionError;
12
13#[derive(Debug, PartialEq, Eq, Clone)]
14#[non_exhaustive]
15pub struct NeighbourDiscoveryUserOptionMessage {
16 pub header: NeighbourDiscoveryUserOptionHeader,
18
19 pub option_body: Vec<u8>,
21
22 pub attributes: Vec<Nla>,
23}
24
25impl NeighbourDiscoveryUserOptionMessage {
26 pub fn new(
27 header: NeighbourDiscoveryUserOptionHeader,
28 option_body: Vec<u8>,
29 attributes: Vec<Nla>,
30 ) -> Self {
31 Self { header, option_body, attributes }
32 }
33}
34
35impl Emitable for NeighbourDiscoveryUserOptionMessage {
36 fn buffer_len(&self) -> usize {
37 NEIGHBOUR_DISCOVERY_USER_OPTION_HEADER_LEN
38 + self.option_body.len()
39 + self.attributes.as_slice().buffer_len()
40 }
41
42 fn emit(&self, buffer: &mut [u8]) {
43 let Self {
44 header: NeighbourDiscoveryUserOptionHeader { interface_index, icmp_type },
45 option_body,
46 attributes,
47 } = self;
48
49 let mut packet = NeighbourDiscoveryUserOptionMessageBuffer::new(buffer);
50
51 packet.set_address_family(icmp_type.family().into());
52
53 let payload = packet.payload_mut();
54 payload[..option_body.len()].copy_from_slice(&option_body[..]);
55 attributes.as_slice().emit(&mut payload[option_body.len()..]);
56
57 packet.set_options_length(
58 u16::try_from(option_body.len())
59 .expect("neighbor discovery options length doesn't fit in u16"),
60 );
61 packet.set_interface_index(*interface_index);
62
63 let (icmp_type, icmp_code) = icmp_type.into_type_and_code();
64 packet.set_icmp_type(icmp_type);
65 packet.set_icmp_code(icmp_code);
66 }
67}
68
69impl<'a, T: AsRef<[u8]> + 'a> Parseable<NeighbourDiscoveryUserOptionMessageBuffer<&'a T>>
70 for NeighbourDiscoveryUserOptionMessage
71{
72 type Error = NeighbourDiscoveryUserOptionError;
73
74 fn parse(
75 buf: &NeighbourDiscoveryUserOptionMessageBuffer<&'a T>,
76 ) -> Result<Self, NeighbourDiscoveryUserOptionError> {
77 let header = NeighbourDiscoveryUserOptionHeader::parse(buf)
78 .map_err(NeighbourDiscoveryUserOptionError::InvalidHeader)?;
79
80 let mut nlas = Vec::new();
81 for nla_buf in buf.nlas() {
82 nlas.push(
83 Nla::parse(&nla_buf.map_err(NeighbourDiscoveryUserOptionError::InvalidNla)?)
84 .map_err(NeighbourDiscoveryUserOptionError::InvalidNla)?,
85 );
86 }
87
88 Ok(NeighbourDiscoveryUserOptionMessage {
89 header,
90 option_body: buf.option_body().to_vec(),
91 attributes: nlas,
92 })
93 }
94}