#![cfg_attr(
not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd")),
allow(dead_code)
)]
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: i32,
pub _pad2: u32,
pub msg_control: *mut c_void,
pub msg_controllen: u32,
pub msg_flags: i32,
}
#[repr(C)]
pub(crate) struct Cmsghdr {
pub cmsg_len: u32,
pub cmsg_level: i32,
pub cmsg_type: i32,
}
#[repr(C)]
pub(crate) struct Cmsgcred {
pub cmcred_pid: i32,
pub cmcred_uid: u32,
pub cmcred_euid: u32,
pub cmcred_gid: u32,
pub cmcred_ngroups: i16,
_pad: i16,
pub cmcred_groups: [u32; 16],
}
pub(crate) const SOL_SOCKET: i32 = 0xffff;
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
pub(crate) const LOCAL_CREDS: i32 = 0x0002;
#[cfg(target_os = "netbsd")]
pub(crate) const LOCAL_CREDS: i32 = 0x0001;
pub(crate) const SCM_CREDS: i32 = 0x03;
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
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::<Cmsgcred>()
);
pub(crate) struct BsdCmsg;
unsafe impl super::super::cmsg::CmsgPlatform for BsdCmsg {
type Hdr = Cmsghdr;
type Cred = Cmsgcred;
type Msghdr = Msghdr;
const TARGET_LEVEL: i32 = SOL_SOCKET;
const TARGET_TYPE: i32 = SCM_CREDS;
fn cmsg_len(hdr: &Cmsghdr) -> usize {
hdr.cmsg_len as usize
}
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 as usize
}
unsafe fn extract_pid_uid(data: *const u8, len: usize) -> Option<(u32, u32)> {
debug_assert!(len >= core::mem::size_of::<Cmsgcred>());
let cred = unsafe { &*(data as *const Cmsgcred) };
Some((cred.cmcred_pid as u32, cred.cmcred_euid))
}
}
pub(crate) fn peer_pid_after_recv(_fd: i32, mhdr: &Msghdr) -> Option<(u32, u32)> {
super::super::cmsg::find_credential::<BsdCmsg>(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,
_pad2: 0,
msg_control: ctrl,
msg_controllen: ctrl_len as u32,
msg_flags: 0,
}
}
pub(crate) fn ctrl_truncated(_mhdr: &Msghdr) -> bool {
false
}
const _: () = assert!(mem::size_of::<Msghdr>() == 48);
const _: () = assert!(mem::size_of::<Cmsgcred>() == 84);
const _: () = assert!(mem::size_of::<Iovec>() == 16);
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) == 44);
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) == 4);
const _: () = assert!(mem::offset_of!(Cmsghdr, cmsg_type) == 8);
const _: () = assert!(mem::offset_of!(Cmsgcred, cmcred_pid) == 0);
const _: () = assert!(mem::offset_of!(Cmsgcred, cmcred_uid) == 4);
const _: () = assert!(mem::offset_of!(Cmsgcred, cmcred_euid) == 8);
const _: () = assert!(mem::offset_of!(Cmsgcred, cmcred_gid) == 12);
const _: () = assert!(mem::offset_of!(Cmsgcred, cmcred_ngroups) == 16);
const _: () = assert!(mem::offset_of!(Cmsgcred, cmcred_groups) == 20);