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.rs57
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;