1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// SPDX-FileCopyrightText: 2026 Dilluti0n <[email protected]>
// SPDX-License-Identifier: GPL-3.0-or-later
use std::os::fd::{OwnedFd, RawFd, FromRawFd};
use std::io::Error;
use std::ffi::{c_int, c_void};
use std::mem;
macro_rules! syscall {
($call:expr) => {
match $call {
-1 => Err(::std::io::Error::last_os_error()),
res => Ok(res),
}
};
}
#[allow(non_camel_case_types)]
pub enum FcntlArg {
F_GETFL,
F_SETFL(c_int),
}
pub fn fcntl(fd: RawFd, op: FcntlArg) -> Result<c_int, Error> {
use libc::fcntl;
syscall!(match op {
FcntlArg::F_GETFL => unsafe { fcntl(fd, libc::F_GETFL) },
FcntlArg::F_SETFL(flags) => unsafe { fcntl(fd, libc::F_SETFL, flags) }
})
}
pub fn flock(fd: RawFd, op: c_int) -> Result<(), Error> {
syscall!(unsafe { libc::flock(fd, op) }).map(drop)
}
pub fn geteuid() -> libc::uid_t {
unsafe { libc::geteuid() }
}
pub fn poll(fds: &mut [libc::pollfd], timeout: c_int) -> Result<(), Error> {
syscall!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as _, timeout) }).map(drop)
}
unsafe fn setsockopt_1<T>(sockfd: RawFd, level: c_int, optname: c_int, optval: &T) -> c_int {
unsafe {
libc::setsockopt(sockfd, level, optname,
(optval as *const T).cast() as *const c_void,
mem::size_of::<T>() as libc::socklen_t)
}
}
#[allow(non_camel_case_types)]
pub enum SockOpt<'a> {
SO_ATTACH_FILTER(&'a [libc::sock_filter]),
PACKET_RX_RING(&'a libc::tpacket_req),
}
pub fn setsockopt(sockfd: RawFd, opt: SockOpt) -> Result<(), Error> {
syscall!(match opt {
SockOpt::SO_ATTACH_FILTER(val) => {
let prog = libc::sock_fprog {
len: val.len() as u16,
filter: val.as_ptr() as *mut libc::sock_filter
};
unsafe {setsockopt_1(sockfd, libc::SOL_SOCKET, libc::SO_ATTACH_FILTER, &prog)}
},
SockOpt::PACKET_RX_RING(optval) => unsafe {
setsockopt_1(sockfd, libc::SOL_PACKET, libc::PACKET_RX_RING, optval)
}
}).map(drop)
}
pub fn socket(domain: c_int, so_type: c_int, protocol: c_int) -> Result<OwnedFd, Error> {
unsafe {
let raw = syscall!(libc::socket(domain, so_type, protocol))?;
Ok(OwnedFd::from_raw_fd(raw))
}
}
pub unsafe fn mmap(
addr: *mut c_void, length: usize, prot: c_int,
flags: c_int, fd: RawFd, offset: libc::off_t
) -> Result<*mut c_void, Error> {
match unsafe {libc::mmap(addr, length, prot, flags, fd, offset)} {
libc::MAP_FAILED => Err(Error::last_os_error()),
res => Ok(res),
}
}
pub unsafe fn munmap(addr: *mut c_void, length: usize) -> Result<(), Error> {
syscall!(unsafe { libc::munmap(addr, length) }).map(drop)
}
|