diff options
| -rw-r--r-- | Cargo.lock | 68 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/platform/linux.rs | 68 |
3 files changed, 45 insertions, 92 deletions
@@ -57,15 +57,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] -name = "block2" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" -dependencies = [ - "objc2", -] - -[[package]] name = "bumpalo" version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -100,12 +91,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] name = "ciborium" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -224,17 +209,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "ctrlc" -version = "3.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" -dependencies = [ - "dispatch2", - "nix 0.31.2", - "windows-sys", -] - -[[package]] name = "daemonize" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -244,29 +218,16 @@ dependencies = [ ] [[package]] -name = "dispatch2" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" -dependencies = [ - "bitflags", - "block2", - "libc", - "objc2", -] - -[[package]] name = "dpibreak" version = "0.6.1" dependencies = [ "anyhow", "criterion", - "ctrlc", "daemonize", "etherparse 0.18.2", "libc", "nfq-updated", - "nix 0.27.1", + "nix", "socket2", "windivert", "windows-services", @@ -374,18 +335,6 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -395,21 +344,6 @@ dependencies = [ ] [[package]] -name = "objc2" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" -dependencies = [ - "objc2-encode", -] - -[[package]] -name = "objc2-encode" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" - -[[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -39,7 +39,6 @@ socket2 = { version = "0.6", features = ["all"] } nix = { version = "0.27.1", features = ["fs", "user"] } daemonize = "0.5.0" libc = "0.2" -ctrlc = { version = "3.4", features = ["termination"] } [target.'cfg(windows)'.dependencies] windivert = { version = "0.6.0" } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index c774d77..975c90c 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1,9 +1,10 @@ // SPDX-FileCopyrightText: 2025-2026 Dilluti0n <[email protected]> // SPDX-License-Identifier: GPL-3.0-or-later -use std::{os::fd::AsRawFd, sync::{ - LazyLock, atomic::{AtomicBool, Ordering} -}}; +use std::{ + os::fd::{AsRawFd, OwnedFd}, + sync::{LazyLock, atomic::{AtomicBool, Ordering}} +}; use std::fs::OpenOptions; use std::process::{Command, Stdio}; use std::io::Write; @@ -24,7 +25,6 @@ use crate::pkt; pub static IS_U32_SUPPORTED: AtomicBool = AtomicBool::new(false); pub static IS_NFT_NOT_SUPPORTED: AtomicBool = AtomicBool::new(false); -static RUNNING: AtomicBool = AtomicBool::new(true); const INJECT_MARK: u32 = 0xD001; const PID_FILE: &str = "/run/dpibreak.pid"; // TODO: unmagic this @@ -240,38 +240,58 @@ enum PollResult { Interrupted, } -fn poll_once(q: &nfq::Queue, rx: Option<&rxring::RxRing>) -> Result<PollResult> { +fn poll_once(sfd: &OwnedFd, q: &nfq::Queue, rx: Option<&rxring::RxRing>) -> Result<PollResult> { use std::io::Error; use std::os::fd::AsRawFd; - let mut fds = [libc::pollfd { fd: -1, events: libc::POLLIN, revents: 0 }; 2]; + let mut fds = [libc::pollfd { fd: -1, events: libc::POLLIN, revents: 0 }; 3]; - fds[0].fd = q.as_raw_fd(); - if let Some(rx) = rx { fds[1].fd = rx.as_raw_fd() }; + fds[0].fd = sfd.as_raw_fd(); + fds[1].fd = q.as_raw_fd(); + if let Some(rx) = rx { fds[2].fd = rx.as_raw_fd() }; match unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as _, -1) } { -1 => { let e = Error::last_os_error(); - if e.raw_os_error() == Some(libc::EINTR) { - return Ok(PollResult::Interrupted); - } + + // EINTR not happen here since we blocked SIGINT on open_signalfd() Err(e.into()) }, - _ => Ok(PollResult::Ready { - q: fds[0].revents & libc::POLLIN != 0, + _ => { + if fds[0].revents & libc::POLLIN != 0 { + return Ok(PollResult::Interrupted); + } + Ok(PollResult::Ready { + q: fds[1].revents & libc::POLLIN != 0, - // false if rx is None (fd=-1, revents set to 0 by poll) - rx: fds[1].revents & libc::POLLIN != 0 - }) + // false if rx is None (fd=-1, revents set to 0 by poll) + rx: fds[2].revents & libc::POLLIN != 0 + }) + } } } -fn trap_exit() -> Result<()> { - ctrlc::set_handler(|| { - RUNNING.store(false, Ordering::SeqCst); - }).context("handler: ")?; +/// open signalfd for SIGINT and SIGTERM +fn open_signalfd() -> Result<OwnedFd> { + use libc::*; + use std::io::Error; + use std::os::fd::FromRawFd; - Ok(()) + // SAFETY: sigaddset fails only when signum is invalid + unsafe { + let mut mask: sigset_t = std::mem::zeroed(); + sigemptyset(&mut mask); + sigaddset(&mut mask, SIGTERM); + sigaddset(&mut mask, SIGINT); + + let ret = pthread_sigmask(SIG_BLOCK, &mask, core::ptr::null_mut()); + if ret < 0 { return Err(Error::last_os_error().into()); } + + let raw = signalfd(-1, &mask, 0); + if raw < 0 { return Err(Error::last_os_error().into()); } + + Ok(OwnedFd::from_raw_fd(raw)) + } } pub fn run() -> Result<()> { @@ -280,16 +300,16 @@ pub fn run() -> Result<()> { _ = cleanup_rules(); // In case the previous execution was not cleaned properly install_rules()?; - trap_exit()?; + let sfd = open_signalfd()?; let mut q = open_nfqueue()?; let mut rx = if opt::fake_autottl() { Some(open_rxring()?) } else { None }; let mut buf = Vec::<u8>::with_capacity(PACKET_SIZE_CAP); crate::splash!("{}", super::MESSAGE_AT_RUN); - while RUNNING.load(Ordering::SeqCst) { - let (q_ready, rx_ready) = match poll_once(&q, rx.as_ref())? { + loop { + let (q_ready, rx_ready) = match poll_once(&sfd, &q, rx.as_ref())? { PollResult::Ready { q, rx } => (q, rx), PollResult::Interrupted => break, }; |
