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