Hi,

please find attached a patch that implements domain specific hooks.
It would be great if this patch made it into a new release of ferm.

Thanks for maintaining ferm im Debian
Peter

PS: Now that 2.0.7 is out fixing a few - IMHO - important bugs,
    what about a new Debian release?
-- 
Peter Marschall
[email protected]
From e4ea33b742a89d432e52088159bbb03d9029d047 Mon Sep 17 00:00:00 2001
From: Peter Marschall <[email protected]>
Date: Sun, 24 Jan 2010 19:04:35 +0100
Subject: [PATCH] support domain-specific hooks

Allow hooks to be defined either globally or within a domain block.
The hooks defined within a domain specific block get called at the
start resp. end of the domain.

These domain-specific hooks allow calling external programs that are
specific to one domain only when ferm updates this domain.
Consider e.g. the case of routing IPv4 but not IPv6 addresses.

Signed-off-by: Peter Marschall <[email protected]>
---
 doc/ferm.pod |    4 ++++
 src/ferm     |   38 +++++++++++++++++++++++++++-----------
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/doc/ferm.pod b/doc/ferm.pod
index adcef03..0248aee 100644
--- a/doc/ferm.pod
+++ b/doc/ferm.pod
@@ -1614,6 +1614,10 @@ the command afterwards.  "flush" hooks are run after ferm has flushed
 the firewall rules (option --flush).  You may install any number of
 hooks.
 
+Hooks can be either global or domain-specific. In the latter case
+simply define them directly within a domain block.
+
+
 =head1 BUILT-IN FUNCTIONS
 
 There are several built-in functions which you might find useful.
diff --git a/src/ferm b/src/ferm
index 7973340..6c5e5d1 100755
--- a/src/ferm
+++ b/src/ferm
@@ -54,7 +54,7 @@ $VERSION .= '~git';
 use vars qw(%option);
 
 ## hooks
-use vars qw(@pre_hooks @post_hooks @flush_hooks);
+use vars qw(%pre_hooks %post_hooks %flush_hooks);
 
 ## parser variables
 # $script: current script file
@@ -521,29 +521,44 @@ die unless @stack == 2;
 # enable/disable hooks depending on --flush
 
 if ($option{flush}) {
-    undef @pre_hooks;
-    undef @post_hooks;
+    undef %pre_hooks;
+    undef %post_hooks;
 } else {
-    undef @flush_hooks;
+    undef %flush_hooks;
 }
 
 # execute all generated rules
 my $status;
 
-foreach my $cmd (@pre_hooks) {
+# call global pre hooks
+foreach my $cmd (@{$pre_hooks{''}}) {
     print LINES "$cmd\n" if $option{lines};
     system($cmd) unless $option{noexec};
 }
 
 while (my ($domain, $domain_info) = each %domains) {
     next unless $domain_info->{enabled};
+
+    # call domain-specific pre hooks
+    foreach my $cmd (@{$pre_hooks{$domain}}) {
+        print LINES "$cmd\n" if $option{lines};
+        system($cmd) unless $option{noexec};
+    }
+
     my $s = $option{fast} &&
       defined $domain_info->{tools}{'tables-restore'}
       ? execute_fast($domain_info) : execute_slow($domain_info);
     $status = $s if defined $s;
+
+    # call domain-specific post/flush hooks
+    foreach my $cmd (@{$post_hooks{$domain}}, @{$flush_hooks{$domain}}) {
+        print LINES "$cmd\n" if $option{lines};
+        system($cmd) unless $option{noexec};
+    }
 }
 
-foreach my $cmd (@post_hooks, @flush_hooks) {
+# call global post/flush hooks
+foreach my $cmd (@{$post_hooks{''}}, @{$flush_hooks{''}}) {
     print LINES "$cmd\n" if $option{lines};
     system($cmd) unless $option{noexec};
 }
@@ -1593,21 +1608,22 @@ sub enter($$) {
 
             if ($keyword eq '@hook') {
                 error('"hook" must be the first token in a command')
-                  if exists $rule{domain};
+                  if (exists $rule{table});
 
+                my $domain = $rule{domain} ? $rule{domain} : '';
                 my $position = getvar();
                 my $hooks;
                 if ($position eq 'pre') {
-                    $hooks = \...@pre_hooks;
+                    $hooks = \$pre_hooks{$domain};
                 } elsif ($position eq 'post') {
-                    $hooks = \...@post_hooks;
+                    $hooks = \$post_hooks{$domain};
                 } elsif ($position eq 'flush') {
-                    $hooks = \...@flush_hooks;
+                    $hooks = \$flush_hooks{$domain};
                 } else {
                     error("Invalid hook position: '$position'");
                 }
 
-                push @$hooks, getvar();
+                push @{$$hooks}, getvar();
 
                 expect_token(';');
                 next;
-- 
1.6.5

Reply via email to