1use super::super::AddressFamily;
4use super::flags::RouteFlags;
5use super::RouteError;
6use netlink_packet_utils::nla::{NlaBuffer, NlaError, NlasIterator};
7use netlink_packet_utils::traits::{Emitable, Parseable};
8use netlink_packet_utils::DecodeError;
9
10const ROUTE_HEADER_LEN: usize = 12;
11
12buffer!(RouteMessageBuffer(ROUTE_HEADER_LEN) {
13 address_family: (u8, 0),
14 destination_prefix_length: (u8, 1),
15 source_prefix_length: (u8, 2),
16 tos: (u8, 3),
17 table: (u8, 4),
18 protocol: (u8, 5),
19 scope: (u8, 6),
20 kind: (u8, 7),
21 flags: (u32, 8..ROUTE_HEADER_LEN),
22 payload: (slice, ROUTE_HEADER_LEN..),
23});
24
25impl<'a, T: AsRef<[u8]> + ?Sized> RouteMessageBuffer<&'a T> {
26 pub fn attributes(&self) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, NlaError>> {
27 NlasIterator::new(self.payload())
28 }
29}
30
31#[derive(Debug, PartialEq, Eq, Clone, Default, Hash)]
34pub struct RouteHeader {
35 pub address_family: AddressFamily,
38 pub destination_prefix_length: u8,
40 pub source_prefix_length: u8,
42 pub tos: u8,
44 pub table: u8,
46 pub protocol: RouteProtocol,
48 pub scope: RouteScope,
50 pub kind: RouteType,
52 pub flags: RouteFlags,
54}
55
56impl RouteHeader {
57 pub const RT_TABLE_MAIN: u8 = 254;
58 pub const RT_TABLE_UNSPEC: u8 = 0;
59}
60
61impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<RouteMessageBuffer<&'a T>> for RouteHeader {
62 type Error = ();
63 fn parse(buf: &RouteMessageBuffer<&'a T>) -> Result<Self, ()> {
64 Ok(RouteHeader {
65 address_family: buf.address_family().into(),
66 destination_prefix_length: buf.destination_prefix_length(),
67 source_prefix_length: buf.source_prefix_length(),
68 tos: buf.tos(),
69 table: buf.table(),
70 protocol: buf.protocol().into(),
71 scope: buf.scope().into(),
72 kind: buf.kind().into(),
73 flags: RouteFlags::from_bits_retain(buf.flags()),
74 })
75 }
76}
77
78impl Emitable for RouteHeader {
79 fn buffer_len(&self) -> usize {
80 ROUTE_HEADER_LEN
81 }
82
83 fn emit(&self, buffer: &mut [u8]) {
84 let mut buffer = RouteMessageBuffer::new(buffer);
85 buffer.set_address_family(self.address_family.into());
86 buffer.set_destination_prefix_length(self.destination_prefix_length);
87 buffer.set_source_prefix_length(self.source_prefix_length);
88 buffer.set_tos(self.tos);
89 buffer.set_table(self.table);
90 buffer.set_protocol(self.protocol.into());
91 buffer.set_scope(self.scope.into());
92 buffer.set_kind(self.kind.into());
93 buffer.set_flags(self.flags.bits());
94 }
95}
96
97#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
98#[non_exhaustive]
99pub enum RouteProtocol {
100 Unspec,
101 IcmpRedirect,
102 Kernel,
103 Boot,
104 Static,
105 Gated,
106 Ra,
107 Mrt,
108 Zebra,
109 Bird,
110 DnRouted,
111 Xorp,
112 Ntk,
113 Dhcp,
114 Mrouted,
115 KeepAlived,
116 Babel,
117 Bgp,
118 Isis,
119 Ospf,
120 Rip,
121 Eigrp,
122 Other(u8),
123}
124
125const RTPROT_UNSPEC: u8 = 0;
126const RTPROT_REDIRECT: u8 = 1;
127const RTPROT_KERNEL: u8 = 2;
128const RTPROT_BOOT: u8 = 3;
129const RTPROT_STATIC: u8 = 4;
130const RTPROT_GATED: u8 = 8;
131const RTPROT_RA: u8 = 9;
132const RTPROT_MRT: u8 = 10;
133const RTPROT_ZEBRA: u8 = 11;
134const RTPROT_BIRD: u8 = 12;
135const RTPROT_DNROUTED: u8 = 13;
136const RTPROT_XORP: u8 = 14;
137const RTPROT_NTK: u8 = 15;
138const RTPROT_DHCP: u8 = 16;
139const RTPROT_MROUTED: u8 = 17;
140const RTPROT_KEEPALIVED: u8 = 18;
141const RTPROT_BABEL: u8 = 42;
142const RTPROT_BGP: u8 = 186;
143const RTPROT_ISIS: u8 = 187;
144const RTPROT_OSPF: u8 = 188;
145const RTPROT_RIP: u8 = 189;
146const RTPROT_EIGRP: u8 = 192;
147
148impl From<RouteProtocol> for u8 {
149 fn from(t: RouteProtocol) -> u8 {
150 match t {
151 RouteProtocol::Unspec => RTPROT_UNSPEC,
152 RouteProtocol::IcmpRedirect => RTPROT_REDIRECT,
153 RouteProtocol::Kernel => RTPROT_KERNEL,
154 RouteProtocol::Boot => RTPROT_BOOT,
155 RouteProtocol::Static => RTPROT_STATIC,
156 RouteProtocol::Gated => RTPROT_GATED,
157 RouteProtocol::Ra => RTPROT_RA,
158 RouteProtocol::Mrt => RTPROT_MRT,
159 RouteProtocol::Zebra => RTPROT_ZEBRA,
160 RouteProtocol::Bird => RTPROT_BIRD,
161 RouteProtocol::DnRouted => RTPROT_DNROUTED,
162 RouteProtocol::Xorp => RTPROT_XORP,
163 RouteProtocol::Ntk => RTPROT_NTK,
164 RouteProtocol::Dhcp => RTPROT_DHCP,
165 RouteProtocol::Mrouted => RTPROT_MROUTED,
166 RouteProtocol::KeepAlived => RTPROT_KEEPALIVED,
167 RouteProtocol::Babel => RTPROT_BABEL,
168 RouteProtocol::Bgp => RTPROT_BGP,
169 RouteProtocol::Isis => RTPROT_ISIS,
170 RouteProtocol::Ospf => RTPROT_OSPF,
171 RouteProtocol::Rip => RTPROT_RIP,
172 RouteProtocol::Eigrp => RTPROT_EIGRP,
173 RouteProtocol::Other(d) => d,
174 }
175 }
176}
177
178impl From<u8> for RouteProtocol {
179 fn from(d: u8) -> Self {
180 match d {
181 RTPROT_UNSPEC => RouteProtocol::Unspec,
182 RTPROT_REDIRECT => RouteProtocol::IcmpRedirect,
183 RTPROT_KERNEL => RouteProtocol::Kernel,
184 RTPROT_BOOT => RouteProtocol::Boot,
185 RTPROT_STATIC => RouteProtocol::Static,
186 RTPROT_GATED => RouteProtocol::Gated,
187 RTPROT_RA => RouteProtocol::Ra,
188 RTPROT_MRT => RouteProtocol::Mrt,
189 RTPROT_ZEBRA => RouteProtocol::Zebra,
190 RTPROT_BIRD => RouteProtocol::Bird,
191 RTPROT_DNROUTED => RouteProtocol::DnRouted,
192 RTPROT_XORP => RouteProtocol::Xorp,
193 RTPROT_NTK => RouteProtocol::Ntk,
194 RTPROT_DHCP => RouteProtocol::Dhcp,
195 RTPROT_MROUTED => RouteProtocol::Mrouted,
196 RTPROT_KEEPALIVED => RouteProtocol::KeepAlived,
197 RTPROT_BABEL => RouteProtocol::Babel,
198 RTPROT_BGP => RouteProtocol::Bgp,
199 RTPROT_ISIS => RouteProtocol::Isis,
200 RTPROT_OSPF => RouteProtocol::Ospf,
201 RTPROT_RIP => RouteProtocol::Rip,
202 RTPROT_EIGRP => RouteProtocol::Eigrp,
203 _ => RouteProtocol::Other(d),
204 }
205 }
206}
207
208impl std::fmt::Display for RouteProtocol {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 match self {
211 Self::Unspec => write!(f, "unspec"),
212 Self::IcmpRedirect => write!(f, "icmp_redirect"),
213 Self::Kernel => write!(f, "kernel"),
214 Self::Boot => write!(f, "boot"),
215 Self::Static => write!(f, "static"),
216 Self::Gated => write!(f, "gated"),
217 Self::Ra => write!(f, "ra"),
218 Self::Mrt => write!(f, "merit_mrt"),
219 Self::Zebra => write!(f, "zebra"),
220 Self::Bird => write!(f, "bird"),
221 Self::DnRouted => write!(f, "decnet_routing_daemon"),
222 Self::Xorp => write!(f, "xorp"),
223 Self::Ntk => write!(f, "netsukuku"),
224 Self::Dhcp => write!(f, "Dhcp"),
225 Self::Mrouted => write!(f, "multicast_daemon"),
226 Self::KeepAlived => write!(f, "keepalived_daemon"),
227 Self::Babel => write!(f, "babel"),
228 Self::Bgp => write!(f, "bgp"),
229 Self::Isis => write!(f, "isis"),
230 Self::Ospf => write!(f, "ospf"),
231 Self::Rip => write!(f, "rip"),
232 Self::Eigrp => write!(f, "eigrp"),
233 Self::Other(v) => write!(f, "other({v})"),
234 }
235 }
236}
237
238impl Default for RouteProtocol {
239 fn default() -> Self {
240 Self::Unspec
241 }
242}
243
244impl Parseable<[u8]> for RouteProtocol {
245 type Error = RouteError;
246 fn parse(buf: &[u8]) -> Result<Self, RouteError> {
247 if buf.len() == 1 {
248 Ok(Self::from(buf[0]))
249 } else {
250 Err(RouteError::ParseRouteProtocol)
251 }
252 }
253}
254
255impl Emitable for RouteProtocol {
256 fn buffer_len(&self) -> usize {
257 1
258 }
259
260 fn emit(&self, buffer: &mut [u8]) {
261 buffer[0] = u8::from(*self);
262 }
263}
264
265const RT_SCOPE_UNIVERSE: u8 = 0;
266const RT_SCOPE_SITE: u8 = 200;
267const RT_SCOPE_LINK: u8 = 253;
268const RT_SCOPE_HOST: u8 = 254;
269const RT_SCOPE_NOWHERE: u8 = 255;
270
271#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
272#[non_exhaustive]
273pub enum RouteScope {
274 Universe,
275 Site,
276 Link,
277 Host,
278 NoWhere,
279 Other(u8),
280}
281
282impl From<RouteScope> for u8 {
283 fn from(v: RouteScope) -> Self {
284 match v {
285 RouteScope::Universe => RT_SCOPE_UNIVERSE,
286 RouteScope::Site => RT_SCOPE_SITE,
287 RouteScope::Link => RT_SCOPE_LINK,
288 RouteScope::Host => RT_SCOPE_HOST,
289 RouteScope::NoWhere => RT_SCOPE_NOWHERE,
290 RouteScope::Other(s) => s,
291 }
292 }
293}
294
295impl From<u8> for RouteScope {
296 fn from(d: u8) -> Self {
297 match d {
298 RT_SCOPE_UNIVERSE => RouteScope::Universe,
299 RT_SCOPE_SITE => RouteScope::Site,
300 RT_SCOPE_LINK => RouteScope::Link,
301 RT_SCOPE_HOST => RouteScope::Host,
302 RT_SCOPE_NOWHERE => RouteScope::NoWhere,
303 _ => RouteScope::Other(d),
304 }
305 }
306}
307
308impl Default for RouteScope {
309 fn default() -> Self {
310 Self::Universe
311 }
312}
313
314impl std::fmt::Display for RouteScope {
315 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
316 match self {
317 Self::Universe => write!(f, "universe"),
318 Self::Site => write!(f, "site"),
319 Self::Link => write!(f, "link"),
320 Self::Host => write!(f, "host"),
321 Self::NoWhere => write!(f, "no_where"),
322 Self::Other(s) => write!(f, "other({s})"),
323 }
324 }
325}
326
327#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
328#[non_exhaustive]
329pub enum RouteType {
330 Unspec,
332 Unicast,
334 Local,
336 Broadcast,
338 Anycast,
340 Multicast,
342 BlackHole,
344 Unreachable,
346 Prohibit,
348 Throw,
350 Nat,
352 ExternalResolve,
354 Other(u8),
355}
356
357const RTN_UNSPEC: u8 = 0;
358const RTN_UNICAST: u8 = 1;
359const RTN_LOCAL: u8 = 2;
360const RTN_BROADCAST: u8 = 3;
361const RTN_ANYCAST: u8 = 4;
362const RTN_MULTICAST: u8 = 5;
363const RTN_BLACKHOLE: u8 = 6;
364const RTN_UNREACHABLE: u8 = 7;
365const RTN_PROHIBIT: u8 = 8;
366const RTN_THROW: u8 = 9;
367const RTN_NAT: u8 = 10;
368const RTN_XRESOLVE: u8 = 11;
369
370impl From<u8> for RouteType {
371 fn from(d: u8) -> Self {
372 match d {
373 RTN_UNSPEC => Self::Unspec,
374 RTN_UNICAST => Self::Unicast,
375 RTN_LOCAL => Self::Local,
376 RTN_BROADCAST => Self::Broadcast,
377 RTN_ANYCAST => Self::Anycast,
378 RTN_MULTICAST => Self::Multicast,
379 RTN_BLACKHOLE => Self::BlackHole,
380 RTN_UNREACHABLE => Self::Unreachable,
381 RTN_PROHIBIT => Self::Prohibit,
382 RTN_THROW => Self::Throw,
383 RTN_NAT => Self::Nat,
384 RTN_XRESOLVE => Self::ExternalResolve,
385 _ => Self::Other(d),
386 }
387 }
388}
389
390impl Default for RouteType {
391 fn default() -> Self {
392 Self::Unspec
393 }
394}
395
396impl From<RouteType> for u8 {
397 fn from(v: RouteType) -> Self {
398 match v {
399 RouteType::Unspec => RTN_UNSPEC,
400 RouteType::Unicast => RTN_UNICAST,
401 RouteType::Local => RTN_LOCAL,
402 RouteType::Broadcast => RTN_BROADCAST,
403 RouteType::Anycast => RTN_ANYCAST,
404 RouteType::Multicast => RTN_MULTICAST,
405 RouteType::BlackHole => RTN_BLACKHOLE,
406 RouteType::Unreachable => RTN_UNREACHABLE,
407 RouteType::Prohibit => RTN_PROHIBIT,
408 RouteType::Throw => RTN_THROW,
409 RouteType::Nat => RTN_NAT,
410 RouteType::ExternalResolve => RTN_XRESOLVE,
411 RouteType::Other(d) => d,
412 }
413 }
414}