netlink_packet_route/rtnl/address/nlas/
mod.rs1mod cache_info;
4pub use self::cache_info::*;
5
6use std::mem::size_of;
7
8use anyhow::Context;
9use byteorder::{ByteOrder, NativeEndian};
10
11use crate::{
12 constants::*,
13 nlas::{self, DefaultNla, NlaBuffer},
14 parsers::{parse_string, parse_u32},
15 traits::Parseable,
16 DecodeError,
17};
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20pub enum Nla {
21 Unspec(Vec<u8>),
22 Address(Vec<u8>),
23 Local(Vec<u8>),
24 Label(String),
25 Broadcast(Vec<u8>),
26 Anycast(Vec<u8>),
27 CacheInfo(Vec<u8>),
28 Multicast(Vec<u8>),
29 Flags(u32),
30 Other(DefaultNla),
31}
32
33impl nlas::Nla for Nla {
34 #[rustfmt::skip]
35 fn value_len(&self) -> usize {
36 use self::Nla::*;
37 match *self {
38 Unspec(ref bytes)
40 | Address(ref bytes)
41 | Local(ref bytes)
42 | Broadcast(ref bytes)
43 | Anycast(ref bytes)
44 | Multicast(ref bytes) => bytes.len(),
45
46 Label(ref string) => string.as_bytes().len() + 1,
48
49 Flags(_) => size_of::<u32>(),
51
52 CacheInfo(ref buffer) => buffer.len(),
54
55 Other(ref attr) => attr.value_len(),
57 }
58 }
59
60 #[rustfmt::skip]
61 fn emit_value(&self, buffer: &mut [u8]) {
62 use self::Nla::*;
63 match *self {
64 Unspec(ref bytes)
66 | Address(ref bytes)
67 | Local(ref bytes)
68 | Broadcast(ref bytes)
69 | Anycast(ref bytes)
70 | CacheInfo(ref bytes)
71 | Multicast(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
72
73 Label(ref string) => {
75 buffer[..string.len()].copy_from_slice(string.as_bytes());
76 buffer[string.len()] = 0;
77 }
78
79 Flags(ref value) => NativeEndian::write_u32(buffer, *value),
81
82
83 Other(ref attr) => attr.emit_value(buffer),
85 }
86 }
87
88 fn kind(&self) -> u16 {
89 use self::Nla::*;
90 match *self {
91 Unspec(_) => IFA_UNSPEC,
92 Address(_) => IFA_ADDRESS,
93 Local(_) => IFA_LOCAL,
94 Label(_) => IFA_LABEL,
95 Broadcast(_) => IFA_BROADCAST,
96 Anycast(_) => IFA_ANYCAST,
97 CacheInfo(_) => IFA_CACHEINFO,
98 Multicast(_) => IFA_MULTICAST,
99 Flags(_) => IFA_FLAGS,
100 Other(ref nla) => nla.kind(),
101 }
102 }
103}
104
105impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nla {
106 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
107 use self::Nla::*;
108 let payload = buf.value();
109 Ok(match buf.kind() {
110 IFA_UNSPEC => Unspec(payload.to_vec()),
111 IFA_ADDRESS => Address(payload.to_vec()),
112 IFA_LOCAL => Local(payload.to_vec()),
113 IFA_LABEL => Label(parse_string(payload).context("invalid IFA_LABEL value")?),
114 IFA_BROADCAST => Broadcast(payload.to_vec()),
115 IFA_ANYCAST => Anycast(payload.to_vec()),
116 IFA_CACHEINFO => CacheInfo(payload.to_vec()),
117 IFA_MULTICAST => Multicast(payload.to_vec()),
118 IFA_FLAGS => Flags(parse_u32(payload).context("invalid IFA_FLAGS value")?),
119 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
120 })
121 }
122}