netlink_packet_route/rtnl/rule/nlas/
mod.rs1use crate::{
4 nlas,
5 nlas::DefaultNla,
6 utils::{
7 byteorder::{ByteOrder, NativeEndian},
8 nla::NlaBuffer,
9 parsers::{parse_string, parse_u32, parse_u8},
10 Parseable,
11 },
12 DecodeError,
13 FRA_DPORT_RANGE,
14 FRA_DST,
15 FRA_FLOW,
16 FRA_FWMARK,
17 FRA_FWMASK,
18 FRA_GOTO,
19 FRA_IIFNAME,
20 FRA_IP_PROTO,
21 FRA_L3MDEV,
22 FRA_OIFNAME,
23 FRA_PAD,
24 FRA_PRIORITY,
25 FRA_PROTOCOL,
26 FRA_SPORT_RANGE,
27 FRA_SRC,
28 FRA_SUPPRESS_IFGROUP,
29 FRA_SUPPRESS_PREFIXLEN,
30 FRA_TABLE,
31 FRA_TUN_ID,
32 FRA_UID_RANGE,
33 FRA_UNSPEC,
34};
35use anyhow::Context;
36
37#[derive(Debug, PartialEq, Eq, Clone)]
38pub enum Nla {
39 Unspec(Vec<u8>),
40 Destination(Vec<u8>),
42 Source(Vec<u8>),
44 Iifname(String),
46 Goto(u32),
48 Priority(u32),
49 FwMark(u32),
50 FwMask(u32),
51 Flow(u32),
53 TunId(u32),
54 SuppressIfGroup(u32),
55 SuppressPrefixLen(u32),
56 Table(u32),
57 OifName(String),
59 Pad(Vec<u8>),
60 L3MDev(u8),
62 UidRange(Vec<u8>),
63 Protocol(u8),
65 IpProto(u8),
67 SourcePortRange(Vec<u8>),
68 DestinationPortRange(Vec<u8>),
69 Other(DefaultNla),
70}
71
72impl nlas::Nla for Nla {
73 fn value_len(&self) -> usize {
74 use self::Nla::*;
75 match self {
76 Unspec(ref bytes)
77 | Destination(ref bytes)
78 | Source(ref bytes)
79 | Pad(ref bytes)
80 | UidRange(ref bytes)
81 | SourcePortRange(ref bytes)
82 | DestinationPortRange(ref bytes) => bytes.len(),
83 Iifname(ref s) | OifName(ref s) => s.as_bytes().len() + 1,
84 Priority(_) | FwMark(_) | FwMask(_) | Flow(_) | TunId(_) | Goto(_)
85 | SuppressIfGroup(_) | SuppressPrefixLen(_) | Table(_) => 4,
86 L3MDev(_) | Protocol(_) | IpProto(_) => 1,
87 Other(attr) => attr.value_len(),
88 }
89 }
90
91 fn kind(&self) -> u16 {
92 use self::Nla::*;
93 match self {
94 Unspec(_) => FRA_UNSPEC,
95 Destination(_) => FRA_DST,
96 Source(_) => FRA_SRC,
97 Iifname(_) => FRA_IIFNAME,
98 Goto(_) => FRA_GOTO,
99 Priority(_) => FRA_PRIORITY,
100 FwMark(_) => FRA_FWMARK,
101 FwMask(_) => FRA_FWMASK,
102 Flow(_) => FRA_FLOW,
103 TunId(_) => FRA_TUN_ID,
104 SuppressIfGroup(_) => FRA_SUPPRESS_IFGROUP,
105 SuppressPrefixLen(_) => FRA_SUPPRESS_PREFIXLEN,
106 Table(_) => FRA_TABLE,
107 OifName(_) => FRA_OIFNAME,
108 Pad(_) => FRA_PAD,
109 L3MDev(_) => FRA_L3MDEV,
110 UidRange(_) => FRA_UID_RANGE,
111 Protocol(_) => FRA_PROTOCOL,
112 IpProto(_) => FRA_IP_PROTO,
113 SourcePortRange(_) => FRA_SPORT_RANGE,
114 DestinationPortRange(_) => FRA_DPORT_RANGE,
115 Other(attr) => attr.kind(),
116 }
117 }
118
119 fn emit_value(&self, buffer: &mut [u8]) {
120 use self::Nla::*;
121 match self {
122 Unspec(ref bytes)
123 | Destination(ref bytes)
124 | Source(ref bytes)
125 | Pad(ref bytes)
126 | UidRange(ref bytes)
127 | SourcePortRange(ref bytes)
128 | DestinationPortRange(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
129 Iifname(ref s) | OifName(ref s) => buffer.copy_from_slice(s.as_bytes()),
130
131 Priority(value)
132 | FwMark(value)
133 | FwMask(value)
134 | Flow(value)
135 | TunId(value)
136 | Goto(value)
137 | SuppressIfGroup(value)
138 | SuppressPrefixLen(value)
139 | Table(value) => NativeEndian::write_u32(buffer, *value),
140 L3MDev(value) | Protocol(value) | IpProto(value) => buffer[0] = *value,
141 Other(attr) => attr.emit_value(buffer),
142 }
143 }
144}
145
146impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nla {
147 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
148 use Nla::*;
149
150 let payload = buf.value();
151
152 Ok(match buf.kind() {
153 FRA_UNSPEC => Unspec(payload.to_vec()),
154 FRA_DST => Destination(payload.to_vec()),
155 FRA_SRC => Source(payload.to_vec()),
156 FRA_IIFNAME => Iifname(parse_string(payload).context("invalid FRA_IIFNAME value")?),
157 FRA_GOTO => Goto(parse_u32(payload).context("invalid FRA_GOTO value")?),
158 FRA_PRIORITY => Priority(parse_u32(payload).context("invalid FRA_PRIORITY value")?),
159 FRA_FWMARK => FwMark(parse_u32(payload).context("invalid FRA_FWMARK value")?),
160 FRA_FLOW => Flow(parse_u32(payload).context("invalid FRA_FLOW value")?),
161 FRA_TUN_ID => TunId(parse_u32(payload).context("invalid FRA_TUN_ID value")?),
162 FRA_SUPPRESS_IFGROUP => {
163 SuppressIfGroup(parse_u32(payload).context("invalid FRA_SUPPRESS_IFGROUP value")?)
164 }
165 FRA_SUPPRESS_PREFIXLEN => SuppressPrefixLen(
166 parse_u32(payload).context("invalid FRA_SUPPRESS_PREFIXLEN value")?,
167 ),
168 FRA_TABLE => Table(parse_u32(payload).context("invalid FRA_TABLE value")?),
169 FRA_FWMASK => FwMask(parse_u32(payload).context("invalid FRA_FWMASK value")?),
170 FRA_OIFNAME => OifName(parse_string(payload).context("invalid FRA_OIFNAME value")?),
171 FRA_PAD => Pad(payload.to_vec()),
172 FRA_L3MDEV => L3MDev(parse_u8(payload).context("invalid FRA_L3MDEV value")?),
173 FRA_UID_RANGE => UidRange(payload.to_vec()),
174 FRA_PROTOCOL => Protocol(parse_u8(payload).context("invalid FRA_PROTOCOL value")?),
175 FRA_IP_PROTO => IpProto(parse_u8(payload).context("invalid FRA_IP_PROTO value")?),
176 FRA_SPORT_RANGE => SourcePortRange(payload.to_vec()),
177 FRA_DPORT_RANGE => DestinationPortRange(payload.to_vec()),
178 _ => Other(DefaultNla::parse(buf).context("invalid NLA (unknown kind)")?),
179 })
180 }
181}