use core::ffi::c_void;
use core::mem;
#[repr(C)]
pub(crate) struct Iovec {
pub iov_base: *mut c_void,
pub iov_len: usize,
}
#[repr(C)]
pub(crate) struct Msghdr {
pub msg_name: *mut c_void,
pub msg_namelen: u32,
pub _pad1: u32,
pub msg_iov: *mut Iovec,
pub msg_iovlen: usize,
pub msg_control: *mut c_void,
pub msg_controllen: usize,
pub msg_flags: i32,
pub _pad2: i32,
}
#[repr(C)]
pub(crate) struct Cmsghdr {
pub cmsg_len: usize,
pub cmsg_level: i32,
pub cmsg_type: i32,
}
#[repr(C)]
pub(crate) struct Ucred {
pub pid: i32,
pub uid: u32,
pub gid: u32,
}
pub(crate) const SOL_SOCKET: i32 = 1;
pub(crate) const SO_PASSCRED: i32 = 16;
pub(crate) const SCM_CREDENTIALS: i32 = 2;
pub(crate) const MSG_CTRUNC: i32 = 0x20;
extern "C" {
pub(crate) fn setsockopt(
fd: i32,
level: i32,
optname: i32,
optval: *const c_void,
optlen: u32,
) -> i32;
pub(crate) fn recvmsg(fd: i32, msg: *mut Msghdr, flags: i32) -> isize;
}
pub(crate) const ANCILLARY_BUFFER_SIZE: usize = 256;
const _: () = assert!(
ANCILLARY_BUFFER_SIZE
>= super::super::cmsg::cmsg_align(core::mem::size_of::<Cmsghdr>())
+ core::mem::size_of::<Ucred>()
);
pub(crate) struct LinuxCmsg;
unsafe impl super::super::cmsg::CmsgPlatform for LinuxCmsg {
type Hdr = Cmsghdr;
type Cred = Ucred;
type Msghdr = Msghdr;
const TARGET_LEVEL: i32 = SOL_SOCKET;
const TARGET_TYPE: i32 = SCM_CREDENTIALS;
fn cmsg_len(hdr: &Cmsghdr) -> usize {
hdr.cmsg_len
}
fn cmsg_level(hdr: &Cmsghdr) -> i32 {
hdr.cmsg_level
}
fn cmsg_type(hdr: &Cmsghdr) -> i32 {
hdr.cmsg_type
}
fn msg_control(mhdr: &Msghdr) -> *const u8 {
mhdr.msg_control as *const u8
}
fn msg_controllen(mhdr: &Msghdr) -> usize {
mhdr.msg_controllen
}
unsafe fn extract_pid_uid(data: *const u8, len: usize) -> Option<(u32, u32)> {
debug_assert!(len >= core::mem::size_of::<Ucred>());
let cred = unsafe { &*(data as *const Ucred) };
Some((cred.pid as u32, cred.uid))
}
}
pub(crate) fn peer_pid_after_recv(_fd: i32, mhdr: &Msghdr) -> Option<(u32, u32)> {
super::super::cmsg::find_credential::<LinuxCmsg>(mhdr)
}
pub(crate) fn msghdr_for_recv(
iov: *mut Iovec,
ctrl: *mut core::ffi::c_void,
ctrl_len: usize,
) -> Msghdr {
Msghdr {
msg_name: core::ptr::null_mut(),
msg_namelen: 0,
_pad1: 0,
msg_iov: iov,
msg_iovlen: 1,
msg_control: ctrl,
msg_controllen: ctrl_len,
msg_flags: 0,
_pad2: 0,
}
}
pub(crate) fn ctrl_truncated(mhdr: &Msghdr) -> bool {
mhdr.msg_flags & MSG_CTRUNC != 0
}
const _: () = assert!(mem::size_of::<Msghdr>() == 56);
const _: () = assert!(mem::offset_of!(Msghdr, msg_name) == 0);
const _: () = assert!(mem::offset_of!(Msghdr, msg_namelen) == 8);
const _: () = assert!(mem::offset_of!(Msghdr, msg_iov) == 16);
const _: () = assert!(mem::offset_of!(Msghdr, msg_iovlen) == 24);
const _: () = assert!(mem::offset_of!(Msghdr, msg_control) == 32);
const _: () = assert!(mem::offset_of!(Msghdr, msg_controllen) == 40);
const _: () = assert!(mem::offset_of!(Msghdr, msg_flags) == 48);
const _: () = assert!(mem::offset_of!(Iovec, iov_base) == 0);
const _: () = assert!(mem::offset_of!(Iovec, iov_len) == 8);
const _: () = assert!(mem::offset_of!(Cmsghdr, cmsg_len) == 0);
const _: () = assert!(mem::offset_of!(Cmsghdr, cmsg_level) == 8);
const _: () = assert!(mem::offset_of!(Cmsghdr, cmsg_type) == 12);
const _: () = assert!(mem::offset_of!(Ucred, pid) == 0);
const _: () = assert!(mem::offset_of!(Ucred, uid) == 4);
const _: () = assert!(mem::offset_of!(Ucred, gid) == 8);