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