Skip to content
This repository was archived by the owner on Oct 26, 2022. It is now read-only.

Commit b4b3c46

Browse files
inemajocathay4t
authored andcommitted
netlink-packet-route/src/rtnl/link: Implement PropList nla
1 parent 26a8e2a commit b4b3c46

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

netlink-packet-route/src/rtnl/link/nlas/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ pub use self::af_spec_inet::*;
1010
mod link_infos;
1111
pub use self::link_infos::*;
1212

13+
mod prop_list;
14+
pub use self::prop_list::*;
15+
1316
mod map;
1417
pub use self::map::*;
1518

@@ -32,7 +35,7 @@ use byteorder::{ByteOrder, NativeEndian};
3235

3336
use crate::{
3437
constants::*,
35-
nlas::{self, DefaultNla, NlaBuffer, NlasIterator},
38+
nlas::{self, DefaultNla, NlaBuffer, NlasIterator, NLA_F_NESTED},
3639
parsers::{parse_i32, parse_string, parse_u32, parse_u8},
3740
traits::{Emitable, Parseable, ParseableParametrized},
3841
DecodeError,
@@ -68,7 +71,7 @@ pub enum Nla {
6871
/// [1]: https://lwn.net/ml/netdev/[email protected]/
6972
/// [2]: https://lwn.net/ml/netdev/[email protected]/
7073
/// [defining message]: https://lwn.net/ml/netdev/[email protected]/
71-
PropList(Vec<u8>),
74+
PropList(Vec<Prop>),
7275
/// `protodown` is a mechanism that allows protocols to hold an interface down.
7376
/// This field is used to specify the reason why it is held down.
7477
/// For additional context see the related linux kernel threads<sup>[1][1],[2][2]</sup>.
@@ -174,7 +177,6 @@ impl nlas::Nla for Nla {
174177
| AfSpecUnknown(ref bytes)
175178
| AfSpecBridge(ref bytes)
176179
| Map(ref bytes)
177-
| PropList(ref bytes)
178180
| ProtoDownReason(ref bytes)
179181
=> bytes.len(),
180182

@@ -217,6 +219,7 @@ impl nlas::Nla for Nla {
217219
Stats(_) => LINK_STATS_LEN,
218220
Stats64(_) => LINK_STATS64_LEN,
219221
Info(ref nlas) => nlas.as_slice().buffer_len(),
222+
PropList(ref nlas) => nlas.as_slice().buffer_len(),
220223
AfSpecInet(ref nlas) => nlas.as_slice().buffer_len(),
221224
// AfSpecBridge(ref nlas) => nlas.as_slice().buffer_len(),
222225
Other(ref attr) => attr.value_len(),
@@ -257,7 +260,6 @@ impl nlas::Nla for Nla {
257260
| Stats(ref bytes)
258261
| Stats64(ref bytes)
259262
| Map(ref bytes)
260-
| PropList(ref bytes)
261263
| ProtoDownReason(ref bytes)
262264
=> buffer.copy_from_slice(bytes.as_slice()),
263265

@@ -303,6 +305,7 @@ impl nlas::Nla for Nla {
303305

304306
OperState(state) => buffer[0] = state.into(),
305307
Info(ref nlas) => nlas.as_slice().emit(buffer),
308+
PropList(ref nlas) => nlas.as_slice().emit(buffer),
306309
AfSpecInet(ref nlas) => nlas.as_slice().emit(buffer),
307310
// AfSpecBridge(ref nlas) => nlas.as_slice().emit(buffer),
308311
// default nlas
@@ -334,7 +337,7 @@ impl nlas::Nla for Nla {
334337
CarrierUpCount(_) => IFLA_CARRIER_UP_COUNT,
335338
CarrierDownCount(_) => IFLA_CARRIER_DOWN_COUNT,
336339
NewIfIndex(_) => IFLA_NEW_IFINDEX,
337-
PropList(_) => IFLA_PROP_LIST,
340+
PropList(_) => IFLA_PROP_LIST | NLA_F_NESTED,
338341
ProtoDownReason(_) => IFLA_PROTO_DOWN_REASON,
339342
// Mac address
340343
Address(_) => IFLA_ADDRESS,
@@ -409,7 +412,16 @@ impl<'a, T: AsRef<[u8]> + ?Sized> ParseableParametrized<NlaBuffer<&'a T>, u16> f
409412
IFLA_CARRIER_UP_COUNT => CarrierUpCount(payload.to_vec()),
410413
IFLA_CARRIER_DOWN_COUNT => CarrierDownCount(payload.to_vec()),
411414
IFLA_NEW_IFINDEX => NewIfIndex(payload.to_vec()),
412-
IFLA_PROP_LIST => PropList(payload.to_vec()),
415+
IFLA_PROP_LIST => {
416+
let error_msg = "invalid IFLA_PROP_LIST value";
417+
let mut nlas = vec![];
418+
for nla in NlasIterator::new(payload) {
419+
let nla = &nla.context(error_msg)?;
420+
let parsed = Prop::parse(nla).context(error_msg)?;
421+
nlas.push(parsed);
422+
}
423+
PropList(nlas)
424+
}
413425
IFLA_PROTO_DOWN_REASON => ProtoDownReason(payload.to_vec()),
414426
// HW address (we parse them as Vec for now, because for IP over GRE, the HW address is
415427
// an IP instead of a MAC for example
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::{
2+
constants::*,
3+
nlas::{DefaultNla, Nla, NlaBuffer},
4+
parsers::parse_string,
5+
traits::Parseable,
6+
DecodeError,
7+
};
8+
9+
use anyhow::Context;
10+
11+
#[derive(Debug, PartialEq, Eq, Clone)]
12+
pub enum Prop {
13+
AltIfName(String),
14+
Other(DefaultNla),
15+
}
16+
17+
impl Nla for Prop {
18+
#[rustfmt::skip]
19+
fn value_len(&self) -> usize {
20+
use self::Prop::*;
21+
match self {
22+
AltIfName(ref string) => string.as_bytes().len() + 1,
23+
Other(nla) => nla.value_len()
24+
}
25+
}
26+
27+
#[rustfmt::skip]
28+
fn emit_value(&self, buffer: &mut [u8]) {
29+
use self::Prop::*;
30+
match self {
31+
AltIfName(ref string) => {
32+
buffer[..string.len()].copy_from_slice(string.as_bytes());
33+
buffer[string.len()] = 0;
34+
},
35+
Other(nla) => nla.emit_value(buffer)
36+
}
37+
}
38+
39+
fn kind(&self) -> u16 {
40+
use self::Prop::*;
41+
match self {
42+
AltIfName(_) => IFLA_ALT_IFNAME,
43+
Other(nla) => nla.kind(),
44+
}
45+
}
46+
}
47+
48+
impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Prop {
49+
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
50+
let payload = buf.value();
51+
Ok(match buf.kind() {
52+
IFLA_ALT_IFNAME => {
53+
Prop::AltIfName(parse_string(payload).context("invalid IFLA_ALT_IFNAME value")?)
54+
}
55+
kind => {
56+
Prop::Other(DefaultNla::parse(buf).context(format!("Unknown NLA type {}", kind))?)
57+
}
58+
})
59+
}
60+
}

0 commit comments

Comments
 (0)