Skip to content

Commit

Permalink
Save current progress
Browse files Browse the repository at this point in the history
  • Loading branch information
alvinpeters committed Jun 19, 2024
1 parent 4e5cea9 commit c7922d5
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 32 deletions.
3 changes: 2 additions & 1 deletion generate_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,16 @@ freebsd() {
bindgen \
--allowlist-type pf_status \
--allowlist-type pfioc_rule \
--allowlist-type pfioc_ruleset \
--allowlist-type pfioc_pooladdr \
--allowlist-type pfioc_trans \
--allowlist-type pfioc_states \
--allowlist-type pfioc_state_kill \
--allowlist-type pfsync_state_1301 \
--allowlist-var PF_.* \
--allowlist-var PFRULE_.* \
--default-enum-style rust \
-o "${output}" "${input}"
rm "${input}"
echo "pfvar.h bindings for FreeBSD has been generated at: ${output}"
}

Expand Down
11 changes: 7 additions & 4 deletions src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,18 @@ ioctl_readwrite!(pf_begin_addrs, b'D', 51, pfvar::pfioc_pooladdr);
// DIOCADDADDR
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
ioctl_readwrite!(pf_add_addr, b'D', 52, pfvar::pfioc_pooladdr);


// DIOCGETRULESETS
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
ioctl_readwrite!(pf_get_rulesets, b'D', 58, pfvar::pfioc_ruleset);
// DIOCGETRULESET
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
ioctl_readwrite!(pf_get_ruleset, b'D', 59, pfvar::pfioc_ruleset);
// DIOCXBEGIN
ioctl_readwrite!(pf_begin_trans, b'D', 81, pfvar::pfioc_trans);
// DIOCXCOMMIT
ioctl_readwrite!(pf_commit_trans, b'D', 82, pfvar::pfioc_trans);

// DIOCXEND
// Required by OpenBSD to release the ticket obtained by the DIOCGETRULES command.
// TODO: Switch to openbsd before push
#[cfg(any(target_os = "macos"))]
#[cfg(any(target_os = "openbsd"))]
ioctl_readwrite!(pf_end_trans, b'D', 100, pfvar::u_int32_t);
70 changes: 44 additions & 26 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,13 @@ impl PfCtl {
let mut pfioc_rule = unsafe { mem::zeroed::<ffi::pfvar::pfioc_rule>() };
#[cfg(target_os = "macos")] {
pfioc_rule.rule.action = kind.into();
name.try_copy_to(&mut pfioc_rule.anchor_call[..])
.chain_err(|| ErrorKind::InvalidArgument("Invalid anchor name"))?;
ioctl_guard!(ffi::pf_insert_rule(self.fd(), &mut pfioc_rule))?;
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))] {
anchor_rule.ticket = utils::get_ticket(
self.fd(),
name,
)?;
anchor_rule.rule.action = ffi::pfvar::PF_CHANGE_REMOVE as u32;
ioctl_guard!(ffi::pf_change_rule(self.fd(), &mut pfioc_rule))
pfioc_rule.rule.action = ffi::pfvar::PF_CHANGE_REMOVE as u8;
}
name.try_copy_to(&mut pfioc_rule.anchor_call[..])
.chain_err(|| ErrorKind::InvalidArgument("Invalid anchor name"))?;
ioctl_guard!(ffi::pf_insert_rule(self.fd(), &mut pfioc_rule))?;
Ok(())
}

Expand All @@ -236,15 +231,16 @@ impl PfCtl {
kind: AnchorKind
) -> Result<()> {
self.with_anchor_rule(name, kind, |mut anchor_rule| {
#[cfg(target_os = "macos")]
return ioctl_guard!(ffi::pf_delete_rule(self.fd(), &mut anchor_rule));
#[cfg(target_os = "macos")] {
ioctl_guard!(ffi::pf_delete_rule(self.fd(), &mut anchor_rule))
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))] {
anchor_rule.ticket = utils::get_ticket(
self.fd(),
name,
)?;
anchor_rule.rule.action = ffi::pfvar::PF_CHANGE_REMOVE as u32;
ioctl_guard!(ffi::pf_change_rule(self.fd(), &mut pfioc_rule))
anchor_rule.rule.action = ffi::pfvar::PF_CHANGE_REMOVE as u8;
ioctl_guard!(ffi::pf_change_rule(self.fd(), &mut anchor_rule))
}

})
Expand All @@ -259,7 +255,10 @@ impl PfCtl {
kind: AnchorKind
) -> Result<()> {
ignore_error_kind!(
self.remove_anchor(name, kind),
self.remove_anchor(name,
#[cfg(target_os = "macos")]
kind
),
ErrorKind::AnchorDoesNotExist
)
}
Expand All @@ -286,7 +285,7 @@ impl PfCtl {
pfioc_rule.action = ffi::pfvar::PF_CHANGE_ADD_TAIL as u32;
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))] {
pfioc_rule.rule.action = ffi::pfvar::PF_CHANGE_ADD_TAIL as u32;
pfioc_rule.rule.action = ffi::pfvar::PF_CHANGE_ADD_TAIL as u8;
}
ioctl_guard!(ffi::pf_change_rule(self.fd(), &mut pfioc_rule))
}
Expand Down Expand Up @@ -317,7 +316,10 @@ impl PfCtl {
}

