More support for native ipfw format
authorJamie Cameron <jcameron@webmin.com>
Wed, 12 Dec 2007 20:52:07 +0000 (20:52 +0000)
committerJamie Cameron <jcameron@webmin.com>
Wed, 12 Dec 2007 20:52:07 +0000 (20:52 +0000)
ipfw/apply.cgi
ipfw/index.cgi
ipfw/ipfw-lib.pl
ipfw/start.pl

index c2ccc3b..bb2e9fd 100755 (executable)
@@ -5,8 +5,7 @@
 require './ipfw-lib.pl';
 &ReadParse();
 &error_setup($text{'apply_err'});
-$rules = &get_config();
-$err = &apply_rules($rules);
+$err = &apply_rules();
 &error($err) if ($err);
 $err = &apply_cluster_configuration();
 &error($err) if ($err);
index ae0b13f..ced7cea 100755 (executable)
@@ -93,23 +93,13 @@ elsif (@$rules && !$in{'reset'}) {
                                  $text{'index_radd'} ], 100, 0,
                                \@widths);
        foreach $r (@$rules) {
+               next if ($r->{'other'});        # Not displayable
                local ($mover, $adder);
-               if ($r->{'index'} >= $lastidx) {
-                       $mover .= "<img src=images/gap.gif>";
-                       }
-               else {
-                       $mover .= "<a href='move.cgi?idx=$r->{'index'}&".
-                                 "down=1'><img src=".
-                                 "images/down.gif border=0></a>";
-                       }
-               if ($r->{'index'} == 0 || $r->{'index'} > $lastidx) {
-                       $mover .= "<img src=images/gap.gif>";
-                       }
-               else {
-                       $mover .= "<a href='move.cgi?idx=$r->{'index'}&".
-                                 "up=1'><img src=images/up.gif ".
-                                 "border=0></a>";
-                       }
+               $mover = &ui_up_down_arrows(
+                       "move.cgi?idx=$r->{'index'}&up=1",
+                       "move.cgi?idx=$r->{'index'}&down=1",
+                       $r->{'index'} != 0 && $r->{'index'} <= $lastidx,
+                       $r->{'index'} < $lastidx);
                if ($r->{'index'} <= $lastidx) {
                        $adder .= "<a href='edit_rule.cgi?new=1&".
                                  "after=$r->{'index'}'>".
index 6a3d029..a32d16c 100644 (file)
@@ -62,23 +62,35 @@ if (open(VERSION, "$module_config_directory/version")) {
 sub get_config
 {
 local $file = $_[0] || $ipfw_file;
+local $fmt = &get_ipfw_format();
 local @rv;
 local $cmt;
-local $lnum = 0;
+local $lnum = -1;
 open(LIST, $file);
 while(<LIST>) {
        ${$_[1]} .= $_ if ($_[1]);
-       if (/^(\d+)\s+(.*)/) {
+       $lnum++;
+       if ($fmt == 1 && !/^add\s+/ && !/^#/) {
+               # Format with 'add' suffixes, with some other directive
+               local $rule = { 'index' => scalar(@rv),
+                                'line' => $lnum-scalar(@cmts),
+                                'eline' => $lnum,
+                               'other' => 1,
+                                'text' => $_ };
+               $cmt = undef;
+               push(@rv, $rule);
+               }
+       elsif (/^(add\s+)?(\d+)\s+(.*)/) {
                # an ipfw rule
                local @cmts = split(/\n/, $cmt);
                local $rule = { 'index' => scalar(@rv),
                                'line' => $lnum-scalar(@cmts),
                                'eline' => $lnum,
-                               'num' => $1,
-                               'text' => $2,
+                               'num' => $2,
+                               'text' => $3,
                                'cmt' => $cmt };
                $cmt = undef;
-               local @w = &split_quoted_string($2);
+               local @w = &split_quoted_string($3);
 
                # Parse counts, if given
                if ($w[0] =~ /^\d+$/) {
@@ -242,21 +254,26 @@ foreach $r (@{$_[0]}) {
 close(LIST);
 }
 
-# rule_lines(&rule, [nocomment])
+# rule_lines(&rule, [no-comment], [no-add])
 # Returns the lines of text to make up a rule
 sub rule_lines
 {
-local ($rule) = @_;
-local @cmts = $_[1] ? ( ) : map { "# $_" } split(/\n/, $rule->{'cmt'});
+local ($rule, $nocmt, $noadd) = @_;
+local @cmts = $nocmt ? ( ) : map { "# $_" } split(/\n/, $rule->{'cmt'});
+local $fmt = &get_ipfw_format();
 if (defined($rule->{'text'})) {
        # Assume un-changed
-       return (@cmts, $rule->{'num'}." ".$rule->{'text'});
+       return (@cmts, (defined($rule->{'num'}) ? $rule->{'num'}." " : "").
+                      $rule->{'text'});
        }
 else {
        # Need to construct
        local @w;
 
        # Add the basic rule parameters
+       if ($fmt == 1 && !$noadd) {
+               push(@w, "add");
+               }
        push(@w, $rule->{'num'});
        push(@w, "set", $rule->{'set'}) if (defined($rule->{'set'}));
        push(@w, "prob", $rule->{'prob'}) if (defined($rule->{'prob'}));
@@ -438,7 +455,7 @@ close(PROTOS);
 return &unique(@stdprotos, @otherprotos);
 }
 
-# apply_rules(&rules)
+# apply_rules([&rules])
 # Apply the supplied firewall rules
 sub apply_rules
 {
@@ -447,16 +464,25 @@ $conf ||= &get_config();
 local $dir = `pwd`;
 chop($dir);
 chdir("/");
-&system_logged("$config{'ipfw'} -f flush >/dev/null 2>&1");
-local $r;
-foreach $r (@$conf) {
-       if ($r->{'num'} != 65535) {     # skip auto-added final rule
-               local ($line) = &rule_lines($r, 1);
-               local $cmd = "$config{'ipfw'} add $line";
-               $out = &backquote_logged("$cmd 2>&1 </dev/null");
-               return "<tt>$cmd</tt> failed : <tt>$out</tt>" if ($?);
+local $fmt = &get_ipfw_format();
+if ($fmt == 0) {
+       # Apply each rule in turn
+       &system_logged("$config{'ipfw'} -f flush >/dev/null 2>&1");
+       local $r;
+       foreach $r (@$conf) {
+               if (!$r->{'other'} &&
+                   $r->{'num'} != 65535) {     # skip auto-added final rule
+                       local ($line) = &rule_lines($r, 1, 1);
+                       local $cmd = "$config{'ipfw'} add $line";
+                       $out = &backquote_logged("$cmd 2>&1 </dev/null");
+                       return "<tt>$cmd</tt> failed : <tt>$out</tt>" if ($?);
+                       }
                }
        }
+else {
+       # The ipfw command can apply the whole file
+       &system_logged("$config{'ipfw'} ".quotemeta($ipfw_file));
+       }
 chdir($dir);
 return undef;
 }
@@ -597,7 +623,8 @@ return 0;
 sub enable_boot
 {
 return 0 if (&check_boot());   # Already on
-if ($has_net_lib && defined(&net::get_rc_conf) && -r "/etc/rc.conf") {
+if ($has_net_lib && defined(&net::get_rc_conf) && &get_ipfw_format() == 1) {
+       # Add to rc.conf
        local %rc = &net::get_rc_conf();
        &lock_file("/etc/rc.conf");
        &net::save_rc_conf('firewall_type', $ipfw_file);
@@ -606,7 +633,10 @@ if ($has_net_lib && defined(&net::get_rc_conf) && -r "/etc/rc.conf") {
        &unlock_file("/etc/rc.conf");
        return 2;
        }
-&create_firewall_init();
+else {
+       # Create init script
+       &create_firewall_init();
+       }
 return 1;
 }
 
@@ -627,4 +657,37 @@ elsif ($mode == 2) {
 return $mode;
 }
 
+# get_ipfw_format()
+# Works out the IPFW file format we should use. Returns 1 for with 'add' at the
+# start, vs 0 for without.
+sub get_ipfw_format
+{
+local $fmt;
+if (open(FILE, $ipfw_file)) {
+       # Check existing format
+       while(<FILE>) {
+               if (/^(\d+)\s/) {
+                       # Numeric line
+                       $fmt = 0;
+                       last;
+                       }
+               elsif (/\S/ && !/^\#/) {
+                       # Add or other directive line
+                       $fmt = 1;
+                       last;
+                       }
+               }
+       close(FILE);
+       return $fmt if (defined($fmt));
+       }
+if (-r "/etc/rc.conf") {
+       # FreeBSD - use it's format
+       return 1;
+       }
+else {
+       # Assume numeric format
+       return 0;
+       }
+}
+
 1;
index 54aeb02..70e0383 100755 (executable)
@@ -5,8 +5,7 @@
 $no_acl_check++;
 require './ipfw-lib.pl';
 &ReadParse();
-$rules = &get_config();
-$err = &apply_rules($rules);
+$err = &apply_rules();
 if ($err) {
        $err =~ s/<[^>]*>//g;
        print STDERR "Failed to enable firewall : $err\n";