aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/platform/linux/libc_s.rs
blob: f599ed09ef42e297c3f445458619450a4a350cec (plain)
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)
}