diff options
Diffstat (limited to 'src/platform/linux.rs')
| -rw-r--r-- | src/platform/linux.rs | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/src/platform/linux.rs b/src/platform/linux.rs index bebc6f4..096451a 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -17,10 +17,10 @@ use crate::opt; mod iptables; mod nftables; mod rxring; +mod libc_s; use iptables::*; use nftables::*; -use libc::sock_filter; use crate::pkt; pub static IS_U32_SUPPORTED: AtomicBool = AtomicBool::new(false); @@ -99,7 +99,7 @@ fn cleanup_rules() -> Result<()> { } fn lock_pid_file() -> Result<()> { - use nix::fcntl::{flock, FlockArg}; + use libc_s::flock; let pid_file = OpenOptions::new() .write(true) @@ -107,7 +107,7 @@ fn lock_pid_file() -> Result<()> { .truncate(false) .open(PID_FILE)?; - if flock(pid_file.as_raw_fd(), FlockArg::LockExclusiveNonblock).is_err() { + if flock(pid_file.as_raw_fd(), libc::LOCK_NB | libc::LOCK_EX).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()); } @@ -122,7 +122,7 @@ fn lock_pid_file() -> Result<()> { } fn exit_if_not_root() { - if !nix::unistd::geteuid().is_root() { + if libc_s::geteuid() != 0 { crate::error!("{PKG_NAME} must be run as root. Try sudo."); std::process::exit(3); } @@ -154,7 +154,10 @@ static RAW6: LazyLock<Socket> = LazyLock::new(|| { let sock = Socket::new(Domain::IPV6, Type::RAW, Some(Protocol::TCP)) .expect("create raw6"); - sock.set_header_included_v6(true).expect("IP_HDRINCL"); + if let Err(e) = sock.set_header_included_v6(true) { + crate::warn!("Failed to set IPV6_HDRINCL. Maybe old kernel version? IPv6 header manipulation disabled."); + crate::warn!("Cause: {e}"); + } sock.set_mark(INJECT_MARK).expect("SO_MARK"); sock @@ -181,26 +184,29 @@ pub fn send_to_raw(pkt: &[u8], dst: std::net::IpAddr) -> Result<()> { fn open_nfqueue() -> Result<nfq::Queue> { use std::os::fd::AsRawFd; - use nix::fcntl::{fcntl, FcntlArg, OFlag}; + use libc_s::{fcntl, FcntlArg}; let mut q = nfq::Queue::open()?; - q.bind(crate::opt::queue_num())?; - crate::info!("nfqueue: bound to queue number {}", crate::opt::queue_num()); + q.bind(opt::queue_num())?; + crate::info!("nfqueue: bound to queue number {}", opt::queue_num()); // to check inturrupts - let raw_fd = q.as_raw_fd(); - let flags = fcntl(raw_fd, FcntlArg::F_GETFL)?; - let new_flags = OFlag::from_bits_truncate(flags) | OFlag::O_NONBLOCK; - fcntl(raw_fd, FcntlArg::F_SETFL(new_flags))?; + let fd = q.as_raw_fd(); + let fl = fcntl(fd, FcntlArg::F_GETFL)?; + fcntl(fd, FcntlArg::F_SETFL(fl | libc::O_NONBLOCK))?; Ok(q) } +/// Open AF_PACKET RX ring for syn/ack packets fn open_rxring() -> Result<rxring::RxRing> { + use libc::sock_filter; + /// cBPF filter for TCP and sport=443 and SYN,ACK packets /// /// Produced by - /// tcpdump -dd '(ip and tcp src port 443 and tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)) or (ip6 and tcp src port 443 and ip6[53] & 0x12 == 0x12)' + /// tcpdump -dd '(ip and tcp src port 443 and tcp[tcpflags] & (tcp-syn|tcp-ack) + /// == (tcp-syn|tcp-ack)) or (ip6 and tcp src port 443 and ip6[53] & 0x12 == 0x12)' const SYNACK_443_CBPF: &[sock_filter] = &[ sock_filter { code: 0x28, jt: 0, jf: 0, k: 0x0000000c }, sock_filter { code: 0x15, jt: 0, jf: 10, k: 0x00000800 }, @@ -225,12 +231,14 @@ fn open_rxring() -> Result<rxring::RxRing> { sock_filter { code: 0x6, jt: 0, jf: 0, k: 0x00040000 }, sock_filter { code: 0x6, jt: 0, jf: 0, k: 0x00000000 }, ]; + const BLOCK_SIZE: u32 = 4096 * 4; // 16 KB + const BLOCK_NR: u32 = 4; + + /// tpacket_hdr (~66) + eth(14) + ipv6(40) + tcp with options(60) = ~180 + const FRAME_SIZE: u32 = 256; - let rx = rxring::RxRing::new(SYNACK_443_CBPF)?; + let rx = rxring::RxRing::new(SYNACK_443_CBPF, BLOCK_SIZE, BLOCK_NR, FRAME_SIZE)?; crate::info!("rxring: initialized"); - crate::debug!( - "rxring: tcp src port 443 and tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)" - ); Ok(rx) } @@ -258,18 +266,6 @@ fn open_signalfd() -> Result<OwnedFd> { } } -// Note: Invalid FDs safely result in POLLNVAL, so this doesn't need to be unsafe -fn poll_s(fds: &mut [libc::pollfd]) -> Result<()> { - use std::io::Error; - - // SAFETY: fds.len() is fds's length - if unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as _, -1) } == -1 { - return Err(Error::last_os_error().into()); - } - - Ok(()) -} - pub fn run() -> Result<()> { use crate::handle_packet; use super::PACKET_SIZE_CAP; @@ -295,7 +291,8 @@ pub fn run() -> Result<()> { crate::splash!("{}", super::MESSAGE_AT_RUN); loop { - poll_s(&mut fds)?; + libc_s::poll(&mut fds, -1)?; + let is_intr: bool = fds[0].revents & libc::POLLIN != 0; let q_ready: bool = fds[1].revents & libc::POLLIN != 0; let rx_ready: bool = fds[2].revents & libc::POLLIN != 0; |
