summaryrefslogtreecommitdiffhomepage
path: root/src/platform/linux.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/linux.rs')
-rw-r--r--src/platform/linux.rs116
1 files changed, 11 insertions, 105 deletions
diff --git a/src/platform/linux.rs b/src/platform/linux.rs
index 03dd94e..1db2e09 100644
--- a/src/platform/linux.rs
+++ b/src/platform/linux.rs
@@ -3,118 +3,25 @@
use std::{
os::fd::{AsRawFd, OwnedFd},
- sync::{LazyLock, atomic::AtomicBool}
+ sync::{LazyLock, atomic}
};
use std::fs::OpenOptions;
-use std::process::{Command, Stdio};
use std::io::Write;
-use anyhow::{Result, Context, anyhow};
+use anyhow::{Result, Context};
use socket2::{Domain, Protocol, Socket, Type};
-mod iptables;
-mod nftables;
+mod rules;
mod rxring;
#[macro_use] mod libc_s;
-use iptables::*;
-use nftables::*;
-
use crate::pkt;
use crate::opt;
-pub static IS_U32_SUPPORTED: AtomicBool = AtomicBool::new(false);
-
const INJECT_MARK: u32 = 0xD001;
const PID_FILE: &str = "/run/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() {
- return Err(anyhow!("command args cannot be empty"));
- }
-
- let program = args[0];
- let stdin_mode = if input.is_some() { Stdio::piped() } else { Stdio::null() };
-
- let mut child = Command::new(program)
- .args(&args[1..])
- .stdin(stdin_mode)
- .stdout(Stdio::null())
- .stderr(Stdio::piped())
- .spawn()
- .with_context(|| format!("failed to spawn {}", program))?;
-
- if let Some(data) = input {
- if let Some(mut stdin) = child.stdin.take() {
- stdin.write_all(data.as_bytes())
- .with_context(|| format!("failed to write input to {}", program))?;
- }
- }
-
- let output = child.wait_with_output()
- .with_context(|| format!("failed to wait for {}", program))?;
-
- match output.status.code() {
- Some(0) => Ok(()),
- Some(code) => Err(anyhow!("{} exited with status {}: {}", program, code,
- String::from_utf8_lossy(&output.stderr))),
- None => Err(anyhow!("{} terminated by signal", program))
- }
-}
-
-struct InstalledRules {
- is_nft_not_supported: bool,
- ipt: Option<IPTables>,
- ip6: Option<IPTables>
-}
-
-fn install_ipt6(is_ipv6: bool) -> Option<IPTables> {
- let ipt = IPTables::new(is_ipv6).map_err(|e| crate::warn!("iptables: {e}")).ok();
- if let Some(ref ipt) = ipt {
- ipt.install().map_err(|e| crate::warn!("iptables: {e}")).ok();
- }
-
- ipt
-}
-
-fn install_rules() -> Result<InstalledRules> {
- let mut is_nft_not_supported = false;
- let mut ipt = None;
- let mut ip6 = None;
-
- if let Err(e) = install_nft_rules() {
- is_nft_not_supported = true;
- crate::warn!("nftables: {}", e.to_string());
- crate::warn!("fallback to iptables");
-
- ipt = install_ipt6(false);
- ip6 = install_ipt6(true);
- }
-
- Ok(InstalledRules{
- is_nft_not_supported,
- ipt,
- ip6
- })
-}
-
-impl Drop for InstalledRules {
- fn drop(&mut self) {
- if self.is_nft_not_supported {
- if let Some(ipt) = &self.ipt {
- ipt.cleanup().map_err(|e| crate::warn!("fail to cleanup iptables rules: {e}")).ok();
- }
- if let Some(ipt) = &self.ip6 {
- ipt.cleanup().map_err(|e| crate::warn!("fail to cleanup ip6tables rules: {e}")).ok();
- }
- cleanup_xt_u32().map_err(|e| crate::warn!("fail to cleanup xt_u32: {e}")).ok();
- } else {
- cleanup_nftables_rules().map_err(|e| crate::warn!("fail to cleanup nftables rules: {e}")).ok();
- }
- }
-}
-
fn lock_pid_file() -> Result<()> {
use libc_s::flock;
@@ -279,21 +186,16 @@ fn open_signalfd() -> Result<OwnedFd> {
}
}
-fn ipt6_cleanup(is_ipv6: bool) -> Result<()> {
- let ipt6 = IPTables::new(is_ipv6)?;
- ipt6.cleanup()
-}
-
pub fn run() -> Result<()> {
use crate::handle_packet;
use super::PACKET_SIZE_CAP;
// In case the previous execution was not cleaned properly
- _ = cleanup_nftables_rules();
- _ = ipt6_cleanup(false);
- _ = ipt6_cleanup(true);
+ _ = rules::nft_cleanup();
+ _ = rules::ipt6_cleanup(false);
+ _ = rules::ipt6_cleanup(true);
- let _rule = install_rules()?;
+ let _rule = rules::install()?;
let sfd = open_signalfd()?;
let mut q = open_nfqueue()?;
@@ -400,3 +302,7 @@ pub fn local_time() -> (i32, u8, u8, u8, u8, u8) {
tm.tm_hour as u8, tm.tm_min as u8, tm.tm_sec as u8)
}
}
+
+pub fn is_kernel_filtered_clienthello() -> bool {
+ rules::IS_U32_SUPPORTED.load(atomic::Ordering::Relaxed)
+}