// set ticket
pfioc_rule.ticket = utils::get_ticket(self.fd(), anchor, AnchorKind::Redirect)?;
pfioc_rule.ticket = utils::get_ticket(self.fd(), anchor,
#[cfg(target_os = "macos")]
AnchorKind::Redirect
)?;

// append rule
pfioc_rule.action = ffi::pfvar::PF_CHANGE_ADD_TAIL as u32;
Expand All @@ -341,7 +343,10 @@ impl PfCtl {
pub fn clear_states(&mut self, anchor_name: &str, kind: AnchorKind) -> Result<u32> {
let pfsync_states = self.get_states()?;
if !pfsync_states.is_empty() {
self.with_anchor_rule(anchor_name, kind, |anchor_rule| {
self.with_anchor_rule(anchor_name,
#[cfg(target_os = "macos")]
kind,
|anchor_rule| {
pfsync_states
.iter()
.filter(|pfsync_state| pfsync_state.anchor == anchor_rule.nr)
Expand Down Expand Up @@ -385,7 +390,7 @@ impl PfCtl {
}
}

/// Helper function to find an anchor in main ruleset matching by name and kind.
/// Helper function to find an anchor in main ruleset matching by name and (on macOS) kind.
///
/// Calls closure with anchor rule (`pfioc_rule`) on match.
/// Provided `pfioc_rule` can be used to modify or remove the anchor rule.
Expand All @@ -394,12 +399,18 @@ impl PfCtl {
/// - Returns Result<R> from call to closure on match.
/// - Returns `ErrorKind::AnchorDoesNotExist` on mismatch, the closure is not called in that
/// case.
fn with_anchor_rule<F, R>(&self, name: &str, kind: AnchorKind, f: F) -> Result<R>
fn with_anchor_rule<F, R>(
&self, name:
&str,
#[cfg(target_os = "macos")]
kind: AnchorKind,
f: F
) -> Result<R>
where
F: FnOnce(ffi::pfvar::pfioc_rule) -> Result<R>,
{
let mut pfioc_rule = unsafe { mem::zeroed::<ffi::pfvar::pfioc_rule>() };
#[cfg(target_os = "macos")] {
let mut pfioc_rule = unsafe { mem::zeroed::<ffi::pfvar::pfioc_rule>() };
pfioc_rule.rule.action = kind.into();
ioctl_guard!(ffi::pf_get_rules(self.fd(), &mut pfioc_rule))?;
pfioc_rule.action = ffi::pfvar::PF_GET_NONE as u32;
Expand All @@ -412,16 +423,21 @@ impl PfCtl {
}
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))] {
let mut pfioc_rule = unsafe { mem::zeroed::<ffi::pfvar::pfioc_rule>() };
name.try_copy_to(&mut pfioc_rule.anchor[..])
.chain_err(|| ErrorKind::InvalidArgument("Invalid anchor name"))?;
ioctl_guard!(ffi::pf_get_rules(self.fd(), &mut pfioc_rule))?;
pfioc_rule.rule.action = ffi::pfvar::PF_GET_NONE as u8;
ioctl_guard!(ffi::pf_get_rule(self.fd(), &mut pfioc_rule))?;
if compare_cstr_safe(name, &pfioc_rule.anchor_call)? {
// Didn't return EINVAL? Awesome.
#[cfg(target_os = "openbsd")] {
return f(pfioc_rule);
}
// Run function now because we have to dispose of the ticket afterwards.
#[cfg(target_os = "openbsd")] {
let mut ticket = pfioc_rule.ticket;
let res = f(pfioc_rule);
ioctl_guard!(ffi::pf_end_trans(self.fd(), &mut ticket))?;
return res;
}

}
bail!(ErrorKind::AnchorDoesNotExist);
}
Expand Down Expand Up @@ -467,8 +483,10 @@ fn setup_pfioc_state_kill(
pfioc_state_kill.psk_proto = pfsync_state.proto;
pfioc_state_kill.psk_proto_variant = pfsync_state.proto_variant;
pfioc_state_kill.psk_ifname = pfsync_state.ifname;
pfioc_state_kill.psk_src.addr.v.a.addr = pfsync_state.lan.addr;
pfioc_state_kill.psk_dst.addr.v.a.addr = pfsync_state.ext_lan.addr;
#[cfg(target_os = "macos")] {
pfioc_state_kill.psk_src.addr.v.a.addr = pfsync_state.lan.addr;
pfioc_state_kill.psk_dst.addr.v.a.addr = pfsync_state.ext_lan.addr;
}
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions src/rule/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<u16> for Port {
}
}

#[cfg(target_os = "macos")]
impl TryCopyTo<ffi::pfvar::pf_port_range> for Port {
fn try_copy_to(&self, pf_port_range: &mut ffi::pfvar::pf_port_range) -> Result<()> {
match *self {
Expand Down
6 changes: 5 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::{conversion::TryCopyTo, ffi, AnchorKind, ErrorKind, PoolAddr, Result, ResultExt};
use crate::{conversion::TryCopyTo, ffi, ErrorKind, PoolAddr, Result, ResultExt};

#[cfg(target_os = "macos")]
use crate::AnchorKind;

use std::{
fs::{File, OpenOptions},
mem,
Expand Down

0 comments on commit c7922d5

Please sign in to comment.