use std::ffi::CStr;
use std::mem::size_of;
use crate::Message;
use crate::ffi::*;
use crate::sys::Bytes;
use what::*;
#[repr(u32)]
#[derive(Debug)]
pub enum Op {
Listen = PROC_CN_MCAST_LISTEN,
Ignore = PROC_CN_MCAST_IGNORE,
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, Default)]
pub struct Subscribe {
cn: cn_msg,
op: u32,
}
#[derive(Clone, Debug)]
pub enum Event {
None,
Fork(Fork),
Exec(Proc),
UID(Proc, u32, u32),
GID(Proc, u32, u32),
SID(Proc),
PTrace(PTrace),
Comm(Proc, String),
Coredump(Proc),
Exit(Exit),
}
#[derive(Clone, Debug)]
pub struct Fork {
pub parent: Proc,
pub child: Proc,
}
#[derive(Clone, Debug)]
pub struct PTrace {
pub process: Proc,
pub tracer: Proc,
}
#[derive(Clone, Debug)]
pub struct Exit {
pub process: Proc,
pub exit_code: u32,
pub exit_signal: u32,
}
#[derive(Clone, Debug)]
pub struct Proc {
pub pid: u32,
pub tgid: u32,
}
pub fn subscribe(op: Op) -> Message<'static, Subscribe> {
let mut msg = Message::<Subscribe>::new(NLMSG_DONE);
msg.cn.id.idx = CN_IDX_PROC;
msg.cn.id.val = CN_VAL_PROC;
msg.cn.len = size_of::<u32>() as u16;
msg.op = op as u32;
msg
}
impl Message<'_, cn_proc_event> {
pub fn event(&self) -> Event {
self.event.into()
}
}
impl From<proc_event> for Event {
fn from(e: proc_event) -> Self {
unsafe {
match e.what {
PROC_EVENT_NONE => Event::None,
PROC_EVENT_FORK => (&e.event_data.fork).into(),
PROC_EVENT_EXEC => (&e.event_data.exec).into(),
PROC_EVENT_UID => (&e.event_data.uid).into(),
PROC_EVENT_GID => (&e.event_data.gid).into(),
PROC_EVENT_SID => (&e.event_data.sid).into(),
PROC_EVENT_PTRACE => (&e.event_data.ptrace).into(),
PROC_EVENT_COMM => (&e.event_data.comm).into(),
PROC_EVENT_COREDUMP => (&e.event_data.coredump).into(),
PROC_EVENT_EXIT => (&e.event_data.exit).into(),
}
}
}
}
impl From<&fork_proc_event> for Event {
fn from(e: &fork_proc_event) -> Self {
Event::Fork(Fork {
parent: (e.parent_pid, e.parent_tgid).into(),
child: (e.child_pid, e.child_tgid).into(),
})
}
}
impl From<&exec_proc_event> for Event {
fn from(e: &exec_proc_event) -> Self {
Event::Exec((e.process_pid, e.process_tgid).into())
}
}
impl From<&uid_proc_event> for Event {
fn from(e: &uid_proc_event) -> Self {
Event::UID((e.process_pid, e.process_tgid).into(), e.ruid, e.euid)
}
}
impl From<&gid_proc_event> for Event {
fn from(e: &gid_proc_event) -> Self {
Event::GID((e.process_pid, e.process_tgid).into(), e.rgid, e.egid)
}
}
impl From<&sid_proc_event> for Event {
fn from(e: &sid_proc_event) -> Self {
Event::SID((e.process_pid, e.process_tgid).into())
}
}
impl From<&ptrace_proc_event> for Event {
fn from(e: &ptrace_proc_event) -> Self {
Event::PTrace(PTrace {
process: (e.process_pid, e.process_tgid).into(),
tracer: (e.tracer_pid, e.tracer_tgid).into(),
})
}
}
impl From<&comm_proc_event> for Event {
fn from(e: &comm_proc_event) -> Self {
let proc = (e.process_pid, e.process_tgid).into();
let comm = unsafe { CStr::from_ptr(e.comm.as_ptr()) };
Event::Comm(proc, comm.to_string_lossy().to_string())
}
}
impl From<&coredump_proc_event> for Event {
fn from(e: &coredump_proc_event) -> Self {
Event::Coredump((e.process_pid, e.process_tgid).into())
}
}
impl From<&exit_proc_event> for Event {
fn from(e: &exit_proc_event) -> Self {
Event::Exit(Exit {
process: (e.process_pid, e.process_tgid).into(),
exit_code: e.exit_code,
exit_signal: e.exit_signal,
})
}
}
impl From<(u32, u32)> for Proc {
fn from((pid, tgid): (u32, u32)) -> Self {
Self { pid, tgid }
}
}
unsafe impl Bytes for Subscribe {}