1use std::fs::File;
101use std::io::{BufRead, BufReader};
102use std::sync::mpsc;
103use std::sync::mpsc::{Receiver, Sender};
104use std::thread;
105
106pub use crate::data_link::DataLink;
107use crate::fields::fields::Fields;
108use crate::fields::ip_header::{get_dest, get_proto, get_source};
109use crate::fields::transport_header::{get_dport, get_icmp_type, get_sport};
110pub use crate::firewall_action::FirewallAction;
111pub use crate::firewall_direction::FirewallDirection;
112pub use crate::firewall_error::FirewallError;
113use crate::firewall_rule::FirewallRule;
114use crate::logs::log_entry::LogEntry;
115use crate::logs::logger::log;
116
117mod data_link;
118mod fields;
119mod firewall_action;
120mod firewall_direction;
121mod firewall_error;
122mod firewall_option;
123mod firewall_rule;
124mod logs;
125mod utils;
126
127#[derive(Debug)]
132pub struct Firewall {
133 rules: Vec<FirewallRule>,
134 enabled: bool,
135 policy_in: FirewallAction,
136 policy_out: FirewallAction,
137 tx: Sender<LogEntry>,
138 data_link: DataLink,
139 log: bool,
140}
141
142impl Firewall {
143 const COMMENT: char = '#';
144
145 pub fn new(file_path: &str) -> Result<Self, FirewallError> {
179 let (tx, rx): (Sender<LogEntry>, Receiver<LogEntry>) = mpsc::channel();
180 thread::Builder::new()
181 .name("logger".to_string())
182 .spawn(move || {
183 log(&rx);
184 })
185 .unwrap();
186
187 let mut firewall = Firewall {
188 rules: Vec::new(),
189 enabled: true,
190 policy_in: FirewallAction::default(),
191 policy_out: FirewallAction::default(),
192 tx,
193 data_link: DataLink::default(),
194 log: true,
195 };
196
197 firewall.update_rules(file_path)?;
198
199 Ok(firewall)
200 }
201
202 #[must_use]
236 pub fn resolve_packet(&self, packet: &[u8], direction: FirewallDirection) -> FirewallAction {
237 if !self.enabled {
238 return FirewallAction::ACCEPT;
239 }
240
241 let mut action_opt = None;
242
243 let fields = Fields::new(packet, self.data_link);
245
246 for rule in &self.rules {
248 if rule.matches_packet(&fields, &direction) {
249 if rule.quick {
250 action_opt = Some(rule.action);
251 break;
252 } else if action_opt.is_none() {
253 action_opt = Some(rule.action);
254 }
255 }
256 }
257
258 let action = action_opt.unwrap_or(match direction {
259 FirewallDirection::IN => self.policy_in,
260 FirewallDirection::OUT => self.policy_out,
261 });
262
263 if self.log {
264 let log_entry = LogEntry::new(&fields, direction, action);
266 self.tx
267 .send(log_entry)
268 .expect("the firewall logger routine aborted");
269 }
270
271 action
272 }
273
274 pub fn update_rules(&mut self, file_path: &str) -> Result<(), FirewallError> {
301 let mut rules = Vec::new();
302 let file = File::open(file_path).unwrap();
303
304 for (l, firewall_rule_str_result) in BufReader::new(file).lines().enumerate() {
305 let Ok(firewall_rule_str_raw) = firewall_rule_str_result else {
306 continue;
307 };
308 let firewall_rule_str = firewall_rule_str_raw.trim();
309 if !firewall_rule_str.starts_with(Self::COMMENT) && !firewall_rule_str.is_empty() {
310 rules.push(FirewallRule::new(l + 1, firewall_rule_str)?);
311 }
312 }
313
314 self.rules = rules;
315 Ok(())
316 }
317
318 pub fn disable(&mut self) {
343 self.enabled = false;
344 }
345
346 pub fn enable(&mut self) {
370 self.enabled = true;
371 }
372
373 pub fn policy_in(&mut self, policy: FirewallAction) {
390 self.policy_in = policy;
391 }
392
393 pub fn policy_out(&mut self, policy: FirewallAction) {
410 self.policy_out = policy;
411 }
412
413 pub fn data_link(&mut self, data_link: DataLink) {
433 self.data_link = data_link;
434 }
435
436 pub fn log(&mut self, log: bool) {
455 self.log = log;
456 }
457}
458
459#[cfg(test)]
460mod tests {
461 use std::sync::mpsc;
462 use std::sync::mpsc::{Receiver, Sender};
463
464 use crate::utils::raw_packets::test_packets::{
465 ARP_PACKET, ICMP_PACKET, TCP_PACKET, UDP_IPV6_PACKET,
466 };
467 use crate::{DataLink, Firewall, LogEntry};
468 use crate::{FirewallAction, FirewallDirection, FirewallRule};
469
470 const TEST_FILE_1: &str = "./samples/firewall_for_tests_1.txt";
471 const TEST_FILE_2: &str = "./samples/firewall_for_tests_2.txt";
472 const TEST_FILE_3: &str = "./samples/firewall_for_tests_3.txt";
473
474 fn get_error_file_path(name: &str) -> String {
475 format!("./samples/firewall_for_tests_error_{name}.txt")
476 }
477
478 #[test]
479 fn test_new_firewall_from_file_1() {
480 let rules = vec![
481 FirewallRule::new(1,"OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080").unwrap(),
482 FirewallRule::new(2,"OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080 --dport 1,2,2000").unwrap(),
483 FirewallRule::new(3, "+ OUT DENY --source 192.168.200.135-192.168.200.140 --sport 6700:6800,8080 --dport 1,2,2000").unwrap(),
484 FirewallRule::new(4,"OUT REJECT --source 192.168.200.135 --sport 6750:6800,8080 --dest 192.168.200.21 --dport 1,2,2000").unwrap(),
485 FirewallRule::new(5,"IN ACCEPT --source 2.1.1.2 --dest 2.1.1.1 --proto 1 --icmp-type 8").unwrap(),
486 FirewallRule::new(6,"+ IN REJECT --source 2.1.1.2 --dest 2.1.1.1 --proto 1 --icmp-type 8").unwrap(),
487 FirewallRule::new(7,"IN ACCEPT --source 2.1.1.2 --dest 2.1.1.1 --proto 1 --icmp-type 9").unwrap(),
488 FirewallRule::new(8,"IN ACCEPT --source 2.1.1.2 --dest 2.1.1.1 --proto 58 --icmp-type 8").unwrap(),
489 FirewallRule::new(9,"OUT REJECT").unwrap(),
490 FirewallRule::new(10,"IN ACCEPT").unwrap(),
491 ];
492
493 let mut firewall_from_file = Firewall::new(TEST_FILE_1).unwrap();
494
495 assert_eq!(firewall_from_file.rules, rules);
496 assert!(firewall_from_file.enabled);
497 assert_eq!(firewall_from_file.policy_out, FirewallAction::default());
498 assert_eq!(firewall_from_file.policy_in, FirewallAction::default());
499
500 firewall_from_file.disable();
501 firewall_from_file.policy_in(FirewallAction::DENY);
502 firewall_from_file.policy_out(FirewallAction::REJECT);
503 assert!(!firewall_from_file.enabled);
504 assert_eq!(firewall_from_file.policy_in, FirewallAction::DENY);
505 assert_eq!(firewall_from_file.policy_out, FirewallAction::REJECT);
506
507 firewall_from_file.enable();
508 assert!(firewall_from_file.enabled);
509 }
510
511 #[test]
512 fn test_firewall_determine_action_for_packets_file_1() {
513 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
514 firewall.policy_in(FirewallAction::DENY);
515 firewall.policy_out(FirewallAction::ACCEPT);
516
517 assert_eq!(firewall.data_link, DataLink::Ethernet);
518
519 assert_eq!(
521 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::IN),
522 FirewallAction::ACCEPT
523 );
524 assert_eq!(
525 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
526 FirewallAction::DENY
527 );
528
529 assert_eq!(
531 firewall.resolve_packet(&ICMP_PACKET, FirewallDirection::IN),
532 FirewallAction::REJECT
533 );
534 assert_eq!(
535 firewall.resolve_packet(&ICMP_PACKET, FirewallDirection::OUT),
536 FirewallAction::REJECT
537 );
538
539 assert_eq!(
541 firewall.resolve_packet(&ARP_PACKET, FirewallDirection::IN),
542 FirewallAction::ACCEPT
543 );
544 assert_eq!(
545 firewall.resolve_packet(&ARP_PACKET, FirewallDirection::OUT),
546 FirewallAction::REJECT
547 );
548 }
549
550 #[test]
551 fn test_firewall_determine_action_for_packets_file_1_with_data_link_raw_ip() {
552 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
553 firewall.data_link(DataLink::RawIP);
554 firewall.policy_in(FirewallAction::DENY);
555 firewall.policy_out(FirewallAction::ACCEPT);
556
557 assert_eq!(firewall.data_link, DataLink::RawIP);
558
559 assert_eq!(
561 firewall.resolve_packet(&TCP_PACKET[14..], FirewallDirection::IN),
562 FirewallAction::ACCEPT
563 );
564 assert_eq!(
565 firewall.resolve_packet(&TCP_PACKET[14..], FirewallDirection::OUT),
566 FirewallAction::DENY
567 );
568
569 assert_eq!(
571 firewall.resolve_packet(&ICMP_PACKET[14..], FirewallDirection::IN),
572 FirewallAction::REJECT
573 );
574 assert_eq!(
575 firewall.resolve_packet(&ICMP_PACKET[14..], FirewallDirection::OUT),
576 FirewallAction::REJECT
577 );
578 }
579
580 #[test]
581 fn test_firewall_determine_action_for_packets_file_2() {
582 let mut firewall = Firewall::new(TEST_FILE_2).unwrap();
583 firewall.policy_in(FirewallAction::DENY);
584 firewall.policy_out(FirewallAction::ACCEPT);
585
586 assert_eq!(
588 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::IN),
589 FirewallAction::DENY
590 );
591 assert_eq!(
592 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
593 FirewallAction::DENY
594 );
595
596 assert_eq!(
598 firewall.resolve_packet(&ICMP_PACKET, FirewallDirection::IN),
599 FirewallAction::ACCEPT
600 );
601 assert_eq!(
602 firewall.resolve_packet(&ICMP_PACKET, FirewallDirection::OUT),
603 FirewallAction::ACCEPT
604 );
605
606 assert_eq!(
608 firewall.resolve_packet(&ARP_PACKET, FirewallDirection::IN),
609 FirewallAction::DENY
610 );
611 assert_eq!(
612 firewall.resolve_packet(&ARP_PACKET, FirewallDirection::OUT),
613 FirewallAction::ACCEPT
614 );
615 }
616
617 #[test]
618 fn test_firewall_determine_action_for_packets_file_3() {
619 let mut firewall = Firewall::new(TEST_FILE_3).unwrap();
620
621 assert_eq!(
623 firewall.resolve_packet(&UDP_IPV6_PACKET, FirewallDirection::IN),
624 FirewallAction::DENY
625 );
626 assert_eq!(
627 firewall.resolve_packet(&UDP_IPV6_PACKET, FirewallDirection::OUT),
628 FirewallAction::ACCEPT
629 );
630
631 assert_eq!(
633 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::IN),
634 FirewallAction::default()
635 );
636 assert_eq!(
637 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
638 FirewallAction::default()
639 );
640
641 firewall.policy_in(FirewallAction::DENY);
643 firewall.policy_out(FirewallAction::REJECT);
644
645 assert_eq!(
647 firewall.resolve_packet(&UDP_IPV6_PACKET, FirewallDirection::IN),
648 FirewallAction::DENY
649 );
650 assert_eq!(
651 firewall.resolve_packet(&UDP_IPV6_PACKET, FirewallDirection::OUT),
652 FirewallAction::ACCEPT
653 );
654
655 assert_eq!(
657 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::IN),
658 FirewallAction::DENY
659 );
660 assert_eq!(
661 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
662 FirewallAction::REJECT
663 );
664 }
665
666 #[test]
667 fn test_firewall_determine_action_for_packets_file_3_with_data_link_raw_ip() {
668 let mut firewall = Firewall::new(TEST_FILE_3).unwrap();
669 firewall.data_link(DataLink::RawIP);
670
671 assert_eq!(
673 firewall.resolve_packet(&UDP_IPV6_PACKET[14..], FirewallDirection::IN),
674 FirewallAction::DENY
675 );
676 assert_eq!(
677 firewall.resolve_packet(&UDP_IPV6_PACKET[14..], FirewallDirection::OUT),
678 FirewallAction::ACCEPT
679 );
680
681 assert_eq!(
683 firewall.resolve_packet(&TCP_PACKET[14..], FirewallDirection::IN),
684 FirewallAction::default()
685 );
686 assert_eq!(
687 firewall.resolve_packet(&TCP_PACKET[14..], FirewallDirection::OUT),
688 FirewallAction::default()
689 );
690
691 firewall.policy_in(FirewallAction::DENY);
693 firewall.policy_out(FirewallAction::REJECT);
694
695 assert_eq!(
697 firewall.resolve_packet(&UDP_IPV6_PACKET[14..], FirewallDirection::IN),
698 FirewallAction::DENY
699 );
700 assert_eq!(
701 firewall.resolve_packet(&UDP_IPV6_PACKET[14..], FirewallDirection::OUT),
702 FirewallAction::ACCEPT
703 );
704
705 assert_eq!(
707 firewall.resolve_packet(&TCP_PACKET[14..], FirewallDirection::IN),
708 FirewallAction::DENY
709 );
710 assert_eq!(
711 firewall.resolve_packet(&TCP_PACKET[14..], FirewallDirection::OUT),
712 FirewallAction::REJECT
713 );
714 }
715
716 #[test]
717 fn test_firewall_determine_action_for_packets_while_disabled() {
718 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
719 firewall.policy_in(FirewallAction::REJECT); firewall.policy_out(FirewallAction::REJECT); firewall.disable(); assert_eq!(
725 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::IN),
726 FirewallAction::ACCEPT
727 );
728 assert_eq!(
729 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
730 FirewallAction::ACCEPT
731 );
732
733 assert_eq!(
735 firewall.resolve_packet(&ICMP_PACKET, FirewallDirection::IN),
736 FirewallAction::ACCEPT
737 );
738 assert_eq!(
739 firewall.resolve_packet(&ICMP_PACKET, FirewallDirection::OUT),
740 FirewallAction::ACCEPT
741 );
742
743 assert_eq!(
745 firewall.resolve_packet(&ARP_PACKET, FirewallDirection::IN),
746 FirewallAction::ACCEPT
747 );
748 assert_eq!(
749 firewall.resolve_packet(&ARP_PACKET, FirewallDirection::OUT),
750 FirewallAction::ACCEPT
751 );
752 }
753
754 #[test]
755 fn test_firewall_rules_precedence() {
756 let (tx, _rx): (Sender<LogEntry>, Receiver<LogEntry>) = mpsc::channel();
757 let mut firewall = Firewall {
758 rules: vec![],
759 enabled: true,
760 policy_in: Default::default(),
761 policy_out: Default::default(),
762 tx,
763 data_link: Default::default(),
764 log: true,
765 };
766
767 let rules_1 = vec![
768 FirewallRule::new(
770 1,
771 "OUT DENY --source 192.168.200.135 --sport 6700:6800,8080",
772 )
773 .unwrap(),
774 FirewallRule::new(
775 2,
776 "OUT ACCEPT --source 192.168.200.135 --sport 6700:6800,8080",
777 )
778 .unwrap(),
779 FirewallRule::new(
780 3,
781 "OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080",
782 )
783 .unwrap(),
784 ];
785 firewall = Firewall {
786 rules: rules_1,
787 ..firewall
788 };
789 assert_eq!(
790 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
791 FirewallAction::DENY
792 );
793 assert_eq!(
794 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::IN),
795 FirewallAction::default()
796 );
797
798 let rules_2 = vec![
799 FirewallRule::new(
801 1,
802 "+ OUT DENY --source 192.168.200.135 --sport 6700:6800,8080",
803 )
804 .unwrap(),
805 FirewallRule::new(
806 2,
807 "OUT ACCEPT --source 192.168.200.135 --sport 6700:6800,8080",
808 )
809 .unwrap(),
810 FirewallRule::new(
811 3,
812 "OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080",
813 )
814 .unwrap(),
815 ];
816 firewall = Firewall {
817 rules: rules_2,
818 ..firewall
819 };
820 assert_eq!(
821 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
822 FirewallAction::DENY
823 );
824
825 let rules_3 = vec![
826 FirewallRule::new(
828 1,
829 "OUT DENY --source 192.168.200.135 --sport 6700:6800,8080",
830 )
831 .unwrap(),
832 FirewallRule::new(
833 2,
834 "OUT ACCEPT --source 192.168.200.135 --sport 6700:6800,8080",
835 )
836 .unwrap(),
837 FirewallRule::new(
838 3,
839 "+ OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080",
840 )
841 .unwrap(),
842 ];
843 firewall = Firewall {
844 rules: rules_3,
845 ..firewall
846 };
847 assert_eq!(
848 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
849 FirewallAction::REJECT
850 );
851
852 let rules_4 = vec![
853 FirewallRule::new(
855 1,
856 "OUT DENY --source 192.168.200.135 --sport 6700:6800,8080",
857 )
858 .unwrap(),
859 FirewallRule::new(
860 2,
861 "+ OUT ACCEPT --source 192.168.200.135 --sport 6700:6800,8080",
862 )
863 .unwrap(),
864 FirewallRule::new(
865 3,
866 "+ OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080",
867 )
868 .unwrap(),
869 ];
870 firewall = Firewall {
871 rules: rules_4,
872 ..firewall
873 };
874 assert_eq!(
875 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
876 FirewallAction::ACCEPT
877 );
878
879 let rules_5 = vec![
880 FirewallRule::new(
882 1,
883 "+ OUT DENY --source 192.168.200.135 --sport 6700:6800,8080",
884 )
885 .unwrap(),
886 FirewallRule::new(
887 2,
888 "+ OUT ACCEPT --source 192.168.200.135 --sport 6700:6800,8080",
889 )
890 .unwrap(),
891 FirewallRule::new(
892 3,
893 "+ OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080",
894 )
895 .unwrap(),
896 ];
897 firewall = Firewall {
898 rules: rules_5,
899 ..firewall
900 };
901 assert_eq!(
902 firewall.resolve_packet(&TCP_PACKET, FirewallDirection::OUT),
903 FirewallAction::DENY
904 );
905 }
906
907 #[test]
908 fn test_update_firewall_rules() {
909 let rules_before_update = vec![
910 FirewallRule::new(1,"OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080").unwrap(),
911 FirewallRule::new(2,"OUT REJECT --source 192.168.200.135 --sport 6700:6800,8080 --dport 1,2,2000").unwrap(),
912 FirewallRule::new(3,"+ OUT DENY --source 192.168.200.135-192.168.200.140 --sport 6700:6800,8080 --dport 1,2,2000").unwrap(),
913 FirewallRule::new(4,"OUT REJECT --source 192.168.200.135 --sport 6750:6800,8080 --dest 192.168.200.21 --dport 1,2,2000").unwrap(),
914 FirewallRule::new(5,"IN ACCEPT --source 2.1.1.2 --dest 2.1.1.1 --proto 1 --icmp-type 8").unwrap(),
915 FirewallRule::new(6,"+ IN REJECT --source 2.1.1.2 --dest 2.1.1.1 --proto 1 --icmp-type 8").unwrap(),
916 FirewallRule::new(7,"IN ACCEPT --source 2.1.1.2 --dest 2.1.1.1 --proto 1 --icmp-type 9").unwrap(),
917 FirewallRule::new(8,"IN ACCEPT --source 2.1.1.2 --dest 2.1.1.1 --proto 58 --icmp-type 8").unwrap(),
918 FirewallRule::new(9,"OUT REJECT").unwrap(),
919 FirewallRule::new(10,"IN ACCEPT").unwrap(),
920 ];
921
922 let rules_after_update = vec![
923 FirewallRule::new(1, "OUT REJECT --dest 3ffe:507:0:1:200:86ff:fe05:800-3ffe:507:0:1:200:86ff:fe05:08dd --sport 545:560,43,53").unwrap(),
924 FirewallRule::new(2,"+ OUT ACCEPT --dest 3ffe:507:0:1:200:86ff:fe05:800-3ffe:507:0:1:200:86ff:fe05:08dd --sport 545:560,43,53").unwrap(),
925 FirewallRule::new(3,"OUT DENY --dest 3ffe:507:0:1:200:86ff:fe05:800-3ffe:507:0:1:200:86ff:fe05:08dd --proto 17 --sport 545:560,43,53 --dport 2396").unwrap(),
926 FirewallRule::new(4,"OUT REJECT --dest 3ffe:507:0:1:200:86ff:fe05:800-3ffe:507:0:1:200:86ff:fe05:08dd --proto 17 --sport 545:560,43,53 --dport 2395").unwrap(),
927 FirewallRule::new(5,"IN DENY --sport 40:49,53").unwrap(),
928 FirewallRule::new(6,"IN REJECT --sport 40:49,53 --source 3ffe:501:4819::41,3ffe:501:4819::42").unwrap(),
929 ];
930
931 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
932 assert_eq!(firewall.rules, rules_before_update);
933 assert!(firewall.enabled);
934 assert_eq!(firewall.policy_in, FirewallAction::ACCEPT);
935 assert_eq!(firewall.policy_out, FirewallAction::ACCEPT);
936
937 firewall.update_rules(TEST_FILE_3).unwrap();
939
940 assert_eq!(firewall.rules, rules_after_update);
941 assert!(firewall.enabled);
942 assert_eq!(firewall.policy_in, FirewallAction::ACCEPT);
943 assert_eq!(firewall.policy_out, FirewallAction::ACCEPT);
944 }
945
946 #[test]
947 fn test_log_disable() {
948 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
949 assert!(firewall.log);
950 firewall.log(false);
951 assert!(!firewall.log);
952 firewall.log(true);
953 assert!(firewall.log);
954 }
955
956 #[test]
957 fn test_file_error_invalid_dport_value() {
958 let path = &get_error_file_path("invalid_dport_value");
959 let expected = String::from(
960 "Firewall error at line 12 - incorrect value for option '--dport 8.8.8.8'",
961 );
962
963 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
964
965 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
966 assert_eq!(
967 firewall.update_rules(path).unwrap_err().to_string(),
968 expected
969 );
970 }
971
972 #[test]
973 fn test_file_error_invalid_sport_value() {
974 let path = &get_error_file_path("invalid_sport_value");
975 let expected =
976 String::from("Firewall error at line 1 - incorrect value for option '--sport 70000'");
977
978 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
979
980 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
981 assert_eq!(
982 firewall.update_rules(path).unwrap_err().to_string(),
983 expected
984 );
985 }
986
987 #[test]
988 fn test_file_error_invalid_dest_value() {
989 let path = &get_error_file_path("invalid_dest_value");
990 let expected =
991 String::from("Firewall error at line 18 - incorrect value for option '--dest 8080'");
992
993 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
994
995 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
996 assert_eq!(
997 firewall.update_rules(path).unwrap_err().to_string(),
998 expected
999 );
1000 }
1001
1002 #[test]
1003 fn test_file_error_invalid_source_value() {
1004 let path = &get_error_file_path("invalid_source_value");
1005 let expected = String::from(
1006 "Firewall error at line 9 - incorrect value for option '--source 8.8.8.8.7'",
1007 );
1008
1009 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1010
1011 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1012 assert_eq!(
1013 firewall.update_rules(path).unwrap_err().to_string(),
1014 expected
1015 );
1016 }
1017
1018 #[test]
1019 fn test_file_error_invalid_icmp_type_value() {
1020 let path = &get_error_file_path("invalid_icmp_type_value");
1021 let expected = String::from(
1022 "Firewall error at line 7 - incorrect value for option '--icmp-type ciao'",
1023 );
1024
1025 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1026
1027 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1028 assert_eq!(
1029 firewall.update_rules(path).unwrap_err().to_string(),
1030 expected
1031 );
1032 }
1033
1034 #[test]
1035 fn test_file_error_invalid_protocol_value() {
1036 let path = &get_error_file_path("invalid_protocol_value");
1037 let expected =
1038 String::from("Firewall error at line 101 - incorrect value for option '--proto -58'");
1039
1040 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1041
1042 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1043 assert_eq!(
1044 firewall.update_rules(path).unwrap_err().to_string(),
1045 expected
1046 );
1047 }
1048
1049 #[test]
1050 fn test_file_error_invalid_direction() {
1051 let path = &get_error_file_path("invalid_direction");
1052 let expected = String::from("Firewall error at line 4 - incorrect direction 'this'");
1053
1054 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1055
1056 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1057 assert_eq!(
1058 firewall.update_rules(path).unwrap_err().to_string(),
1059 expected
1060 );
1061 }
1062
1063 #[test]
1064 fn test_file_error_invalid_action() {
1065 let path = &get_error_file_path("invalid_action");
1066 let expected =
1067 String::from("Firewall error at line 1 - incorrect action 'DROPTHISPACKETOMG'");
1068
1069 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1070
1071 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1072 assert_eq!(
1073 firewall.update_rules(path).unwrap_err().to_string(),
1074 expected
1075 );
1076 }
1077
1078 #[test]
1079 fn test_file_error_unknown_option() {
1080 let path = &get_error_file_path("unknown_option");
1081 let expected =
1082 String::from("Firewall error at line 3 - the specified option '-dest' doesn't exist");
1083
1084 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1085
1086 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1087 assert_eq!(
1088 firewall.update_rules(path).unwrap_err().to_string(),
1089 expected
1090 );
1091 }
1092
1093 #[test]
1094 fn test_file_error_not_enough_arguments() {
1095 let path = &get_error_file_path("not_enough_arguments");
1096 let expected =
1097 String::from("Firewall error at line 8 - not enough arguments supplied for rule");
1098
1099 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1100
1101 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1102 assert_eq!(
1103 firewall.update_rules(path).unwrap_err().to_string(),
1104 expected
1105 );
1106 }
1107
1108 #[test]
1109 fn test_file_error_empty_option() {
1110 let path = &get_error_file_path("empty_option");
1111 let expected =
1112 String::from("Firewall error at line 20 - the supplied option '--sport' is empty");
1113
1114 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1115
1116 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1117 assert_eq!(
1118 firewall.update_rules(path).unwrap_err().to_string(),
1119 expected
1120 );
1121 }
1122
1123 #[test]
1124 fn test_file_error_duplicated_option() {
1125 let path = &get_error_file_path("duplicated_option");
1126 let expected = String::from(
1127 "Firewall error at line 9 - duplicated option '--dport' for the same rule",
1128 );
1129
1130 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1131
1132 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1133 assert_eq!(
1134 firewall.update_rules(path).unwrap_err().to_string(),
1135 expected
1136 );
1137 }
1138
1139 #[test]
1140 fn test_file_error_not_applicable_icmp_type() {
1141 let path = &get_error_file_path("not_applicable_icmp_type");
1142 let expected = String::from("Firewall error at line 6 - option '--icmp-type' is valid only if '--proto 1' or '--proto 58' is also specified");
1143
1144 assert_eq!(Firewall::new(path).unwrap_err().to_string(), expected);
1145
1146 let mut firewall = Firewall::new(TEST_FILE_1).unwrap();
1147 assert_eq!(
1148 firewall.update_rules(path).unwrap_err().to_string(),
1149 expected
1150 );
1151 }
1152}