nullnet_firewall/
firewall_action.rs

1use std::fmt::{Display, Formatter};
2
3use rusqlite::types::ToSqlOutput;
4use rusqlite::ToSql;
5
6use crate::FirewallError;
7
8/// Action dictated by a firewall rule.
9///
10/// Each firewall rule is associated to a given action.
11#[derive(Default, Copy, Clone, Eq, PartialEq, Debug)]
12pub enum FirewallAction {
13    /// Allows traffic that matches the rule to pass.
14    #[default]
15    ACCEPT,
16    /// Silently blocks traffic that matches the rule.
17    DENY,
18    /// Blocks traffic that matches the rule.
19    ///
20    /// An *ICMP Destination Unreachable* message should be sent back to the traffic source.
21    REJECT,
22}
23
24impl FirewallAction {
25    pub(crate) fn from_str_with_line(l: usize, s: &str) -> Result<Self, FirewallError> {
26        match s {
27            "ACCEPT" => Ok(Self::ACCEPT),
28            "DENY" => Ok(Self::DENY),
29            "REJECT" => Ok(Self::REJECT),
30            x => Err(FirewallError::InvalidAction(l, x.to_owned())),
31        }
32    }
33}
34
35impl Display for FirewallAction {
36    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37        write!(f, "{self:?}")
38    }
39}
40
41impl ToSql for FirewallAction {
42    fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
43        Ok(self.to_string().into())
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use rusqlite::types::ToSqlOutput;
50    use rusqlite::types::Value::Text;
51    use rusqlite::ToSql;
52
53    use crate::{FirewallAction, FirewallError};
54
55    #[test]
56    fn test_firewall_actions_from_str() {
57        assert_eq!(
58            FirewallAction::from_str_with_line(1, "ACCEPT"),
59            Ok(FirewallAction::ACCEPT)
60        );
61        assert_eq!(
62            FirewallAction::from_str_with_line(1, "DENY"),
63            Ok(FirewallAction::DENY)
64        );
65        assert_eq!(
66            FirewallAction::from_str_with_line(1, "REJECT"),
67            Ok(FirewallAction::REJECT)
68        );
69
70        let err = FirewallAction::from_str_with_line(28, "DROP").unwrap_err();
71        assert_eq!(err, FirewallError::InvalidAction(28, "DROP".to_owned()));
72        assert_eq!(
73            err.to_string(),
74            "Firewall error at line 28 - incorrect action 'DROP'"
75        );
76    }
77
78    #[test]
79    fn test_firewall_actions_to_sql() {
80        assert_eq!(
81            FirewallAction::to_sql(&FirewallAction::ACCEPT),
82            Ok(ToSqlOutput::Owned(Text("ACCEPT".to_string())))
83        );
84
85        assert_eq!(
86            FirewallAction::to_sql(&FirewallAction::DENY),
87            Ok(ToSqlOutput::Owned(Text("DENY".to_string())))
88        );
89
90        assert_eq!(
91            FirewallAction::to_sql(&FirewallAction::REJECT),
92            Ok(ToSqlOutput::Owned(Text("REJECT".to_string())))
93        );
94    }
95}