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