1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::{
conversion::{CopyTo, TryCopyTo},
ffi, Interface, Ip, Result,
};
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 {
fn try_copy_to(&self, pf_pooladdr: &mut ffi::pfvar::pf_pooladdr) -> Result<()> {
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> {
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 unsafe fn to_palist(&self) -> ffi::pfvar::pf_palist {
self.list
}
fn init_pool(pool_addrs: &[PoolAddr]) -> Result<Vec<ffi::pfvar::pf_pooladdr>> {
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 Vec<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 Vec<ffi::pfvar::pf_pooladdr>) -> ffi::pfvar::pf_palist {
let mut list = unsafe { mem::zeroed::<ffi::pfvar::pf_palist>() };
if pool.len() > 0 {
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
}
}