nell 0.3.0

Linux netlink interface
Documentation
// Copyright (C) 2019 - Will Glozer. All rights reserved.

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 {}