use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::netlink::error::{Error, Result};
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, FromBytes, IntoBytes, Immutable, KnownLayout)]
pub struct RtMsg {
pub rtm_family: u8,
pub rtm_dst_len: u8,
pub rtm_src_len: u8,
pub rtm_tos: u8,
pub rtm_table: u8,
pub rtm_protocol: u8,
pub rtm_scope: u8,
pub rtm_type: u8,
pub rtm_flags: u32,
}
impl RtMsg {
pub const SIZE: usize = std::mem::size_of::<Self>();
pub fn new() -> Self {
Self::default()
}
pub fn with_family(mut self, family: u8) -> Self {
self.rtm_family = family;
self
}
pub fn with_dst_len(mut self, len: u8) -> Self {
self.rtm_dst_len = len;
self
}
pub fn with_table(mut self, table: u8) -> Self {
self.rtm_table = table;
self
}
pub fn with_protocol(mut self, protocol: u8) -> Self {
self.rtm_protocol = protocol;
self
}
pub fn with_scope(mut self, scope: u8) -> Self {
self.rtm_scope = scope;
self
}
pub fn with_type(mut self, rtype: u8) -> Self {
self.rtm_type = rtype;
self
}
pub fn as_bytes(&self) -> &[u8] {
<Self as IntoBytes>::as_bytes(self)
}
pub fn from_bytes(data: &[u8]) -> Result<&Self> {
Self::ref_from_prefix(data)
.map(|(r, _)| r)
.map_err(|_| Error::Truncated {
expected: Self::SIZE,
actual: data.len(),
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
#[non_exhaustive]
pub enum RtaAttr {
Unspec = 0,
Dst = 1,
Src = 2,
Iif = 3,
Oif = 4,
Gateway = 5,
Priority = 6,
Prefsrc = 7,
Metrics = 8,
Multipath = 9,
Protoinfo = 10, Flow = 11,
Cacheinfo = 12,
Session = 13, MpAlgo = 14, Table = 15,
Mark = 16,
MfcStats = 17,
Via = 18,
Newdst = 19,
Pref = 20,
EncapType = 21,
Encap = 22,
Expires = 23,
Pad = 24,
Uid = 25,
TtlPropagate = 26,
IpProto = 27,
Sport = 28,
Dport = 29,
NhId = 30,
}
impl From<u16> for RtaAttr {
fn from(val: u16) -> Self {
match val {
0 => Self::Unspec,
1 => Self::Dst,
2 => Self::Src,
3 => Self::Iif,
4 => Self::Oif,
5 => Self::Gateway,
6 => Self::Priority,
7 => Self::Prefsrc,
8 => Self::Metrics,
9 => Self::Multipath,
10 => Self::Protoinfo,
11 => Self::Flow,
12 => Self::Cacheinfo,
15 => Self::Table,
16 => Self::Mark,
17 => Self::MfcStats,
18 => Self::Via,
19 => Self::Newdst,
20 => Self::Pref,
21 => Self::EncapType,
22 => Self::Encap,
23 => Self::Expires,
24 => Self::Pad,
25 => Self::Uid,
26 => Self::TtlPropagate,
27 => Self::IpProto,
28 => Self::Sport,
29 => Self::Dport,
30 => Self::NhId,
_ => Self::Unspec,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[non_exhaustive]
pub enum RouteType {
Unspec = 0,
Unicast = 1,
Local = 2,
Broadcast = 3,
Anycast = 4,
Multicast = 5,
Blackhole = 6,
Unreachable = 7,
Prohibit = 8,
Throw = 9,
Nat = 10,
ExternalResolver = 11,
}
impl From<u8> for RouteType {
fn from(val: u8) -> Self {
match val {
0 => Self::Unspec,
1 => Self::Unicast,
2 => Self::Local,
3 => Self::Broadcast,
4 => Self::Anycast,
5 => Self::Multicast,
6 => Self::Blackhole,
7 => Self::Unreachable,
8 => Self::Prohibit,
9 => Self::Throw,
10 => Self::Nat,
11 => Self::ExternalResolver,
_ => Self::Unspec,
}
}
}
impl RouteType {
pub fn name(&self) -> &'static str {
match self {
Self::Unspec => "unspec",
Self::Unicast => "unicast",
Self::Local => "local",
Self::Broadcast => "broadcast",
Self::Anycast => "anycast",
Self::Multicast => "multicast",
Self::Blackhole => "blackhole",
Self::Unreachable => "unreachable",
Self::Prohibit => "prohibit",
Self::Throw => "throw",
Self::Nat => "nat",
Self::ExternalResolver => "xresolve",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[non_exhaustive]
pub enum RouteProtocol {
Unspec = 0,
Redirect = 1,
Kernel = 2,
Boot = 3,
Static = 4,
Gated = 8,
Ra = 9,
Mrt = 10,
Zebra = 11,
Bird = 12,
Dnrouted = 13,
Xorp = 14,
Ntk = 15,
Dhcp = 16,
Mrouted = 17,
Keepalived = 18,
Babel = 42,
Bgp = 186,
Isis = 187,
Ospf = 188,
Rip = 189,
Eigrp = 192,
}
impl From<u8> for RouteProtocol {
fn from(val: u8) -> Self {
match val {
0 => Self::Unspec,
1 => Self::Redirect,
2 => Self::Kernel,
3 => Self::Boot,
4 => Self::Static,
8 => Self::Gated,
9 => Self::Ra,
10 => Self::Mrt,
11 => Self::Zebra,
12 => Self::Bird,
13 => Self::Dnrouted,
14 => Self::Xorp,
15 => Self::Ntk,
16 => Self::Dhcp,
17 => Self::Mrouted,
18 => Self::Keepalived,
42 => Self::Babel,
186 => Self::Bgp,
187 => Self::Isis,
188 => Self::Ospf,
189 => Self::Rip,
192 => Self::Eigrp,
_ => Self::Unspec,
}
}
}
impl RouteProtocol {
pub fn name(&self) -> &'static str {
match self {
Self::Unspec => "unspec",
Self::Redirect => "redirect",
Self::Kernel => "kernel",
Self::Boot => "boot",
Self::Static => "static",
Self::Gated => "gated",
Self::Ra => "ra",
Self::Mrt => "mrt",
Self::Zebra => "zebra",
Self::Bird => "bird",
Self::Dnrouted => "dnrouted",
Self::Xorp => "xorp",
Self::Ntk => "ntk",
Self::Dhcp => "dhcp",
Self::Mrouted => "mrouted",
Self::Keepalived => "keepalived",
Self::Babel => "babel",
Self::Bgp => "bgp",
Self::Isis => "isis",
Self::Ospf => "ospf",
Self::Rip => "rip",
Self::Eigrp => "eigrp",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[non_exhaustive]
pub enum RouteScope {
Universe = 0,
Site = 200,
Link = 253,
Host = 254,
Nowhere = 255,
}
impl From<u8> for RouteScope {
fn from(val: u8) -> Self {
match val {
0 => Self::Universe,
200 => Self::Site,
253 => Self::Link,
254 => Self::Host,
255 => Self::Nowhere,
_ => Self::Universe,
}
}
}
impl RouteScope {
pub fn name(&self) -> &'static str {
match self {
Self::Universe => "global",
Self::Site => "site",
Self::Link => "link",
Self::Host => "host",
Self::Nowhere => "nowhere",
}
}
pub fn from_name(name: &str) -> Option<Self> {
match name.to_lowercase().as_str() {
"global" | "universe" => Some(Self::Universe),
"site" => Some(Self::Site),
"link" => Some(Self::Link),
"host" => Some(Self::Host),
"nowhere" => Some(Self::Nowhere),
_ => None,
}
}
}
pub mod rt_table {
pub const UNSPEC: u8 = 0;
pub const COMPAT: u8 = 252;
pub const DEFAULT: u8 = 253;
pub const MAIN: u8 = 254;
pub const LOCAL: u8 = 255;
}
pub mod rtm_flags {
pub const NOTIFY: u32 = 0x100;
pub const CLONED: u32 = 0x200;
pub const EQUALIZE: u32 = 0x400;
pub const PREFIX: u32 = 0x800;
pub const LOOKUP_TABLE: u32 = 0x1000;
pub const FIB_MATCH: u32 = 0x2000;
pub const OFFLOAD: u32 = 0x4000;
pub const TRAP: u32 = 0x8000;
pub const OFFLOAD_FAILED: u32 = 0x20000000;
}