#![cfg_attr(
not(any(target_os = "illumos", target_os = "solaris")),
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,
}
pub(crate) const SOL_SOCKET: i32 = 0xffff;
pub(crate) const SO_RECVUCRED: i32 = 0x0400;
pub(crate) const SCM_UCRED: i32 = 0x1012;
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
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;
}
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
extern "C" {
pub(crate) fn ucred_getpid(uc: *const c_void) -> i32;
pub(crate) fn ucred_geteuid(uc: *const c_void) -> u32;
#[allow(dead_code)]
pub(crate) fn ucred_getzoneid(uc: *const c_void) -> i32;
}
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
pub(crate) unsafe fn ucred_getpid(uc: *const c_void) -> i32 {
unsafe { (uc as *const i32).read_unaligned() }
}
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
pub(crate) unsafe fn ucred_geteuid(uc: *const c_void) -> u32 {
unsafe { (uc as *const u8).add(4).cast::<u32>().read_unaligned() }
}
pub(crate) const ANCILLARY_BUFFER_SIZE: usize = 1024;
pub(crate) struct IllumosCmsg;
unsafe impl super::super::cmsg::CmsgPlatform for IllumosCmsg {
type Hdr = Cmsghdr;
type Cred = ();
type Msghdr = Msghdr;
const TARGET_LEVEL: i32 = SOL_SOCKET;
const TARGET_TYPE: i32 = SCM_UCRED;
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)> {
let pid = unsafe { ucred_getpid(data as *const c_void) };
let uid = unsafe { ucred_geteuid(data as *const c_void) };
if pid < 0 || uid == u32::MAX {
None
} else {
Some((pid as u32, uid))
}
}
}
pub(crate) fn peer_pid_after_recv(_fd: i32, mhdr: &Msghdr) -> Option<(u32, u32)> {
super::super::cmsg::find_credential::<IllumosCmsg>(mhdr)
}
pub(crate) fn msghdr_for_recv(iov: *mut Iovec, ctrl: *mut 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::<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);