use crate::{
Interface, Ip,
conversion::{CopyTo, TryCopyTo},
ffi,
};
use std::{mem, ptr, vec::Vec};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PoolAddr {
interface: Interface,
ip: Ip,
}
impl PoolAddr {
pub fn new<INTERFACE: Into<Interface>, IP: Into<Ip>>(interface: INTERFACE, ip: IP) -> Self {
PoolAddr {
interface: interface.into(),
ip: ip.into(),
}
}
}
impl From<Interface> for PoolAddr {
fn from(interface: Interface) -> Self {
PoolAddr {
interface,
ip: Ip::Any,
}
}
}
impl From<Ip> for PoolAddr {
fn from(ip: Ip) -> Self {
PoolAddr {
interface: Interface::Any,
ip,
}
}
}
impl TryCopyTo<ffi::pfvar::pf_pooladdr> for PoolAddr {
type Error = crate::Error;
fn try_copy_to(&self, pf_pooladdr: &mut ffi::pfvar::pf_pooladdr) -> Result<(), Self::Error> {
self.interface.try_copy_to(&mut pf_pooladdr.ifname)?;
self.ip.copy_to(&mut pf_pooladdr.addr);
Ok(())
}
}
pub struct PoolAddrList {
list: ffi::pfvar::pf_palist,
_pool: Box<[ffi::pfvar::pf_pooladdr]>,
}
impl PoolAddrList {
pub fn new(pool_addrs: &[PoolAddr]) -> Result<Self, crate::Error> {
let mut pool = Self::init_pool(pool_addrs)?;
Self::link_elements(&mut pool);
let list = Self::create_palist(&mut pool);
Ok(PoolAddrList {
list,
_pool: pool.into_boxed_slice(),
})
}
pub(crate) unsafe fn to_palist(&self) -> ffi::pfvar::pf_palist {
self.list
}
fn init_pool(pool_addrs: &[PoolAddr]) -> Result<Vec<ffi::pfvar::pf_pooladdr>, crate::Error> {
let mut pool = Vec::with_capacity(pool_addrs.len());
for pool_addr in pool_addrs {
let mut pf_pooladdr = unsafe { mem::zeroed::<ffi::pfvar::pf_pooladdr>() };
pool_addr.try_copy_to(&mut pf_pooladdr)?;
pool.push(pf_pooladdr);
}
Ok(pool)
}
fn link_elements(pool: &mut [ffi::pfvar::pf_pooladdr]) {
for i in 1..pool.len() {
let mut elem1 = pool[i - 1];
let mut elem2 = pool[i];
elem1.entries.tqe_next = &mut elem2;
elem2.entries.tqe_prev = &mut elem1.entries.tqe_next;
}
}
fn create_palist(pool: &mut [ffi::pfvar::pf_pooladdr]) -> ffi::pfvar::pf_palist {
let mut list = unsafe { mem::zeroed::<ffi::pfvar::pf_palist>() };
if !pool.is_empty() {
let mut first_elem = pool[0];
let mut last_elem = pool[pool.len() - 1];
list.tqh_first = &mut first_elem;
first_elem.entries.tqe_prev = &mut list.tqh_first;
last_elem.entries.tqe_next = ptr::null_mut();
list.tqh_last = &mut last_elem.entries.tqe_next;
} else {
list.tqh_first = ptr::null_mut();
list.tqh_last = &mut list.tqh_first;
}
list
}
}