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 AuditToken {
pub val: [u32; 8],
}
#[repr(C)]
pub(crate) struct Xucred {
pub cr_version: u32,
pub cr_uid: u32,
pub cr_ngroups: i16,
pub cr_groups: [u32; 16],
}
pub(crate) const SOL_SOCKET: i32 = 0xffff;
pub(crate) const LOCAL_PEERTOKEN: i32 = 0x0021;
pub(crate) const LOCAL_PEERPID: i32 = 0x0002;
pub(crate) const LOCAL_PEERCRED: i32 = 0x0001;
extern "C" {
pub(crate) fn recvmsg(fd: i32, msg: *mut Msghdr, flags: i32) -> isize;
pub(crate) fn getsockopt(
fd: i32,
level: i32,
optname: i32,
optval: *mut c_void,
optlen: *mut u32,
) -> i32;
}
pub(crate) const ANCILLARY_BUFFER_SIZE: usize = 16;
pub(crate) fn peer_pid_after_recv(fd: i32, _mhdr: &Msghdr) -> Option<(u32, u32)> {
let token = get_token(fd);
let pid = get_peer_pid(fd);
let cred = get_peer_cred(fd);
Some(super::super::macos_fallback::pid_uid_from_results(
token, pid, cred,
))
}
fn get_token(fd: i32) -> super::super::macos_fallback::TokenResult {
let mut token = AuditToken { val: [0u32; 8] };
let mut optlen: u32 = mem::size_of::<AuditToken>() as u32;
let ret = unsafe {
getsockopt(
fd,
SOL_SOCKET,
LOCAL_PEERTOKEN,
&mut token as *mut AuditToken as *mut c_void,
&mut optlen,
)
};
super::super::macos_fallback::TokenResult {
ret,
optlen,
at_pid: token.val[5],
at_euid: token.val[1],
}
}
fn get_peer_pid(fd: i32) -> super::super::macos_fallback::PidResult {
let mut pid: i32 = 0;
let mut optlen: u32 = mem::size_of::<i32>() as u32;
let ret = unsafe {
getsockopt(
fd,
SOL_SOCKET,
LOCAL_PEERPID,
&mut pid as *mut i32 as *mut c_void,
&mut optlen,
)
};
super::super::macos_fallback::PidResult { ret, optlen, pid }
}
fn get_peer_cred(fd: i32) -> super::super::macos_fallback::CredResult {
let mut cred = Xucred {
cr_version: 0,
cr_uid: 0,
cr_ngroups: 0,
cr_groups: [0u32; 16],
};
let mut optlen: u32 = mem::size_of::<Xucred>() as u32;
let ret = unsafe {
getsockopt(
fd,
SOL_SOCKET,
LOCAL_PEERCRED,
&mut cred as *mut Xucred as *mut c_void,
&mut optlen,
)
};
super::super::macos_fallback::CredResult {
ret,
optlen,
cr_uid: cred.cr_uid,
}
}
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::<AuditToken>() == 32);
const _: () = assert!(mem::size_of::<Xucred>() == 76);
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);