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 IfAddrMsg {
pub ifa_family: u8,
pub ifa_prefixlen: u8,
pub ifa_flags: u8,
pub ifa_scope: u8,
pub ifa_index: u32,
}
impl IfAddrMsg {
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.ifa_family = family;
self
}
pub fn with_prefixlen(mut self, prefixlen: u8) -> Self {
self.ifa_prefixlen = prefixlen;
self
}
pub fn with_index(mut self, index: u32) -> Self {
self.ifa_index = index;
self
}
pub fn with_scope(mut self, scope: u8) -> Self {
self.ifa_scope = scope;
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 IfaAttr {
Unspec = 0,
Address = 1,
Local = 2,
Label = 3,
Broadcast = 4,
Anycast = 5,
Cacheinfo = 6,
Multicast = 7,
Flags = 8,
RtPriority = 9,
TargetNetnsid = 10,
Proto = 11,
}
impl From<u16> for IfaAttr {
fn from(val: u16) -> Self {
match val {
0 => Self::Unspec,
1 => Self::Address,
2 => Self::Local,
3 => Self::Label,
4 => Self::Broadcast,
5 => Self::Anycast,
6 => Self::Cacheinfo,
7 => Self::Multicast,
8 => Self::Flags,
9 => Self::RtPriority,
10 => Self::TargetNetnsid,
11 => Self::Proto,
_ => Self::Unspec,
}
}
}
pub mod ifa_flags {
pub const SECONDARY: u32 = 0x01;
pub const TEMPORARY: u32 = 0x01; pub const NODAD: u32 = 0x02;
pub const OPTIMISTIC: u32 = 0x04;
pub const DADFAILED: u32 = 0x08;
pub const HOMEADDRESS: u32 = 0x10;
pub const DEPRECATED: u32 = 0x20;
pub const TENTATIVE: u32 = 0x40;
pub const PERMANENT: u32 = 0x80;
pub const MANAGETEMPADDR: u32 = 0x100;
pub const NOPREFIXROUTE: u32 = 0x200;
pub const MCAUTOJOIN: u32 = 0x400;
pub const STABLE_PRIVACY: u32 = 0x800;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[non_exhaustive]
pub enum Scope {
Universe = 0,
Site = 200,
Link = 253,
Host = 254,
Nowhere = 255,
}
impl From<u8> for Scope {
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 Scope {
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,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, FromBytes, Immutable, KnownLayout)]
pub struct IfaCacheinfo {
pub ifa_prefered: u32,
pub ifa_valid: u32,
pub cstamp: u32,
pub tstamp: u32,
}
impl IfaCacheinfo {
pub fn from_bytes(data: &[u8]) -> Option<&Self> {
Self::ref_from_prefix(data).map(|(r, _)| r).ok()
}
}