netlink_packet_route/neighbour_discovery_user_option/
nla.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4
5use netlink_packet_utils::nla::{self, DefaultNla, NlaBuffer};
6use netlink_packet_utils::traits::Parseable;
7use netlink_packet_utils::DecodeError;
8
9use super::constants;
10
11/// Neighbor discovery options, which may be included as attributes for
12/// `RTM_NEWNDUSEROPT` messages.
13#[derive(Debug, PartialEq, Eq, Clone)]
14#[non_exhaustive]
15pub enum Nla {
16    /// The source link-layer address, as defined by RFC 2461 section 4.6.1.
17    SourceLinkLocalAddress(Vec<u8>),
18    Other(DefaultNla),
19}
20
21impl nla::Nla for Nla {
22    fn value_len(&self) -> usize {
23        use self::Nla::*;
24        match *self {
25            SourceLinkLocalAddress(ref bytes) => bytes.len(),
26            Other(ref attr) => attr.value_len(),
27        }
28    }
29
30    fn emit_value(&self, buffer: &mut [u8]) {
31        use self::Nla::*;
32        match *self {
33            SourceLinkLocalAddress(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
34            Other(ref attr) => attr.emit_value(buffer),
35        }
36    }
37
38    fn kind(&self) -> u16 {
39        use self::Nla::*;
40        use constants::*;
41        match *self {
42            SourceLinkLocalAddress(_) => ND_OPT_SOURCE_LL_ADDR,
43            Other(ref attr) => attr.kind(),
44        }
45    }
46}
47
48impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nla {
49    type Error = DecodeError;
50
51    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
52        use self::Nla::*;
53
54        let payload = buf.value();
55        Ok(match buf.kind() {
56            constants::ND_OPT_SOURCE_LL_ADDR => SourceLinkLocalAddress(payload.to_vec()),
57            _ => Other(DefaultNla::parse(buf).context("invalid NLA (unknown kind)")?),
58        })
59    }
60}