1use super::super::AddressFamily;
4use super::RouteError;
5use super::flags::RouteFlags;
6use netlink_packet_utils::DecodeError;
7use netlink_packet_utils::nla::{NlaBuffer, NlaError, NlasIterator};
8use netlink_packet_utils::traits::{Emitable, Parseable};
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 { Ok(Self::from(buf[0])) } else { Err(RouteError::ParseRouteProtocol) }
248 }
249}
250
251impl Emitable for RouteProtocol {
252 fn buffer_len(&self) -> usize {
253 1
254 }
255
256 fn emit(&self, buffer: &mut [u8]) {
257 buffer[0] = u8::from(*self);
258 }
259}
260
261const RT_SCOPE_UNIVERSE: u8 = 0;
262const RT_SCOPE_SITE: u8 = 200;
263const RT_SCOPE_LINK: u8 = 253;
264const RT_SCOPE_HOST: u8 = 254;
265const RT_SCOPE_NOWHERE: u8 = 255;
266
267#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
268#[non_exhaustive]
269pub enum RouteScope {
270 Universe,
271 Site,
272 Link,
273 Host,
274 NoWhere,
275 Other(u8),
276}
277
278impl From<RouteScope> for u8 {
279 fn from(v: RouteScope) -> Self {
280 match v {
281 RouteScope::Universe => RT_SCOPE_UNIVERSE,
282 RouteScope::Site => RT_SCOPE_SITE,
283 RouteScope::Link => RT_SCOPE_LINK,
284 RouteScope::Host => RT_SCOPE_HOST,
285 RouteScope::NoWhere => RT_SCOPE_NOWHERE,
286 RouteScope::Other(s) => s,
287 }
288 }
289}
290
291impl From<u8> for RouteScope {
292 fn from(d: u8) -> Self {
293 match d {
294 RT_SCOPE_UNIVERSE => RouteScope::Universe,
295 RT_SCOPE_SITE => RouteScope::Site,
296 RT_SCOPE_LINK => RouteScope::Link,
297 RT_SCOPE_HOST => RouteScope::Host,
298 RT_SCOPE_NOWHERE => RouteScope::NoWhere,
299 _ => RouteScope::Other(d),
300 }
301 }
302}
303
304impl Default for RouteScope {
305 fn default() -> Self {
306 Self::Universe
307 }
308}
309
310impl std::fmt::Display for RouteScope {
311 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
312 match self {
313 Self::Universe => write!(f, "universe"),
314 Self::Site => write!(f, "site"),
315 Self::Link => write!(f, "link"),
316 Self::Host => write!(f, "host"),
317 Self::NoWhere => write!(f, "no_where"),
318 Self::Other(s) => write!(f, "other({s})"),
319 }
320 }
321}
322
323#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
324#[non_exhaustive]
325pub enum RouteType {
326 Unspec,
328 Unicast,
330 Local,
332 Broadcast,
334 Anycast,
336 Multicast,
338 BlackHole,
340 Unreachable,
342 Prohibit,
344 Throw,
346 Nat,
348 ExternalResolve,
350 Other(u8),
351}
352
353const RTN_UNSPEC: u8 = 0;
354const RTN_UNICAST: u8 = 1;
355const RTN_LOCAL: u8 = 2;
356const RTN_BROADCAST: u8 = 3;
357const RTN_ANYCAST: u8 = 4;
358const RTN_MULTICAST: u8 = 5;
359const RTN_BLACKHOLE: u8 = 6;
360const RTN_UNREACHABLE: u8 = 7;
361const RTN_PROHIBIT: u8 = 8;
362const RTN_THROW: u8 = 9;
363const RTN_NAT: u8 = 10;
364const RTN_XRESOLVE: u8 = 11;
365
366impl From<u8> for RouteType {
367 fn from(d: u8) -> Self {
368 match d {
369 RTN_UNSPEC => Self::Unspec,
370 RTN_UNICAST => Self::Unicast,
371 RTN_LOCAL => Self::Local,
372 RTN_BROADCAST => Self::Broadcast,
373 RTN_ANYCAST => Self::Anycast,
374 RTN_MULTICAST => Self::Multicast,
375 RTN_BLACKHOLE => Self::BlackHole,
376 RTN_UNREACHABLE => Self::Unreachable,
377 RTN_PROHIBIT => Self::Prohibit,
378 RTN_THROW => Self::Throw,
379 RTN_NAT => Self::Nat,
380 RTN_XRESOLVE => Self::ExternalResolve,
381 _ => Self::Other(d),
382 }
383 }
384}
385
386impl Default for RouteType {
387 fn default() -> Self {
388 Self::Unspec
389 }
390}
391
392impl From<RouteType> for u8 {
393 fn from(v: RouteType) -> Self {
394 match v {
395 RouteType::Unspec => RTN_UNSPEC,
396 RouteType::Unicast => RTN_UNICAST,
397 RouteType::Local => RTN_LOCAL,
398 RouteType::Broadcast => RTN_BROADCAST,
399 RouteType::Anycast => RTN_ANYCAST,
400 RouteType::Multicast => RTN_MULTICAST,
401 RouteType::BlackHole => RTN_BLACKHOLE,
402 RouteType::Unreachable => RTN_UNREACHABLE,
403 RouteType::Prohibit => RTN_PROHIBIT,
404 RouteType::Throw => RTN_THROW,
405 RouteType::Nat => RTN_NAT,
406 RouteType::ExternalResolve => RTN_XRESOLVE,
407 RouteType::Other(d) => d,
408 }
409 }
410}