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 NdMsg {
pub ndm_family: u8,
pub ndm_pad1: u8,
pub ndm_pad2: u16,
pub ndm_ifindex: i32,
pub ndm_state: u16,
pub ndm_flags: u8,
pub ndm_type: u8,
}
impl NdMsg {
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.ndm_family = family;
self
}
pub fn with_ifindex(mut self, ifindex: i32) -> Self {
self.ndm_ifindex = ifindex;
self
}
pub fn with_state(mut self, state: u16) -> Self {
self.ndm_state = state;
self
}
pub fn with_flags(mut self, flags: u8) -> Self {
self.ndm_flags = flags;
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 NdaAttr {
Unspec = 0,
Dst = 1,
Lladdr = 2,
Cacheinfo = 3,
Probes = 4,
Vlan = 5,
Port = 6,
Vni = 7,
Ifindex = 8,
Master = 9,
LinkNetnsid = 10,
SrcVni = 11,
Protocol = 12,
NhId = 13,
FdbExtAttrs = 14,
Flags = 15,
}
impl From<u16> for NdaAttr {
fn from(val: u16) -> Self {
match val {
0 => Self::Unspec,
1 => Self::Dst,
2 => Self::Lladdr,
3 => Self::Cacheinfo,
4 => Self::Probes,
5 => Self::Vlan,
6 => Self::Port,
7 => Self::Vni,
8 => Self::Ifindex,
9 => Self::Master,
10 => Self::LinkNetnsid,
11 => Self::SrcVni,
12 => Self::Protocol,
13 => Self::NhId,
14 => Self::FdbExtAttrs,
15 => Self::Flags,
_ => Self::Unspec,
}
}
}
pub mod nud {
pub const INCOMPLETE: u16 = 0x01;
pub const REACHABLE: u16 = 0x02;
pub const STALE: u16 = 0x04;
pub const DELAY: u16 = 0x08;
pub const PROBE: u16 = 0x10;
pub const FAILED: u16 = 0x20;
pub const NOARP: u16 = 0x40;
pub const PERMANENT: u16 = 0x80;
pub const NONE: u16 = 0x00;
}
pub fn nud_state_name(state: u16) -> &'static str {
match state {
nud::INCOMPLETE => "INCOMPLETE",
nud::REACHABLE => "REACHABLE",
nud::STALE => "STALE",
nud::DELAY => "DELAY",
nud::PROBE => "PROBE",
nud::FAILED => "FAILED",
nud::NOARP => "NOARP",
nud::PERMANENT => "PERMANENT",
nud::NONE => "NONE",
_ => "UNKNOWN",
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
#[non_exhaustive]
pub enum NeighborState {
None = 0x00,
Incomplete = 0x01,
Reachable = 0x02,
Stale = 0x04,
Delay = 0x08,
Probe = 0x10,
Failed = 0x20,
Noarp = 0x40,
Permanent = 0x80,
}
impl From<u16> for NeighborState {
fn from(val: u16) -> Self {
match val {
0x01 => Self::Incomplete,
0x02 => Self::Reachable,
0x04 => Self::Stale,
0x08 => Self::Delay,
0x10 => Self::Probe,
0x20 => Self::Failed,
0x40 => Self::Noarp,
0x80 => Self::Permanent,
_ => Self::None,
}
}
}
impl NeighborState {
pub fn name(&self) -> &'static str {
match self {
Self::None => "NONE",
Self::Incomplete => "INCOMPLETE",
Self::Reachable => "REACHABLE",
Self::Stale => "STALE",
Self::Delay => "DELAY",
Self::Probe => "PROBE",
Self::Failed => "FAILED",
Self::Noarp => "NOARP",
Self::Permanent => "PERMANENT",
}
}
}
pub mod ntf {
pub const USE: u8 = 0x01;
pub const SELF: u8 = 0x02;
pub const MASTER: u8 = 0x04;
pub const PROXY: u8 = 0x08;
pub const EXT_LEARNED: u8 = 0x10;
pub const OFFLOADED: u8 = 0x20;
pub const STICKY: u8 = 0x40;
pub const ROUTER: u8 = 0x80;
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, FromBytes, Immutable, KnownLayout)]
pub struct NdaCacheinfo {
pub ndm_confirmed: u32,
pub ndm_used: u32,
pub ndm_updated: u32,
pub ndm_refcnt: u32,
}
impl NdaCacheinfo {
pub fn from_bytes(data: &[u8]) -> Option<&Self> {
Self::ref_from_prefix(data).map(|(r, _)| r).ok()
}
}