winfw/
lib.rs

1// Licensed under the Apache License, Version 2.0
2// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>
4// All files in the project carrying such notice may not be copied, modified, or distributed
5// except according to those terms.
6use libc::{c_char, c_long, c_ulong};
7use serde::Serialize;
8use std::{
9    fmt::{self, Display, Formatter},
10    vec::Vec,
11};
12
13mod utils;
14use self::utils::{decode_vecs, encode};
15
16mod cfw;
17use cfw::fw_rule_impl;
18
19mod consts;
20pub use self::consts::{Actions, Directions, Protocols};
21
22mod error;
23pub use self::error::Error;
24
25#[derive(Default, Clone, Serialize)]
26#[repr(C)]
27pub struct FwRule {
28    pub name: String,
29    pub description: String,
30    pub app_name: String,
31    pub service_name: String,
32    pub protocol: Protocols,
33    pub icmp_type: String,
34    pub local_ports: String,
35    pub remote_ports: String,
36    pub local_adresses: String,
37    pub remote_addresses: String,
38    pub profile1: String,
39    pub profile2: String,
40    pub profile3: String,
41    pub direction: Directions,
42    pub action: Actions,
43    pub interface_types: String,
44    pub interfaces: String,
45    pub enabled: bool,
46    pub grouping: String,
47    pub edge_traversal: bool,
48}
49
50impl Display for FwRule {
51    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
52        write!(f, "name: {}\ndescription: {}\napplication name: {}\nservice name: {}\nprotocol: {}\nicmp type: {}\nlocal ports: {}\nremote ports: {}\nlocal address: {}\nremote address: {}\nprofiles: {} {} {}\ndirection: {}\naction: {}\ninterfaces types: {}\ninterfaces: {}\nenabled: {}\ngrouping: {}\nedge traversal: {}\n---",
53        self.name,
54        self.description,
55        self.app_name,
56        self.service_name,
57        self.protocol,
58        self.icmp_type,
59        self.local_ports,
60        self.remote_ports,
61        self.local_adresses,
62        self.remote_addresses,
63        self.profile1,
64        self.profile2,
65        self.profile3,
66        self.direction,
67        self.action,
68        self.interfaces,
69        self.interface_types,
70        self.enabled,
71        self.grouping,
72        self.edge_traversal)
73    }
74}
75
76extern "C" {
77    fn getFWRules(
78        rules: &*mut fw_rule_impl,
79        size: *mut c_long,
80        rules_count: *mut c_long,
81    ) -> c_ulong;
82    fn newFWRule(rule: &fw_rule_impl) -> c_ulong;
83    fn delFWRule(rule: *const c_char) -> c_ulong;
84    fn enableFWRule(rule: *const c_char, enabled: c_long) -> c_ulong;
85}
86
87#[no_mangle]
88pub fn get_fw_rules() -> Result<Vec<FwRule>, Error> {
89    //! Gets all the firewal rules configured.
90    //!
91    //! ## Example usage
92    //! ```rust
93    //! use winfw::get_fw_rules;
94    //!
95    //! let rules = get_fw_rules();
96    //! match rules {
97    //!     Err(_) => assert!(false),
98    //!     Ok(_) => {
99    //!         assert!(true)
100    //!    }
101    //! }
102    //! ```
103    let mut required_size = 0;
104    let mut rules_count = 0;
105    let mut rules: *mut fw_rule_impl = std::ptr::null_mut();
106    let mut res = unsafe { getFWRules(&rules, &mut required_size, &mut rules_count) };
107    assert_eq!(res, 8);
108    rules = unsafe { libc::malloc(required_size as usize) } as *mut fw_rule_impl;
109    if rules == std::ptr::null_mut() {
110        return Err(Error(1));
111    }
112    res = unsafe { getFWRules(&rules, &mut required_size, &mut rules_count) };
113    if res != 0 {
114        return Err(Error(1));
115    }
116    let fw_rules_slice = unsafe { std::slice::from_raw_parts_mut(rules, rules_count as usize) };
117    let res = decode_vecs(fw_rules_slice.to_vec());
118    unsafe { libc::free(rules as *mut libc::c_void) };
119    Ok(res)
120}
121
122#[no_mangle]
123pub fn new_fw_rule(rule: &FwRule) -> Result<(), Error> {
124    //! Add and configure a new firewall rule.
125    //!
126    //! ## Example usage
127    //! ```ignore
128    //! use winfw::{new_fw_rule, Actions, FwRule, Protocols};
129    //!
130    //! let mut new_rule = FwRule::default();
131    //! new_rule.name = "TEST_INTERFACE_RULE".to_string();
132    //! new_rule.description = "Allow incoming network traffic over port 2400 coming from LAN interface type".to_string();
133    //! new_rule.grouping = "Test Rule Group".to_string();
134    //! new_rule.grouping = "Test Rule Group".to_string();
135    //! new_rule.local_ports = "2400-2450".to_string();
136    //! new_rule.interface_types = "LAN".to_string();
137    //! new_rule.protocol = Protocols::Tcp;
138    //! new_rule.action = Actions::Allow;
139    //! new_rule.enabled = true;
140    //! match new_fw_rule(&new_rule) {
141    //!     Err(_) => assert!(false),
142    //!     Ok(()) => assert!(true),
143    //! }
144    //! ```
145    let fw_rule: fw_rule_impl = rule.into();
146    let res = unsafe { newFWRule(&fw_rule) };
147    if res != 0 {
148        return Err(Error(res));
149    }
150    Ok(())
151}
152
153#[no_mangle]
154pub fn enable_fw_rule(name: &str) -> Result<(), Error> {
155    //! Enable existing firewall rule.
156    //!
157    //! ## Example usage
158    //! ```ignore
159    //! use winfw::enable_fw_rule;
160    //!
161    //! match enable_fw_rule(&"TEST_INTERFACE_RULE".to_string()) {
162    //!     Err(_) => assert!(false),
163    //!     Ok(()) => assert!(true),
164    //! }
165    //! ```
166    let mut s: [c_char; 1024] = [0; 1024];
167    encode(name, &mut s);
168    let res = unsafe { enableFWRule(s.as_ptr(), 1) };
169    if res != 0 {
170        return Err(Error(res));
171    }
172    Ok(())
173}
174
175#[no_mangle]
176pub fn del_fw_rule(name: &str) -> Result<(), Error> {
177    //! Deletes an existing firewall rule.
178    //!
179    //! ## Example usage
180    //! ```ignore
181    //! use winfw::del_fw_rule;
182    //!
183    //! match del_fw_rule(&"TEST_INTERFACE_RULE".to_string()) {
184    //!     Err(_) => assert!(false),
185    //!     Ok(()) => assert!(true),
186    //! }
187    //! ```
188    let mut s: [c_char; 1024] = [0; 1024];
189    encode(name, &mut s);
190    let res = unsafe { delFWRule(s.as_ptr()) };
191    if res != 0 {
192        return Err(Error(res));
193    }
194    Ok(())
195}
196
197#[no_mangle]
198pub fn disable_fw_rule(name: &str) -> Result<(), Error> {
199    //! Disables an existing firewall rule.
200    //!
201    //! ## Example usage
202    //! ```ignore
203    //! use winfw::disable_fw_rule;
204    //!
205    //! match disable_fw_rule(&"TEST_INTERFACE_RULE".to_string()) {
206    //!     Err(_) => assert!(false),
207    //!     Ok(()) =>  assert!(true),
208    //! }
209    //! ```
210    let mut s: [c_char; 1024] = [0; 1024];
211    encode(name, &mut s);
212    let res = unsafe { enableFWRule(s.as_ptr(), 0) };
213    if res != 0 {
214        return Err(Error(res));
215    }
216    Ok(())
217}
218
219#[cfg(test)]
220mod tests {
221    use super::*;
222
223    #[test]
224    fn test_get_fw_rules() {
225        let rules = get_fw_rules();
226        match rules {
227            Err(_) => assert!(false),
228            Ok(_) => {
229                assert!(true)
230            }
231        }
232    }
233}