netlink_packet_route/link/link_info/
netkit.rs1use netlink_packet_core::{
4 emit_u16, emit_u32, parse_u16, parse_u32, parse_u8, DecodeError,
5 DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, Parseable,
6};
7
8use super::super::{LinkMessage, LinkMessageBuffer};
9
10const NETKIT_L2: u32 = 0;
11const NETKIT_L3: u32 = 1;
12
13#[derive(Debug, PartialEq, Eq, Clone, Copy)]
14#[non_exhaustive]
15pub enum NetkitMode {
16 L2,
17 L3,
18 Other(u32),
19}
20
21impl From<NetkitMode> for u32 {
22 fn from(mode: NetkitMode) -> Self {
23 match mode {
24 NetkitMode::L2 => NETKIT_L2,
25 NetkitMode::L3 => NETKIT_L3,
26 NetkitMode::Other(value) => value,
27 }
28 }
29}
30
31impl From<u32> for NetkitMode {
32 fn from(value: u32) -> Self {
33 match value {
34 NETKIT_L2 => NetkitMode::L2,
35 NETKIT_L3 => NetkitMode::L3,
36 _ => NetkitMode::Other(value),
37 }
38 }
39}
40
41const NETKIT_PASS: u32 = 0;
42const NETKIT_DROP: u32 = 2;
43const NETKIT_REDIRECT: u32 = 7;
44
45#[derive(Debug, PartialEq, Eq, Clone, Copy)]
46#[non_exhaustive]
47pub enum NetkitPolicy {
48 Pass,
49 Drop,
50 Redirect,
51 Other(u32),
52}
53
54impl NetkitPolicy {
55 #[allow(non_upper_case_globals)]
57 pub const Forward: NetkitPolicy = Self::Pass;
58}
59
60impl From<NetkitPolicy> for u32 {
61 fn from(policy: NetkitPolicy) -> Self {
62 match policy {
63 NetkitPolicy::Pass => NETKIT_PASS,
64 NetkitPolicy::Drop => NETKIT_DROP,
65 NetkitPolicy::Redirect => NETKIT_REDIRECT,
66 NetkitPolicy::Other(value) => value,
67 }
68 }
69}
70
71impl From<u32> for NetkitPolicy {
72 fn from(value: u32) -> Self {
73 match value {
74 NETKIT_PASS => NetkitPolicy::Pass,
75 NETKIT_DROP => NetkitPolicy::Drop,
76 _ => NetkitPolicy::Other(value),
77 }
78 }
79}
80
81const NETKIT_SCRUB_NONE: u32 = 0;
82const NETKIT_SCRUB_DEFAULT: u32 = 1;
83
84#[derive(Debug, PartialEq, Eq, Clone, Copy)]
85#[non_exhaustive]
86pub enum NetkitScrub {
87 None,
88 Default,
89}
90
91impl From<NetkitScrub> for u32 {
92 fn from(scrub: NetkitScrub) -> Self {
93 match scrub {
94 NetkitScrub::None => NETKIT_SCRUB_NONE,
95 _ => NETKIT_SCRUB_DEFAULT,
96 }
97 }
98}
99
100impl From<u32> for NetkitScrub {
101 fn from(value: u32) -> Self {
102 match value {
103 NETKIT_SCRUB_NONE => NetkitScrub::None,
104 _ => NetkitScrub::Default,
105 }
106 }
107}
108
109const IFLA_NETKIT_PEER_INFO: u16 = 1;
110const IFLA_NETKIT_PRIMARY: u16 = 2;
111const IFLA_NETKIT_POLICY: u16 = 3;
112const IFLA_NETKIT_PEER_POLICY: u16 = 4;
113const IFLA_NETKIT_MODE: u16 = 5;
114const IFLA_NETKIT_SCRUB: u16 = 6;
115const IFLA_NETKIT_PEER_SCRUB: u16 = 7;
116const IFLA_NETKIT_HEADROOM: u16 = 8;
117const IFLA_NETKIT_TAILROOM: u16 = 9;
118
119#[derive(Debug, PartialEq, Eq, Clone)]
120#[non_exhaustive]
121pub enum InfoNetkit {
122 Peer(LinkMessage),
123 Primary(bool),
124 Policy(NetkitPolicy),
125 PeerPolicy(NetkitPolicy),
126 Mode(NetkitMode),
127 Scrub(NetkitScrub),
128 PeerScrub(NetkitScrub),
129 Headroom(u16),
130 Tailroom(u16),
131 Other(DefaultNla),
132}
133
134impl Nla for InfoNetkit {
135 fn value_len(&self) -> usize {
136 match *self {
137 Self::Peer(ref message) => message.buffer_len(),
138 Self::Primary(_) => 1,
139 Self::Policy(_) | Self::PeerPolicy(_) | Self::Mode(_) => 4,
140 Self::Scrub(_) | Self::PeerScrub(_) => 4,
141 Self::Headroom(_) | Self::Tailroom(_) => 4,
142 Self::Other(ref attr) => attr.value_len(),
143 }
144 }
145
146 fn emit_value(&self, buffer: &mut [u8]) {
147 match *self {
148 Self::Peer(ref message) => message.emit(buffer),
149 Self::Primary(value) => {
150 buffer[0] = value as u8;
151 }
152 Self::Policy(value) | Self::PeerPolicy(value) => {
153 emit_u32(buffer, value.into()).unwrap();
154 }
155 Self::Mode(value) => {
156 emit_u32(buffer, value.into()).unwrap();
157 }
158 Self::Scrub(value) | Self::PeerScrub(value) => {
159 emit_u32(buffer, value.into()).unwrap();
160 }
161 Self::Headroom(value) | Self::Tailroom(value) => {
162 emit_u16(buffer, value).unwrap();
163 }
164 Self::Other(ref attr) => attr.emit_value(buffer),
165 }
166 }
167
168 fn kind(&self) -> u16 {
169 match *self {
170 Self::Peer(_) => IFLA_NETKIT_PEER_INFO,
171 Self::Primary(_) => IFLA_NETKIT_PRIMARY,
172 Self::Policy(_) => IFLA_NETKIT_POLICY,
173 Self::PeerPolicy(_) => IFLA_NETKIT_PEER_POLICY,
174 Self::Mode(_) => IFLA_NETKIT_MODE,
175 Self::Scrub(_) => IFLA_NETKIT_SCRUB,
176 Self::PeerScrub(_) => IFLA_NETKIT_PEER_SCRUB,
177 Self::Headroom(_) => IFLA_NETKIT_HEADROOM,
178 Self::Tailroom(_) => IFLA_NETKIT_TAILROOM,
179 Self::Other(ref attr) => attr.kind(),
180 }
181 }
182}
183
184impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoNetkit {
185 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
186 let payload = buf.value();
187 Ok(match buf.kind() {
188 IFLA_NETKIT_PEER_INFO => {
189 let err = "failed to parse netkit peer info";
190 let buffer =
191 LinkMessageBuffer::new_checked(&payload).context(err)?;
192 Self::Peer(LinkMessage::parse(&buffer).context(err)?)
193 }
194 IFLA_NETKIT_PRIMARY => {
195 let value = parse_u8(payload)? != 0;
196 Self::Primary(value)
197 }
198 IFLA_NETKIT_POLICY => Self::Policy(parse_u32(payload)?.into()),
199 IFLA_NETKIT_PEER_POLICY => {
200 Self::PeerPolicy(parse_u32(payload)?.into())
201 }
202 IFLA_NETKIT_MODE => Self::Mode(parse_u32(payload)?.into()),
203 IFLA_NETKIT_SCRUB => Self::Scrub(parse_u32(payload)?.into()),
204 IFLA_NETKIT_PEER_SCRUB => {
205 Self::PeerScrub(parse_u32(payload)?.into())
206 }
207 IFLA_NETKIT_HEADROOM => Self::Headroom(parse_u16(payload)?),
208 IFLA_NETKIT_TAILROOM => Self::Tailroom(parse_u16(payload)?),
209 kind => Self::Other(
210 DefaultNla::parse(buf)
211 .context(format!("unknown NLA type {kind} for netkit"))?,
212 ),
213 })
214 }
215}