1use super::super::AddressFamily;
4use super::lwtunnel::VecRouteLwTunnelEncap;
5use super::metrics::VecRouteMetric;
6use super::mpls::VecMplsLabel;
7use super::{
8 MplsLabel, RouteAddress, RouteCacheInfo, RouteCacheInfoBuffer, RouteError, RouteLwEnCapType,
9 RouteLwTunnelEncap, RouteMetric, RouteMfcStats, RouteMfcStatsBuffer, RouteMplsTtlPropagation,
10 RouteNextHop, RouteNextHopBuffer, RoutePreference, RouteRealm, RouteType, RouteVia,
11 RouteViaBuffer,
12};
13use byteorder::{ByteOrder, NativeEndian};
14use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
15use netlink_packet_utils::parsers::{parse_u16, parse_u32, parse_u64, parse_u8};
16use netlink_packet_utils::traits::{Emitable, Parseable, ParseableParametrized};
17
18const RTA_DST: u16 = 1;
19const RTA_SRC: u16 = 2;
20const RTA_IIF: u16 = 3;
21const RTA_OIF: u16 = 4;
22const RTA_GATEWAY: u16 = 5;
23const RTA_PRIORITY: u16 = 6;
24const RTA_PREFSRC: u16 = 7;
25const RTA_METRICS: u16 = 8;
26const RTA_MULTIPATH: u16 = 9;
27const RTA_FLOW: u16 = 11;
29const RTA_CACHEINFO: u16 = 12;
30const RTA_TABLE: u16 = 15;
33const RTA_MARK: u16 = 16;
34const RTA_MFC_STATS: u16 = 17;
35const RTA_VIA: u16 = 18;
36const RTA_NEWDST: u16 = 19;
37const RTA_PREF: u16 = 20;
38pub(crate) const RTA_ENCAP_TYPE: u16 = 21;
39const RTA_ENCAP: u16 = 22;
40const RTA_EXPIRES: u16 = 23;
41const RTA_UID: u16 = 25;
42const RTA_TTL_PROPAGATE: u16 = 26;
43#[derive(Debug, PartialEq, Eq, Clone)]
52#[non_exhaustive]
53pub enum RouteAttribute {
54 Metrics(Vec<RouteMetric>),
55 MfcStats(RouteMfcStats),
56 MultiPath(Vec<RouteNextHop>),
57 CacheInfo(RouteCacheInfo),
58 Destination(RouteAddress),
59 Source(RouteAddress),
60 Gateway(RouteAddress),
61 PrefSource(RouteAddress),
62 Via(RouteVia),
63 NewDestination(Vec<MplsLabel>),
65 Preference(RoutePreference),
66 EncapType(RouteLwEnCapType),
67 Encap(Vec<RouteLwTunnelEncap>),
68 Expires(u32),
73 MulticastExpires(u64),
75 Uid(u32),
76 TtlPropagate(RouteMplsTtlPropagation),
77 Iif(u32),
78 Oif(u32),
79 Priority(u32),
80 Realm(RouteRealm),
82 Table(u32),
83 Mark(u32),
84 Other(DefaultNla),
85}
86
87impl Nla for RouteAttribute {
88 fn value_len(&self) -> usize {
89 match self {
90 Self::Destination(addr)
91 | Self::PrefSource(addr)
92 | Self::Gateway(addr)
93 | Self::Source(addr) => addr.buffer_len(),
94 Self::Via(v) => v.buffer_len(),
95 Self::NewDestination(v) => VecMplsLabel(v.clone()).buffer_len(),
96 Self::Encap(v) => v.as_slice().buffer_len(),
97 Self::TtlPropagate(_) => 1,
98 Self::CacheInfo(cache_info) => cache_info.buffer_len(),
99 Self::MfcStats(stats) => stats.buffer_len(),
100 Self::Metrics(metrics) => metrics.as_slice().buffer_len(),
101 Self::MultiPath(next_hops) => next_hops.iter().map(|nh| nh.buffer_len()).sum(),
102 Self::Preference(_) => 1,
103 Self::EncapType(v) => v.buffer_len(),
104 Self::Realm(v) => v.buffer_len(),
105 Self::Uid(_)
106 | Self::Expires(_)
107 | Self::Iif(_)
108 | Self::Oif(_)
109 | Self::Priority(_)
110 | Self::Table(_)
111 | Self::Mark(_) => 4,
112 Self::MulticastExpires(_) => 8,
113 Self::Other(attr) => attr.value_len(),
114 }
115 }
116
117 fn emit_value(&self, buffer: &mut [u8]) {
118 match self {
119 Self::Destination(addr)
120 | Self::PrefSource(addr)
121 | Self::Source(addr)
122 | Self::Gateway(addr) => addr.emit(buffer),
123 Self::Via(v) => v.emit(buffer),
124 Self::NewDestination(v) => VecMplsLabel(v.to_vec()).emit(buffer),
125
126 Self::Encap(nlas) => nlas.as_slice().emit(buffer),
127 Self::TtlPropagate(v) => buffer[0] = u8::from(*v),
128 Self::Preference(p) => buffer[0] = (*p).into(),
129 Self::CacheInfo(cache_info) => cache_info.emit(buffer),
130 Self::MfcStats(stats) => stats.emit(buffer),
131 Self::Metrics(metrics) => metrics.as_slice().emit(buffer),
132 Self::MultiPath(next_hops) => {
133 let mut offset = 0;
134 for nh in next_hops {
135 let len = nh.buffer_len();
136 nh.emit(&mut buffer[offset..offset + len]);
137 offset += len
138 }
139 }
140 Self::EncapType(v) => v.emit(buffer),
141 Self::Uid(value)
142 | Self::Expires(value)
143 | Self::Iif(value)
144 | Self::Oif(value)
145 | Self::Priority(value)
146 | Self::Table(value)
147 | Self::Mark(value) => NativeEndian::write_u32(buffer, *value),
148 Self::Realm(v) => v.emit(buffer),
149 Self::MulticastExpires(value) => NativeEndian::write_u64(buffer, *value),
150 Self::Other(attr) => attr.emit_value(buffer),
151 }
152 }
153
154 fn kind(&self) -> u16 {
155 match self {
156 Self::Destination(_) => RTA_DST,
157 Self::Source(_) => RTA_SRC,
158 Self::Iif(_) => RTA_IIF,
159 Self::Oif(_) => RTA_OIF,
160 Self::Gateway(_) => RTA_GATEWAY,
161 Self::Priority(_) => RTA_PRIORITY,
162 Self::PrefSource(_) => RTA_PREFSRC,
163 Self::Metrics(_) => RTA_METRICS,
164 Self::MultiPath(_) => RTA_MULTIPATH,
165 Self::Realm(_) => RTA_FLOW,
166 Self::CacheInfo(_) => RTA_CACHEINFO,
167 Self::Table(_) => RTA_TABLE,
168 Self::Mark(_) => RTA_MARK,
169 Self::MfcStats(_) => RTA_MFC_STATS,
170 Self::Via(_) => RTA_VIA,
171 Self::NewDestination(_) => RTA_NEWDST,
172 Self::Preference(_) => RTA_PREF,
173 Self::EncapType(_) => RTA_ENCAP_TYPE,
174 Self::Encap(_) => RTA_ENCAP,
175 Self::Expires(_) => RTA_EXPIRES,
176 Self::MulticastExpires(_) => RTA_EXPIRES,
177 Self::Uid(_) => RTA_UID,
178 Self::TtlPropagate(_) => RTA_TTL_PROPAGATE,
179 Self::Other(ref attr) => attr.kind(),
180 }
181 }
182}
183
184impl<'a, T: AsRef<[u8]> + ?Sized>
185 ParseableParametrized<NlaBuffer<&'a T>, (AddressFamily, RouteType, RouteLwEnCapType)>
186 for RouteAttribute
187{
188 type Error = RouteError;
189 fn parse_with_param(
190 buf: &NlaBuffer<&'a T>,
191 (address_family, route_type, encap_type): (AddressFamily, RouteType, RouteLwEnCapType),
192 ) -> Result<Self, RouteError> {
193 let payload = buf.value();
194 Ok(match buf.kind() {
195 RTA_DST => Self::Destination(
196 RouteAddress::parse(address_family, payload)
197 .map_err(|error| RouteError::InvalidValue { kind: "RTA_DST", error })?,
198 ),
199 RTA_SRC => Self::Source(
200 RouteAddress::parse(address_family, payload)
201 .map_err(|error| RouteError::InvalidValue { kind: "RTA_SRC", error })?,
202 ),
203 RTA_GATEWAY => Self::Gateway(
204 RouteAddress::parse(address_family, payload)
205 .map_err(|error| RouteError::InvalidValue { kind: "RTA_GATEWAY", error })?,
206 ),
207 RTA_PREFSRC => Self::PrefSource(
208 RouteAddress::parse(address_family, payload)
209 .map_err(|error| RouteError::InvalidValue { kind: "RTA_PREFSRC", error })?,
210 ),
211 RTA_VIA => Self::Via(
212 RouteVia::parse(
213 &RouteViaBuffer::new_checked(payload)
214 .map_err(|error| RouteError::InvalidValue { kind: "RTA_VIA", error })?,
215 )
216 .map_err(|error| RouteError::InvalidValue { kind: "RTA_VIA", error })?,
217 ),
218 RTA_NEWDST => Self::NewDestination(VecMplsLabel::parse(payload)?.0),
219
220 RTA_PREF => Self::Preference(
221 parse_u8(payload)
222 .map_err(|error| RouteError::InvalidValue { kind: "RTA_PREF", error })?
223 .into(),
224 ),
225 RTA_ENCAP => Self::Encap(VecRouteLwTunnelEncap::parse_with_param(buf, encap_type)?.0),
226 RTA_EXPIRES => {
227 if route_type == RouteType::Multicast {
228 Self::MulticastExpires(parse_u64(payload).map_err(|error| {
229 RouteError::InvalidValue { kind: "RTA_EXPIRES (multicast)", error }
230 })?)
231 } else {
232 Self::Expires(
233 parse_u32(payload).map_err(|error| RouteError::InvalidValue {
234 kind: "RTA_EXPIRES",
235 error,
236 })?,
237 )
238 }
239 }
240 RTA_UID => Self::Uid(
241 parse_u32(payload)
242 .map_err(|error| RouteError::InvalidValue { kind: "RTA_UID", error })?,
243 ),
244 RTA_TTL_PROPAGATE => {
245 Self::TtlPropagate(RouteMplsTtlPropagation::from(parse_u8(payload).map_err(
246 |error| RouteError::InvalidValue { kind: "RTA_TTL_PROPAGATE", error },
247 )?))
248 }
249 RTA_ENCAP_TYPE => Self::EncapType(RouteLwEnCapType::from(
250 parse_u16(payload)
251 .map_err(|error| RouteError::InvalidValue { kind: "RTA_ENCAP_TYPE", error })?,
252 )),
253 RTA_IIF => Self::Iif(
254 parse_u32(payload)
255 .map_err(|error| RouteError::InvalidValue { kind: "RTA_IIF", error })?,
256 ),
257 RTA_OIF => Self::Oif(
258 parse_u32(payload)
259 .map_err(|error| RouteError::InvalidValue { kind: "RTA_OIF", error })?,
260 ),
261 RTA_PRIORITY => Self::Priority(
262 parse_u32(payload)
263 .map_err(|error| RouteError::InvalidValue { kind: "RTA_PRIORITY", error })?,
264 ),
265 RTA_FLOW => Self::Realm(RouteRealm::parse(payload)?),
266 RTA_TABLE => Self::Table(
267 parse_u32(payload)
268 .map_err(|error| RouteError::InvalidValue { kind: "RTA_TABLE", error })?,
269 ),
270 RTA_MARK => Self::Mark(
271 parse_u32(payload)
272 .map_err(|error| RouteError::InvalidValue { kind: "RTA_MARK", error })?,
273 ),
274
275 RTA_CACHEINFO => {
276 Self::CacheInfo(
277 RouteCacheInfo::parse(&RouteCacheInfoBuffer::new_checked(payload).map_err(
278 |error| RouteError::InvalidValue { kind: "RTA_CACHEINFO", error },
279 )?)
280 .map_err(|error| RouteError::InvalidValue { kind: "RTA_CACHEINFO", error })?,
281 )
282 }
283 RTA_MFC_STATS => {
284 Self::MfcStats(
285 RouteMfcStats::parse(&RouteMfcStatsBuffer::new_checked(payload).map_err(
286 |error| RouteError::InvalidValue { kind: "RTA_MFC_STATS", error },
287 )?)
288 .map_err(|error| RouteError::InvalidValue { kind: "RTA_MFC_STATS", error })?,
289 )
290 }
291 RTA_METRICS => Self::Metrics(VecRouteMetric::parse(payload)?.0),
292 RTA_MULTIPATH => {
293 let mut next_hops = vec![];
294 let mut buf = payload;
295 loop {
296 let nh_buf = RouteNextHopBuffer::new_checked(&buf).map_err(|error| {
297 RouteError::InvalidValue { kind: "RTA_MULTIPATH", error }
298 })?;
299 let len = nh_buf.length() as usize;
300 let nh = RouteNextHop::parse_with_param(
301 &nh_buf,
302 (address_family, route_type, encap_type),
303 )?;
304 next_hops.push(nh);
305 if buf.len() == len {
306 break;
307 }
308 buf = &buf[len..];
309 }
310 Self::MultiPath(next_hops)
311 }
312 _ => {
313 Self::Other(DefaultNla::parse(buf).map_err(|error| RouteError::InvalidValue {
314 kind: "NLA (uknown kind)",
315 error,
316 })?)
317 }
318 })
319 }
320}