1mod inet;
4pub use self::inet::*;
5
6mod inet6;
7pub use self::inet6::*;
8
9mod af_spec_inet;
10pub use self::af_spec_inet::*;
11
12mod af_spec_bridge;
13pub use self::af_spec_bridge::*;
14
15mod link_infos;
16pub use self::link_infos::*;
17
18mod prop_list;
19pub use self::prop_list::*;
20
21mod map;
22pub use self::map::*;
23
24mod stats;
25pub use self::stats::*;
26
27mod stats64;
28pub use self::stats64::*;
29
30mod link_state;
31pub use self::link_state::*;
32
33#[cfg(test)]
34mod tests;
35
36use std::os::unix::io::RawFd;
37
38use anyhow::Context;
39use byteorder::{ByteOrder, NativeEndian};
40
41use crate::{
42 constants::*,
43 nlas::{self, DefaultNla, NlaBuffer, NlasIterator, NLA_F_NESTED},
44 parsers::{parse_i32, parse_string, parse_u32, parse_u8},
45 traits::{Emitable, Parseable, ParseableParametrized},
46 DecodeError,
47};
48
49#[derive(Debug, PartialEq, Eq, Clone)]
50pub enum Nla {
51 Unspec(Vec<u8>),
53 Cost(Vec<u8>),
54 Priority(Vec<u8>),
55 Weight(Vec<u8>),
56 VfInfoList(Vec<u8>),
57 VfPorts(Vec<u8>),
58 PortSelf(Vec<u8>),
59 PhysPortId(Vec<u8>),
60 PhysSwitchId(Vec<u8>),
61 Pad(Vec<u8>),
62 Xdp(Vec<u8>),
63 Event(Vec<u8>),
64 NewNetnsId(Vec<u8>),
65 IfNetnsId(Vec<u8>),
66 CarrierUpCount(Vec<u8>),
67 CarrierDownCount(Vec<u8>),
68 NewIfIndex(Vec<u8>),
69 Info(Vec<Info>),
70 Wireless(Vec<u8>),
71 ProtoInfo(Vec<u8>),
72 PropList(Vec<Prop>),
80 ProtoDownReason(Vec<u8>),
87 Address(Vec<u8>),
90 Broadcast(Vec<u8>),
91 PermAddress(Vec<u8>),
94
95 IfName(String),
100 Qdisc(String),
101 IfAlias(String),
102 PhysPortName(String),
103 AltIfName(String),
109 Mode(u8),
111 Carrier(u8),
112 ProtoDown(u8),
113 Mtu(u32),
115 Link(u32),
116 Master(u32),
117 TxQueueLen(u32),
118 NetNsPid(u32),
119 NumVf(u32),
120 Group(u32),
121 NetNsFd(RawFd),
122 ExtMask(u32),
123 Promiscuity(u32),
124 NumTxQueues(u32),
125 NumRxQueues(u32),
126 CarrierChanges(u32),
127 GsoMaxSegs(u32),
128 GsoMaxSize(u32),
129 MinMtu(u32),
134 MaxMtu(u32),
139 NetnsId(i32),
141 OperState(State),
143 Stats(Vec<u8>),
144 Stats64(Vec<u8>),
145 Map(Vec<u8>),
146 AfSpecInet(Vec<AfSpecInet>),
148 AfSpecBridge(Vec<AfSpecBridge>),
149 AfSpecUnknown(Vec<u8>),
151 Other(DefaultNla),
152}
153
154impl nlas::Nla for Nla {
155 #[rustfmt::skip]
156 fn value_len(&self) -> usize {
157 use self::Nla::*;
158 match *self {
159 Unspec(ref bytes)
161 | Cost(ref bytes)
162 | Priority(ref bytes)
163 | Weight(ref bytes)
164 | VfInfoList(ref bytes)
165 | VfPorts(ref bytes)
166 | PortSelf(ref bytes)
167 | PhysPortId(ref bytes)
168 | PhysSwitchId(ref bytes)
169 | Pad(ref bytes)
170 | Xdp(ref bytes)
171 | Event(ref bytes)
172 | NewNetnsId(ref bytes)
173 | IfNetnsId(ref bytes)
174 | Wireless(ref bytes)
175 | ProtoInfo(ref bytes)
176 | CarrierUpCount(ref bytes)
177 | CarrierDownCount(ref bytes)
178 | NewIfIndex(ref bytes)
179 | Address(ref bytes)
180 | Broadcast(ref bytes)
181 | PermAddress(ref bytes)
182 | AfSpecUnknown(ref bytes)
183 | Map(ref bytes)
184 | ProtoDownReason(ref bytes)
185 => bytes.len(),
186
187 IfName(ref string)
189 | Qdisc(ref string)
190 | IfAlias(ref string)
191 | PhysPortName(ref string)
192 | AltIfName(ref string)
193 => string.as_bytes().len() + 1,
194
195 Mode(_)
197 | Carrier(_)
198 | ProtoDown(_)
199 => 1,
200
201 Mtu(_)
203 | Link(_)
204 | Master(_)
205 | TxQueueLen(_)
206 | NetNsPid(_)
207 | NumVf(_)
208 | Group(_)
209 | NetNsFd(_)
210 | ExtMask(_)
211 | Promiscuity(_)
212 | NumTxQueues(_)
213 | NumRxQueues(_)
214 | CarrierChanges(_)
215 | GsoMaxSegs(_)
216 | GsoMaxSize(_)
217 | NetnsId(_)
218 | MinMtu(_)
219 | MaxMtu(_) => 4,
220
221 OperState(_) => 1,
223 Stats(_) => LINK_STATS_LEN,
224 Stats64(_) => LINK_STATS64_LEN,
225 Info(ref nlas) => nlas.as_slice().buffer_len(),
226 PropList(ref nlas) => nlas.as_slice().buffer_len(),
227 AfSpecInet(ref nlas) => nlas.as_slice().buffer_len(),
228 AfSpecBridge(ref nlas) => nlas.as_slice().buffer_len(),
229 Other(ref attr) => attr.value_len(),
230 }
231 }
232
233 #[rustfmt::skip]
234 fn emit_value(&self, buffer: &mut [u8]) {
235 use self::Nla::*;
236 match *self {
237 Unspec(ref bytes)
239 | Cost(ref bytes)
240 | Priority(ref bytes)
241 | Weight(ref bytes)
242 | VfInfoList(ref bytes)
243 | VfPorts(ref bytes)
244 | PortSelf(ref bytes)
245 | PhysPortId(ref bytes)
246 | PhysSwitchId(ref bytes)
247 | Wireless(ref bytes)
248 | ProtoInfo(ref bytes)
249 | Pad(ref bytes)
250 | Xdp(ref bytes)
251 | Event(ref bytes)
252 | NewNetnsId(ref bytes)
253 | IfNetnsId(ref bytes)
254 | CarrierUpCount(ref bytes)
255 | CarrierDownCount(ref bytes)
256 | NewIfIndex(ref bytes)
257 | Address(ref bytes)
260 | Broadcast(ref bytes)
261 | PermAddress(ref bytes)
262 | AfSpecUnknown(ref bytes)
263 | Stats(ref bytes)
264 | Stats64(ref bytes)
265 | Map(ref bytes)
266 | ProtoDownReason(ref bytes)
267 => buffer.copy_from_slice(bytes.as_slice()),
268
269 IfName(ref string)
271 | Qdisc(ref string)
272 | IfAlias(ref string)
273 | PhysPortName(ref string)
274 | AltIfName(ref string)
275 => {
276 buffer[..string.len()].copy_from_slice(string.as_bytes());
277 buffer[string.len()] = 0;
278 }
279
280 Mode(ref val)
282 | Carrier(ref val)
283 | ProtoDown(ref val)
284 => buffer[0] = *val,
285
286 Mtu(ref value)
288 | Link(ref value)
289 | Master(ref value)
290 | TxQueueLen(ref value)
291 | NetNsPid(ref value)
292 | NumVf(ref value)
293 | Group(ref value)
294 | ExtMask(ref value)
295 | Promiscuity(ref value)
296 | NumTxQueues(ref value)
297 | NumRxQueues(ref value)
298 | CarrierChanges(ref value)
299 | GsoMaxSegs(ref value)
300 | GsoMaxSize(ref value)
301 | MinMtu(ref value)
302 | MaxMtu(ref value)
303 => NativeEndian::write_u32(buffer, *value),
304
305 NetnsId(ref value)
306 | NetNsFd(ref value)
307 => NativeEndian::write_i32(buffer, *value),
308
309 OperState(state) => buffer[0] = state.into(),
310 Info(ref nlas) => nlas.as_slice().emit(buffer),
311 PropList(ref nlas) => nlas.as_slice().emit(buffer),
312 AfSpecInet(ref nlas) => nlas.as_slice().emit(buffer),
313 AfSpecBridge(ref nlas) => nlas.as_slice().emit(buffer),
314 Other(ref attr) => attr.emit_value(buffer),
316 }
317 }
318
319 fn kind(&self) -> u16 {
320 use self::Nla::*;
321 match *self {
322 Unspec(_) => IFLA_UNSPEC,
324 Cost(_) => IFLA_COST,
325 Priority(_) => IFLA_PRIORITY,
326 Weight(_) => IFLA_WEIGHT,
327 VfInfoList(_) => IFLA_VFINFO_LIST,
328 VfPorts(_) => IFLA_VF_PORTS,
329 PortSelf(_) => IFLA_PORT_SELF,
330 PhysPortId(_) => IFLA_PHYS_PORT_ID,
331 PhysSwitchId(_) => IFLA_PHYS_SWITCH_ID,
332 Info(_) => IFLA_LINKINFO,
333 Wireless(_) => IFLA_WIRELESS,
334 ProtoInfo(_) => IFLA_PROTINFO,
335 Pad(_) => IFLA_PAD,
336 Xdp(_) => IFLA_XDP,
337 Event(_) => IFLA_EVENT,
338 NewNetnsId(_) => IFLA_NEW_NETNSID,
339 IfNetnsId(_) => IFLA_IF_NETNSID,
340 CarrierUpCount(_) => IFLA_CARRIER_UP_COUNT,
341 CarrierDownCount(_) => IFLA_CARRIER_DOWN_COUNT,
342 NewIfIndex(_) => IFLA_NEW_IFINDEX,
343 PropList(_) => IFLA_PROP_LIST | NLA_F_NESTED,
344 ProtoDownReason(_) => IFLA_PROTO_DOWN_REASON,
345 Address(_) => IFLA_ADDRESS,
347 Broadcast(_) => IFLA_BROADCAST,
348 PermAddress(_) => IFLA_PERM_ADDRESS,
349 IfName(_) => IFLA_IFNAME,
351 Qdisc(_) => IFLA_QDISC,
352 IfAlias(_) => IFLA_IFALIAS,
353 PhysPortName(_) => IFLA_PHYS_PORT_NAME,
354 AltIfName(_) => IFLA_ALT_IFNAME,
355 Mode(_) => IFLA_LINKMODE,
357 Carrier(_) => IFLA_CARRIER,
358 ProtoDown(_) => IFLA_PROTO_DOWN,
359 Mtu(_) => IFLA_MTU,
361 Link(_) => IFLA_LINK,
362 Master(_) => IFLA_MASTER,
363 TxQueueLen(_) => IFLA_TXQLEN,
364 NetNsPid(_) => IFLA_NET_NS_PID,
365 NumVf(_) => IFLA_NUM_VF,
366 Group(_) => IFLA_GROUP,
367 NetNsFd(_) => IFLA_NET_NS_FD,
368 ExtMask(_) => IFLA_EXT_MASK,
369 Promiscuity(_) => IFLA_PROMISCUITY,
370 NumTxQueues(_) => IFLA_NUM_TX_QUEUES,
371 NumRxQueues(_) => IFLA_NUM_RX_QUEUES,
372 CarrierChanges(_) => IFLA_CARRIER_CHANGES,
373 GsoMaxSegs(_) => IFLA_GSO_MAX_SEGS,
374 GsoMaxSize(_) => IFLA_GSO_MAX_SIZE,
375 MinMtu(_) => IFLA_MIN_MTU,
376 MaxMtu(_) => IFLA_MAX_MTU,
377 NetnsId(_) => IFLA_LINK_NETNSID,
379 OperState(_) => IFLA_OPERSTATE,
381 Map(_) => IFLA_MAP,
382 Stats(_) => IFLA_STATS,
383 Stats64(_) => IFLA_STATS64,
384 AfSpecInet(_) | AfSpecBridge(_) | AfSpecUnknown(_) => IFLA_AF_SPEC,
385 Other(ref attr) => attr.kind(),
386 }
387 }
388}
389
390impl<'a, T: AsRef<[u8]> + ?Sized> ParseableParametrized<NlaBuffer<&'a T>, u16> for Nla {
391 fn parse_with_param(
392 buf: &NlaBuffer<&'a T>,
393 interface_family: u16,
394 ) -> Result<Self, DecodeError> {
395 use Nla::*;
396 let payload = buf.value();
397 Ok(match buf.kind() {
398 IFLA_UNSPEC => Unspec(payload.to_vec()),
400 IFLA_COST => Cost(payload.to_vec()),
401 IFLA_PRIORITY => Priority(payload.to_vec()),
402 IFLA_WEIGHT => Weight(payload.to_vec()),
403 IFLA_VFINFO_LIST => VfInfoList(payload.to_vec()),
404 IFLA_VF_PORTS => VfPorts(payload.to_vec()),
405 IFLA_PORT_SELF => PortSelf(payload.to_vec()),
406 IFLA_PHYS_PORT_ID => PhysPortId(payload.to_vec()),
407 IFLA_PHYS_SWITCH_ID => PhysSwitchId(payload.to_vec()),
408 IFLA_WIRELESS => Wireless(payload.to_vec()),
409 IFLA_PROTINFO => ProtoInfo(payload.to_vec()),
410 IFLA_PAD => Pad(payload.to_vec()),
411 IFLA_XDP => Xdp(payload.to_vec()),
412 IFLA_EVENT => Event(payload.to_vec()),
413 IFLA_NEW_NETNSID => NewNetnsId(payload.to_vec()),
414 IFLA_IF_NETNSID => IfNetnsId(payload.to_vec()),
415 IFLA_CARRIER_UP_COUNT => CarrierUpCount(payload.to_vec()),
416 IFLA_CARRIER_DOWN_COUNT => CarrierDownCount(payload.to_vec()),
417 IFLA_NEW_IFINDEX => NewIfIndex(payload.to_vec()),
418 IFLA_PROP_LIST => {
419 let error_msg = "invalid IFLA_PROP_LIST value";
420 let mut nlas = vec![];
421 for nla in NlasIterator::new(payload) {
422 let nla = &nla.context(error_msg)?;
423 let parsed = Prop::parse(nla).context(error_msg)?;
424 nlas.push(parsed);
425 }
426 PropList(nlas)
427 }
428 IFLA_PROTO_DOWN_REASON => ProtoDownReason(payload.to_vec()),
429 IFLA_ADDRESS => Address(payload.to_vec()),
432 IFLA_BROADCAST => Broadcast(payload.to_vec()),
433 IFLA_PERM_ADDRESS => PermAddress(payload.to_vec()),
434 IFLA_IFNAME => IfName(parse_string(payload).context("invalid IFLA_IFNAME value")?),
436 IFLA_QDISC => Qdisc(parse_string(payload).context("invalid IFLA_QDISC value")?),
437 IFLA_IFALIAS => IfAlias(parse_string(payload).context("invalid IFLA_IFALIAS value")?),
438 IFLA_PHYS_PORT_NAME => {
439 PhysPortName(parse_string(payload).context("invalid IFLA_PHYS_PORT_NAME value")?)
440 }
441 IFLA_ALT_IFNAME => {
442 AltIfName(parse_string(payload).context("invalid IFLA_ALT_IFNAME value")?)
443 }
444
445 IFLA_LINKMODE => Mode(parse_u8(payload).context("invalid IFLA_LINKMODE value")?),
447 IFLA_CARRIER => Carrier(parse_u8(payload).context("invalid IFLA_CARRIER value")?),
448 IFLA_PROTO_DOWN => {
449 ProtoDown(parse_u8(payload).context("invalid IFLA_PROTO_DOWN value")?)
450 }
451
452 IFLA_MTU => Mtu(parse_u32(payload).context("invalid IFLA_MTU value")?),
453 IFLA_LINK => Link(parse_u32(payload).context("invalid IFLA_LINK value")?),
454 IFLA_MASTER => Master(parse_u32(payload).context("invalid IFLA_MASTER value")?),
455 IFLA_TXQLEN => TxQueueLen(parse_u32(payload).context("invalid IFLA_TXQLEN value")?),
456 IFLA_NET_NS_PID => {
457 NetNsPid(parse_u32(payload).context("invalid IFLA_NET_NS_PID value")?)
458 }
459 IFLA_NUM_VF => NumVf(parse_u32(payload).context("invalid IFLA_NUM_VF value")?),
460 IFLA_GROUP => Group(parse_u32(payload).context("invalid IFLA_GROUP value")?),
461 IFLA_NET_NS_FD => NetNsFd(parse_i32(payload).context("invalid IFLA_NET_NS_FD value")?),
462 IFLA_EXT_MASK => ExtMask(parse_u32(payload).context("invalid IFLA_EXT_MASK value")?),
463 IFLA_PROMISCUITY => {
464 Promiscuity(parse_u32(payload).context("invalid IFLA_PROMISCUITY value")?)
465 }
466 IFLA_NUM_TX_QUEUES => {
467 NumTxQueues(parse_u32(payload).context("invalid IFLA_NUM_TX_QUEUES value")?)
468 }
469 IFLA_NUM_RX_QUEUES => {
470 NumRxQueues(parse_u32(payload).context("invalid IFLA_NUM_RX_QUEUES value")?)
471 }
472 IFLA_CARRIER_CHANGES => {
473 CarrierChanges(parse_u32(payload).context("invalid IFLA_CARRIER_CHANGES value")?)
474 }
475 IFLA_GSO_MAX_SEGS => {
476 GsoMaxSegs(parse_u32(payload).context("invalid IFLA_GSO_MAX_SEGS value")?)
477 }
478 IFLA_GSO_MAX_SIZE => {
479 GsoMaxSize(parse_u32(payload).context("invalid IFLA_GSO_MAX_SIZE value")?)
480 }
481 IFLA_MIN_MTU => MinMtu(parse_u32(payload).context("invalid IFLA_MIN_MTU value")?),
482 IFLA_MAX_MTU => MaxMtu(parse_u32(payload).context("invalid IFLA_MAX_MTU value")?),
483 IFLA_LINK_NETNSID => {
484 NetnsId(parse_i32(payload).context("invalid IFLA_LINK_NETNSID value")?)
485 }
486 IFLA_OPERSTATE => OperState(
487 parse_u8(payload)
488 .context("invalid IFLA_OPERSTATE value")?
489 .into(),
490 ),
491 IFLA_MAP => Map(payload.to_vec()),
492 IFLA_STATS => Stats(payload.to_vec()),
493 IFLA_STATS64 => Stats64(payload.to_vec()),
494 IFLA_AF_SPEC => match interface_family as u16 {
495 AF_INET | AF_INET6 | AF_UNSPEC => {
496 let mut nlas = vec![];
497 let err = "invalid IFLA_AF_SPEC value";
498 for nla in NlasIterator::new(payload) {
499 let nla = nla.context(err)?;
500 nlas.push(af_spec_inet::AfSpecInet::parse(&nla).context(err)?);
501 }
502 AfSpecInet(nlas)
503 }
504 AF_BRIDGE => {
505 let mut nlas = vec![];
506 let err = "invalid IFLA_AF_SPEC value for AF_BRIDGE";
507 for nla in NlasIterator::new(payload) {
508 let nla = nla.context(err)?;
509 nlas.push(af_spec_bridge::AfSpecBridge::parse(&nla).context(err)?);
510 }
511 AfSpecBridge(nlas)
512 }
513 _ => AfSpecUnknown(payload.to_vec()),
514 },
515 IFLA_LINKINFO => {
516 let err = "invalid IFLA_LINKINFO value";
517 let buf = NlaBuffer::new_checked(payload).context(err)?;
518 Info(VecInfo::parse(&buf).context(err)?.0)
519 }
520
521 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
522 })
523 }
524}