diff options
Diffstat (limited to 'src/platform/linux.rs')
| -rw-r--r-- | src/platform/linux.rs | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/src/platform/linux.rs b/src/platform/linux.rs index e6cf577..3668fe8 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1,11 +1,9 @@ // SPDX-FileCopyrightText: 2025-2026 Dilluti0n <[email protected]> // SPDX-License-Identifier: GPL-3.0-or-later -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Mutex, - LazyLock -}; +use std::{os::fd::AsRawFd, sync::{ + LazyLock, Mutex, atomic::{AtomicBool, Ordering} +}}; use std::process::{Command, Stdio}; use std::io::Write; use anyhow::{Result, Context, anyhow}; @@ -22,6 +20,8 @@ pub static IS_U32_SUPPORTED: AtomicBool = AtomicBool::new(false); pub static IS_NFT_NOT_SUPPORTED: AtomicBool = AtomicBool::new(false); const INJECT_MARK: u32 = 0xD001; +const PID_FILE: &str = "/tmp/dpibreak.pid"; // TODO: unmagic this +const PKG_NAME: &str = env!("CARGO_PKG_NAME"); fn exec_process(args: &[&str], input: Option<&str>) -> Result<()> { if args.is_empty() { @@ -98,9 +98,31 @@ pub fn cleanup() -> Result<()> { Ok(()) } + +/// Only called on non-daemon run. Fail if running dpibreak is +/// existing. pub fn bootstrap() -> Result<()> { - _ = cleanup(); // In case the previous execution was not cleaned properly - install_rules() + use nix::fcntl::{flock, FlockArg}; + use std::fs::OpenOptions; + + let pid_file = OpenOptions::new() + .write(true) + .create(true) + .truncate(false) + .open(PID_FILE)?; + + if flock(pid_file.as_raw_fd(), FlockArg::LockExclusiveNonblock).is_err() { + let existing_pid = std::fs::read_to_string(PID_FILE)?; + anyhow::bail!("Fail to lock {PID_FILE}: {PKG_NAME} already running with PID {}", existing_pid.trim()); + } + + pid_file.set_len(0)?; + writeln!(&pid_file, "{}", std::process::id())?; + pid_file.sync_all()?; + + std::mem::forget(pid_file); // Tell std to do not close the file + + Ok(()) } use socket2::{Domain, Protocol, Socket, Type}; @@ -172,6 +194,9 @@ pub fn run() -> Result<()> { use crate::handle_packet; use super::PACKET_SIZE_CAP; + _ = cleanup(); // In case the previous execution was not cleaned properly + install_rules()?; + let mut q = Queue::open()?; q.bind(crate::opt::queue_num())?; log_println!(LogLevel::Info, "nfqueue: bound to queue number {}", @@ -221,7 +246,6 @@ pub fn run() -> Result<()> { Ok(()) } -const PKG_NAME: &str = env!("CARGO_PKG_NAME"); const DAEMON_PREFIX: &str = "/tmp"; fn daemonize() -> Result<()> { @@ -229,10 +253,9 @@ fn daemonize() -> Result<()> { use daemonize::Daemonize; let log_file = fs::File::create(format!("{DAEMON_PREFIX}/{PKG_NAME}.log"))?; - let pid_file = format!("{DAEMON_PREFIX}/{PKG_NAME}.pid"); let daemonize = Daemonize::new() - .pid_file(&pid_file) + .pid_file(PID_FILE) .chown_pid_file(true) .working_directory(DAEMON_PREFIX) .stdout(log_file); |
