use std::os::unix::net::UnixDatagram;
use std::mem::MaybeUninit;
use std::{
net::Shutdown,
os::unix::{
prelude::AsRawFd,
io::RawFd
}
};
use nix::errno::Errno;
use crate::{map_error, throw_error};
use super::common::*;
use super::error::{SyRes, SyslogError, SyslogErrCode};
pub(crate) enum SyslogSocket
{
None,
UnPriv(UnixDatagram),
Priv(UnixDatagram),
OldLog(UnixDatagram),
}
unsafe impl Sync for SyslogSocket{}
unsafe impl Send for SyslogSocket{}
impl SyslogSocket
{
pub(crate) fn none() -> Self
{
return Self::None;
}
pub(crate) fn get_raw_fd(&self) -> RawFd
{
match *self
{
Self::None => panic!("Assertion: wrong use of get_raw_fd()"),
Self::UnPriv(ref s) |
Self::Priv(ref s) |
Self::OldLog(ref s) =>
{
return s.as_raw_fd();
}
}
}
fn connect_internal() -> SyRes<Self>
{
let sock =
UnixDatagram::unbound().map_err(|e|
map_error!("unbounded unix datagram initialization failure: {}", e)
)?;
if let Ok(_) = sock.connect(PATH_LOG_PRIV)
{
return Ok(Self::Priv(sock));
}
else if let Ok(_) = sock.connect(PATH_LOG)
{
return Ok(Self::UnPriv(sock));
}
else if let Ok(_) = sock.connect(PATH_OLDLOG)
{
return Ok(Self::OldLog(sock));
}
else if let Ok(_) = sock.connect(PATH_OSX)
{
return Ok(Self::Priv(sock));
}
else
{
throw_error!("failed to open connection to syslog server: {} ",
Errno::last());
};
}
pub(crate) fn connect() -> SyRes<Self>
{
let stream = Self::connect_internal()?;
let mut len: MaybeUninit<libc::socklen_t> = std::mem::MaybeUninit::uninit();
let res = unsafe
{
libc::getsockopt(
stream.get_raw_fd(),
libc::SOL_SOCKET,
libc::SO_SNDBUF,
len.as_mut_ptr() as *mut libc::c_void,
&mut {
std::mem::size_of::<libc::socklen_t>() as libc::socklen_t
}
)
};
if res == 0
{
let mut len = unsafe { len.assume_init() };
if len < MAXLINE
{
len = MAXLINE;
unsafe {
libc::setsockopt(
stream.get_raw_fd(),
libc::SOL_SOCKET,
libc::SO_SNDBUF,
&len as *const _ as *const libc::c_void,
std::mem::size_of::<libc::socklen_t>() as libc::socklen_t
)
};
}
}
return Ok(stream);
}
pub(crate) fn send(&mut self, msg: &[u8]) -> std::io::Result<usize>
{
match *self
{
Self::None =>
panic!("Assertion: send() called on uninited socket"),
Self::UnPriv(ref mut s) |
Self::Priv(ref mut s) |
Self::OldLog(ref mut s) =>
{
return s.send(msg);
}
}
}
pub(crate) fn shutdown(&mut self)
{
match *self
{
Self::None => panic!("Assertion: wrong use of get_raw_fd()"),
Self::UnPriv(ref mut s) |
Self::Priv(ref mut s) |
Self::OldLog(ref mut s) =>
{
let _ = s.shutdown(Shutdown::Both);
}
}
}
pub(crate) fn is_none(&self) -> bool
{
match self
{
Self::None => return true,
Self::UnPriv(_) |
Self::Priv(_) |
Self::OldLog(_) => return false,
}
}
pub(crate) fn is_priv(&self) -> bool
{
match self
{
Self::None => return false,
Self::UnPriv(_) => return false,
Self::Priv(_) => return true,
Self::OldLog(_) => return false,
}
}
}