netlink_packet_route/rtnl/link/nlas/inet6/
mod.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use byteorder::{ByteOrder, NativeEndian};
5
6use crate::constants::*;
7
8use netlink_packet_utils::{
9    nla::{DefaultNla, Nla, NlaBuffer},
10    parsers::{parse_ipv6, parse_u32, parse_u8},
11    traits::Parseable,
12    DecodeError,
13};
14
15mod cache;
16pub use self::cache::*;
17mod dev_conf;
18pub use self::dev_conf::*;
19mod icmp6_stats;
20pub use self::icmp6_stats::*;
21mod stats;
22pub use self::stats::*;
23
24#[derive(Clone, Eq, PartialEq, Debug)]
25#[non_exhaustive]
26pub enum Inet6 {
27    Flags(u32),
28    CacheInfo(Vec<u8>),
29    DevConf(Vec<u8>),
30    Unspec(Vec<u8>),
31    Stats(Vec<u8>),
32    IcmpStats(Vec<u8>),
33    Token([u8; 16]),
34    AddrGenMode(u8),
35    Other(DefaultNla),
36}
37
38impl Nla for Inet6 {
39    fn value_len(&self) -> usize {
40        use self::Inet6::*;
41        match *self {
42            Unspec(ref bytes) => bytes.len(),
43            CacheInfo(ref cache_info) => cache_info.len(),
44            DevConf(ref dev_conf) => dev_conf.len(),
45            Stats(ref stats) => stats.len(),
46            IcmpStats(ref icmp_stats) => icmp_stats.len(),
47            Flags(_) => 4,
48            Token(_) => 16,
49            AddrGenMode(_) => 1,
50            Other(ref nla) => nla.value_len(),
51        }
52    }
53
54    fn emit_value(&self, buffer: &mut [u8]) {
55        use self::Inet6::*;
56        match *self {
57            Unspec(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
58            Flags(ref value) => NativeEndian::write_u32(buffer, *value),
59            CacheInfo(ref cache_info) => {
60                buffer.copy_from_slice(cache_info.as_slice())
61            }
62            DevConf(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
63            Stats(ref inet6_stats) => {
64                buffer.copy_from_slice(inet6_stats.as_slice())
65            }
66            IcmpStats(ref icmp6_stats) => {
67                buffer.copy_from_slice(icmp6_stats.as_slice())
68            }
69            Token(ref ipv6) => buffer.copy_from_slice(&ipv6[..]),
70            AddrGenMode(value) => buffer[0] = value,
71            Other(ref nla) => nla.emit_value(buffer),
72        }
73    }
74
75    fn kind(&self) -> u16 {
76        use self::Inet6::*;
77        match *self {
78            Unspec(_) => IFLA_INET6_UNSPEC,
79            Flags(_) => IFLA_INET6_FLAGS,
80            CacheInfo(_) => IFLA_INET6_CACHEINFO,
81            DevConf(_) => IFLA_INET6_CONF,
82            Stats(_) => IFLA_INET6_STATS,
83            IcmpStats(_) => IFLA_INET6_ICMP6STATS,
84            Token(_) => IFLA_INET6_TOKEN,
85            AddrGenMode(_) => IFLA_INET6_ADDR_GEN_MODE,
86            Other(ref nla) => nla.kind(),
87        }
88    }
89}
90
91impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Inet6 {
92    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
93        use self::Inet6::*;
94        let payload = buf.value();
95        Ok(match buf.kind() {
96            IFLA_INET6_UNSPEC => Unspec(payload.to_vec()),
97            IFLA_INET6_FLAGS => Flags(
98                parse_u32(payload).context("invalid IFLA_INET6_FLAGS value")?,
99            ),
100            IFLA_INET6_CACHEINFO => CacheInfo(payload.to_vec()),
101            IFLA_INET6_CONF => DevConf(payload.to_vec()),
102            IFLA_INET6_STATS => Stats(payload.to_vec()),
103            IFLA_INET6_ICMP6STATS => IcmpStats(payload.to_vec()),
104            IFLA_INET6_TOKEN => Token(
105                parse_ipv6(payload)
106                    .context("invalid IFLA_INET6_TOKEN value")?,
107            ),
108            IFLA_INET6_ADDR_GEN_MODE => AddrGenMode(
109                parse_u8(payload)
110                    .context("invalid IFLA_INET6_ADDR_GEN_MODE value")?,
111            ),
112            kind => Other(
113                DefaultNla::parse(buf)
114                    .context(format!("unknown NLA type {kind}"))?,
115            ),
116        })
117    }
118}