1use netlink_packet_core::{
4 parse_string, DecodeError, DefaultNla, Emitable, ErrorContext, Nla,
5 NlaBuffer, NlasIterator, Parseable, ParseableParametrized,
6};
7
8use super::super::{InfoData, InfoPortData, InfoPortKind, LinkXstats};
9
10const IFLA_INFO_KIND: u16 = 1;
11const IFLA_INFO_DATA: u16 = 2;
12const IFLA_INFO_XSTATS: u16 = 3;
13const IFLA_INFO_PORT_KIND: u16 = 4;
14const IFLA_INFO_PORT_DATA: u16 = 5;
15
16const DUMMY: &str = "dummy";
17const IFB: &str = "ifb";
18const BRIDGE: &str = "bridge";
19const TUN: &str = "tun";
20const NLMON: &str = "nlmon";
21const VLAN: &str = "vlan";
22const VETH: &str = "veth";
23const VXLAN: &str = "vxlan";
24const BOND: &str = "bond";
25const IPVLAN: &str = "ipvlan";
26const IPVTAP: &str = "ipvtap";
27const MACVLAN: &str = "macvlan";
28const MACVTAP: &str = "macvtap";
29const GRETAP: &str = "gretap";
30const IP6GRETAP: &str = "ip6gretap";
31const IPIP: &str = "ipip";
32const SIT: &str = "sit";
33const GRE: &str = "gre";
34const IP6GRE: &str = "ip6gre";
35const VTI: &str = "vti";
36const VRF: &str = "vrf";
37const GTP: &str = "gtp";
38const IPOIB: &str = "ipoib";
39const WIREGUARD: &str = "wireguard";
40const XFRM: &str = "xfrm";
41const MACSEC: &str = "macsec";
42const HSR: &str = "hsr";
43const GENEVE: &str = "geneve";
44
45#[derive(Debug, PartialEq, Eq, Clone)]
46#[non_exhaustive]
47pub enum LinkInfo {
48 Xstats(LinkXstats),
49 Kind(InfoKind),
50 Data(InfoData),
51 PortKind(InfoPortKind),
52 PortData(InfoPortData),
53 Other(DefaultNla),
54}
55
56impl Nla for LinkInfo {
57 fn value_len(&self) -> usize {
58 match self {
59 Self::Xstats(v) => v.buffer_len(),
60 Self::Kind(nla) => nla.value_len(),
61 Self::Data(nla) => nla.value_len(),
62 Self::PortKind(nla) => nla.value_len(),
63 Self::PortData(nla) => nla.value_len(),
64 Self::Other(nla) => nla.value_len(),
65 }
66 }
67
68 fn emit_value(&self, buffer: &mut [u8]) {
69 match self {
70 Self::Xstats(v) => v.emit(buffer),
71 Self::Kind(nla) => nla.emit_value(buffer),
72 Self::Data(nla) => nla.emit_value(buffer),
73 Self::PortKind(nla) => nla.emit_value(buffer),
74 Self::PortData(nla) => nla.emit_value(buffer),
75 Self::Other(nla) => nla.emit_value(buffer),
76 }
77 }
78
79 fn kind(&self) -> u16 {
80 match self {
81 Self::Xstats(_) => IFLA_INFO_XSTATS,
82 Self::PortKind(_) => IFLA_INFO_PORT_KIND,
83 Self::PortData(_) => IFLA_INFO_PORT_DATA,
84 Self::Kind(_) => IFLA_INFO_KIND,
85 Self::Data(_) => IFLA_INFO_DATA,
86 Self::Other(nla) => nla.kind(),
87 }
88 }
89}
90
91pub(crate) struct VecLinkInfo(pub(crate) Vec<LinkInfo>);
92
93impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VecLinkInfo {
105 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
106 let mut nlas = Vec::new();
107 let mut link_info_kind: Option<InfoKind> = None;
108 let mut link_info_port_kind: Option<InfoPortKind> = None;
109 for nla in NlasIterator::new(buf.into_inner()) {
110 let nla = nla?;
111 match nla.kind() {
112 IFLA_INFO_XSTATS => {
113 if let Some(link_info_kind) = &link_info_kind {
114 nlas.push(LinkInfo::Xstats(
115 LinkXstats::parse_with_param(&nla, link_info_kind)?,
116 ));
117 } else {
118 return Err("IFLA_INFO_XSTATS is not preceded by an \
119 IFLA_INFO_KIND"
120 .into());
121 }
122 }
123 IFLA_INFO_PORT_KIND => {
124 let parsed = InfoPortKind::parse(&nla)?;
125 nlas.push(LinkInfo::PortKind(parsed.clone()));
126 link_info_port_kind = Some(parsed);
127 }
128 IFLA_INFO_PORT_DATA => {
129 if let Some(link_info_port_kind) = link_info_port_kind {
130 nlas.push(LinkInfo::PortData(
131 InfoPortData::parse_with_param(
132 nla.value(),
133 link_info_port_kind,
134 )?,
135 ));
136 } else {
137 return Err("IFLA_INFO_PORT_DATA is not preceded by \
138 an IFLA_INFO_PORT_KIND"
139 .into());
140 }
141 link_info_port_kind = None;
142 }
143 IFLA_INFO_KIND => {
144 let parsed = InfoKind::parse(&nla)?;
145 nlas.push(LinkInfo::Kind(parsed.clone()));
146 link_info_kind = Some(parsed);
147 }
148 IFLA_INFO_DATA => {
149 if let Some(link_info_kind) = &link_info_kind {
150 nlas.push(LinkInfo::Data(InfoData::parse_with_param(
151 nla.value(),
152 link_info_kind,
153 )?));
154 } else {
155 return Err("IFLA_INFO_DATA is not preceded by an \
156 IFLA_INFO_KIND"
157 .into());
158 }
159 }
160 _kind => nlas.push(LinkInfo::Other(
161 DefaultNla::parse(&nla).context(format!(
162 "Unknown NLA type for IFLA_INFO_DATA {nla:?}"
163 ))?,
164 )),
165 }
166 }
167 Ok(Self(nlas))
168 }
169}
170
171#[derive(Debug, PartialEq, Eq, Clone)]
172#[non_exhaustive]
173pub enum InfoKind {
174 Dummy,
175 Ifb,
176 Bridge,
177 Tun,
178 Nlmon,
179 Vlan,
180 Veth,
181 Vxlan,
182 Bond,
183 IpVlan,
184 IpVtap,
185 MacVlan,
186 MacVtap,
187 GreTap,
188 GreTap6,
189 IpTun,
190 SitTun,
191 GreTun,
192 GreTun6,
193 Vti,
194 Vrf,
195 Gtp,
196 Ipoib,
197 Wireguard,
198 Xfrm,
199 MacSec,
200 Hsr,
201 Geneve,
202 Other(String),
203}
204
205impl std::fmt::Display for InfoKind {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 write!(
208 f,
209 "{}",
210 match self {
211 Self::Dummy => DUMMY,
212 Self::Ifb => IFB,
213 Self::Bridge => BRIDGE,
214 Self::Tun => TUN,
215 Self::Nlmon => NLMON,
216 Self::Vlan => VLAN,
217 Self::Veth => VETH,
218 Self::Vxlan => VXLAN,
219 Self::Bond => BOND,
220 Self::IpVlan => IPVLAN,
221 Self::IpVtap => IPVTAP,
222 Self::MacVlan => MACVLAN,
223 Self::MacVtap => MACVTAP,
224 Self::GreTap => GRETAP,
225 Self::GreTap6 => IP6GRETAP,
226 Self::IpTun => IPIP,
227 Self::SitTun => SIT,
228 Self::GreTun => GRE,
229 Self::GreTun6 => IP6GRE,
230 Self::Vti => VTI,
231 Self::Vrf => VRF,
232 Self::Gtp => GTP,
233 Self::Ipoib => IPOIB,
234 Self::Wireguard => WIREGUARD,
235 Self::Xfrm => XFRM,
236 Self::MacSec => MACSEC,
237 Self::Hsr => HSR,
238 Self::Geneve => GENEVE,
239 Self::Other(s) => s.as_str(),
240 }
241 )
242 }
243}
244
245impl Nla for InfoKind {
246 fn value_len(&self) -> usize {
247 let len = match self {
248 Self::Dummy => DUMMY.len(),
249 Self::Ifb => IFB.len(),
250 Self::Bridge => BRIDGE.len(),
251 Self::Tun => TUN.len(),
252 Self::Nlmon => NLMON.len(),
253 Self::Vlan => VLAN.len(),
254 Self::Veth => VETH.len(),
255 Self::Vxlan => VXLAN.len(),
256 Self::Bond => BOND.len(),
257 Self::IpVlan => IPVLAN.len(),
258 Self::IpVtap => IPVTAP.len(),
259 Self::MacVlan => MACVLAN.len(),
260 Self::MacVtap => MACVTAP.len(),
261 Self::GreTap => GRETAP.len(),
262 Self::GreTap6 => IP6GRETAP.len(),
263 Self::IpTun => IPIP.len(),
264 Self::SitTun => SIT.len(),
265 Self::GreTun => GRE.len(),
266 Self::GreTun6 => IP6GRE.len(),
267 Self::Vti => VTI.len(),
268 Self::Vrf => VRF.len(),
269 Self::Gtp => GTP.len(),
270 Self::Ipoib => IPOIB.len(),
271 Self::Wireguard => WIREGUARD.len(),
272 Self::Xfrm => XFRM.len(),
273 Self::MacSec => MACSEC.len(),
274 Self::Hsr => HSR.len(),
275 Self::Geneve => GENEVE.len(),
276 Self::Other(s) => s.len(),
277 };
278 len + 1
279 }
280
281 fn emit_value(&self, buffer: &mut [u8]) {
282 let kind = self.to_string();
283 let s = kind.as_str();
284 buffer[..s.len()].copy_from_slice(s.to_string().as_bytes());
285 buffer[s.len()] = 0;
286 }
287
288 fn kind(&self) -> u16 {
289 IFLA_INFO_KIND
290 }
291}
292
293impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoKind {
294 fn parse(buf: &NlaBuffer<&'a T>) -> Result<InfoKind, DecodeError> {
295 if buf.kind() != IFLA_INFO_KIND {
296 return Err(format!(
297 "failed to parse IFLA_INFO_KIND: NLA type is {}",
298 buf.kind()
299 )
300 .into());
301 }
302 let s = parse_string(buf.value())
303 .context("invalid IFLA_INFO_KIND value")?;
304 Ok(match s.as_str() {
305 DUMMY => Self::Dummy,
306 IFB => Self::Ifb,
307 BRIDGE => Self::Bridge,
308 TUN => Self::Tun,
309 NLMON => Self::Nlmon,
310 VLAN => Self::Vlan,
311 VETH => Self::Veth,
312 VXLAN => Self::Vxlan,
313 BOND => Self::Bond,
314 IPVLAN => Self::IpVlan,
315 IPVTAP => Self::IpVtap,
316 MACVLAN => Self::MacVlan,
317 MACVTAP => Self::MacVtap,
318 GRETAP => Self::GreTap,
319 IP6GRETAP => Self::GreTap6,
320 IPIP => Self::IpTun,
321 SIT => Self::SitTun,
322 GRE => Self::GreTun,
323 IP6GRE => Self::GreTun6,
324 VTI => Self::Vti,
325 VRF => Self::Vrf,
326 GTP => Self::Gtp,
327 IPOIB => Self::Ipoib,
328 WIREGUARD => Self::Wireguard,
329 MACSEC => Self::MacSec,
330 XFRM => Self::Xfrm,
331 HSR => Self::Hsr,
332 GENEVE => Self::Geneve,
333 _ => Self::Other(s),
334 })
335 }
336}