nell 0.3.0

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

use std::fmt;
use std::os::raw::{c_char, c_int};
use super::conn::cn_msg;

pub const PROC_CN_MCAST_LISTEN: u32 = 1;
pub const PROC_CN_MCAST_IGNORE: u32 = 2;

#[repr(C, packed)]
#[derive(Copy, Clone, Debug)]
pub struct cn_proc_event {
    pub cn:    cn_msg,
    pub event: proc_event,
}

#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct proc_event {
    pub what:         what,
    pub cpu:          u32,
    pub timestamp_ns: u64,
    pub event_data:   event_data,
}

#[repr(u32)]
#[derive(Clone, Copy, Debug)]
pub enum what {
    PROC_EVENT_NONE     = 0x00000000,
    PROC_EVENT_FORK     = 0x00000001,
    PROC_EVENT_EXEC     = 0x00000002,
    PROC_EVENT_UID      = 0x00000004,
    PROC_EVENT_GID      = 0x00000040,
    PROC_EVENT_SID      = 0x00000080,
    PROC_EVENT_PTRACE   = 0x00000100,
    PROC_EVENT_COMM     = 0x00000200,
    PROC_EVENT_COREDUMP = 0x40000000,
    PROC_EVENT_EXIT     = 0x80000000,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub union event_data {
    pub ack:      ack,
    pub fork:     fork_proc_event,
    pub exec:     exec_proc_event,
    pub uid:      uid_proc_event,
    pub gid:      gid_proc_event,
    pub sid:      sid_proc_event,
    pub ptrace:   ptrace_proc_event,
    pub comm:     comm_proc_event,
    pub coredump: coredump_proc_event,
    pub exit:     exit_proc_event,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct ack {
    pub err: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct fork_proc_event {
    pub parent_pid:  u32,
    pub parent_tgid: u32,
    pub child_pid:   u32,
    pub child_tgid:  u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct exec_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct uid_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub ruid:         u32,
    pub euid:         u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct gid_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub rgid:         u32,
    pub egid:         u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct sid_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct ptrace_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub tracer_pid:   u32,
    pub tracer_tgid:  u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct comm_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub comm:         [c_char; 16],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct coredump_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct exit_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub exit_code:    u32,
    pub exit_signal:  u32,
}

impl Default for what {
    fn default() -> Self {
        what::PROC_EVENT_NONE
    }
}

impl Default for event_data {
    fn default() -> Self {
        Self { ack: ack { err: 0 } }
    }
}

impl fmt::Debug for proc_event {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let event_data = unsafe {
            let data = &self.event_data;
            match self.what {
                what::PROC_EVENT_NONE     => &"NONE"        as &dyn fmt::Debug,
                what::PROC_EVENT_FORK     => &data.fork     as &dyn fmt::Debug,
                what::PROC_EVENT_EXEC     => &data.exec     as &dyn fmt::Debug,
                what::PROC_EVENT_UID      => &data.uid      as &dyn fmt::Debug,
                what::PROC_EVENT_GID      => &data.gid      as &dyn fmt::Debug,
                what::PROC_EVENT_SID      => &data.sid      as &dyn fmt::Debug,
                what::PROC_EVENT_PTRACE   => &data.ptrace   as &dyn fmt::Debug,
                what::PROC_EVENT_COMM     => &data.comm     as &dyn fmt::Debug,
                what::PROC_EVENT_COREDUMP => &data.coredump as &dyn fmt::Debug,
                what::PROC_EVENT_EXIT     => &data.exit     as &dyn fmt::Debug,
            }
        };

        f.debug_struct("proc_event")
            .field("what",         &self.what)
            .field("cpu",          &self.cpu)
            .field("timestamp_ns", &self.timestamp_ns)
            .field("event_data",   event_data)
            .finish()
    }
}