linux_audit_parser/
message_type.rs

1#[cfg(feature = "serde")]
2use serde_with::{DeserializeFromStr, SerializeDisplay};
3use std::fmt::{self, Debug, Display};
4use std::str::{self, FromStr};
5
6use thiserror::Error;
7
8use crate::constants::*;
9
10/// Type of an audit message, corresponding to the `type=…` part of
11/// every Linux Audit log line.
12///
13/// The implementation uses the same 32bit unsigned integer values
14/// that are used by the Linux Audit API. Mappings between numeric and
15/// symbolic values is generated using CSV retrieved from the [`Linux
16/// Audit Project`]'s documentation.
17///
18/// [`Linux Audit Project`]: https://github.com/linux-audit/audit-documentation
19#[derive(PartialEq, Eq, Hash, Default, Clone, Copy)]
20#[cfg_attr(feature = "serde", derive(DeserializeFromStr, SerializeDisplay))]
21pub struct MessageType(pub u32);
22
23impl Display for MessageType {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match EVENT_NAMES.get(&(self.0)) {
26            Some(name) => write!(f, "{name}"),
27            None => write!(f, "UNKNOWN[{}]", self.0),
28        }
29    }
30}
31
32impl Debug for MessageType {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match EVENT_NAMES.get(&(self.0)) {
35            Some(name) => write!(f, "MessageType({name})"),
36            None => write!(f, "MessageType({})", self.0),
37        }
38    }
39}
40
41/// The error type returned by [MessageType::from_str]
42#[derive(Debug, Error)]
43pub enum ParseMessageTypeError {
44    #[error("unknown identifier ({0})")]
45    Unknown(String),
46    #[error("malformed UNKNOWN[…] string")]
47    MalformedUnknown,
48    #[error("cannot parse number ({0}): {1}")]
49    Number(String, std::num::ParseIntError),
50}
51
52impl FromStr for MessageType {
53    type Err = ParseMessageTypeError;
54    fn from_str(s: &str) -> Result<Self, Self::Err> {
55        if let Some(id) = EVENT_IDS.get(s.as_bytes()) {
56            Ok(MessageType(*id))
57        } else {
58            let number = s
59                .strip_prefix("UNKNOWN[")
60                .ok_or_else(|| ParseMessageTypeError::Unknown(s.into()))?
61                .strip_suffix("]")
62                .ok_or(ParseMessageTypeError::MalformedUnknown)?;
63            let id = u32::from_str(number)
64                .map_err(|e| ParseMessageTypeError::Number(number.into(), e))?;
65            Ok(MessageType(id))
66        }
67    }
68}
69
70include!(concat!(env!("OUT_DIR"), "/message_type_impl.rs"));
71
72impl MessageType {
73    /// True for messages that are part of multi-part events from
74    /// kernel-space.
75    ///
76    /// This mimics auparse logic as of version 3.0.6
77    pub fn is_multipart(&self) -> bool {
78        (1300..2100).contains(&self.0) || self == &MessageType::LOGIN
79    }
80}