netlink_packet_route/rtnl/link/nlas/inet6/
mod.rs1use 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}