Various Shorewall changes by Paul Gear
authorJamie Cameron <jcameron@webmin.com>
Thu, 2 Aug 2007 20:14:11 +0000 (20:14 +0000)
committerJamie Cameron <jcameron@webmin.com>
Thu, 2 Aug 2007 20:14:11 +0000 (20:14 +0000)
14 files changed:
shorewall/CHANGELOG
shorewall/delete.cgi
shorewall/down.cgi
shorewall/edit.cgi
shorewall/editcmt.cgi
shorewall/index.cgi
shorewall/lang/en
shorewall/list.cgi
shorewall/manual_form.cgi
shorewall/module.info
shorewall/save.cgi
shorewall/savecmt.cgi
shorewall/shorewall-lib.pl
shorewall/up.cgi

index 95c78ee..f93f071 100644 (file)
@@ -1,3 +1,10 @@
+---- Changes since 1.351 ----
+Corrected name to "Shoreline Firewall".
+Correctly determine Shorewall version for beta releases.
+Corrected zones file support on version 3 or greater when IPSECFILE=ipsec.
+Added bug compatibility with IPSECFILE on Shorewall 3.4.0-3.4.4.
+Added support for renaming firewall zone.
+Added support for editing of params & shorewall.conf.
 ---- Changes since 1.140 ----
 Added buttons for adding rules or other table entries above or below an existing entry.
 Added support for OpenVPN and generic tunnels.
index 22de01c..753914f 100755 (executable)
@@ -1,11 +1,10 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # Delete a bunch of table rows
 
 require './shorewall-lib.pl';
 &ReadParse();
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-$pfunc = $in{'table'}."_parser";
-$pfunc = "standard_parser" if (!defined(&$pfunc));
+$pfunc = &get_parser_func(\%in);
 &error_setup($text{'delete_err'});
 @d = split(/\0/, $in{'d'});
 scalar(@d) || &error($text{'delete_enone'});
index 5ed20a1..c101d67 100755 (executable)
@@ -1,13 +1,11 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # down.cgi
 # Move a row in a table down
 
 require './shorewall-lib.pl';
 &ReadParse();
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-
-$pfunc = $in{'table'}."_parser";
-$pfunc = "standard_parser" if (!defined(&$pfunc));
+$pfunc = &get_parser_func(\%in);
 &lock_table($in{'table'});
 &swap_table_rows($in{'table'}, $pfunc, $in{'idx'}, $in{'idx'}+1);
 &unlock_table($in{'table'});
index 8e74423..ae865ab 100755 (executable)
@@ -1,12 +1,13 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # edit.cgi
 # Display a form for editing or creating a table entry
 
 require './shorewall-lib.pl';
 &ReadParse();
+&get_clean_table_name(\%in);
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
 if ($in{'new'}) {
-       &ui_print_header(undef, $text{$in{'table'}."_create"}, "");
+       &ui_print_header(undef, $text{$in{'tableclean'}."_create"}, "");
        if ($in{'before'} ne '') {
                $msg = &text('edit_before', $in{'before'}+1);
                }
@@ -16,9 +17,8 @@ if ($in{'new'}) {
        print "<center><font size=+1>$msg</font></center>\n" if ($msg);
        }
 else {
-       &ui_print_header(undef, $text{$in{'table'}."_edit"}, "");
-       $pfunc = $in{'table'}."_parser";
-       $pfunc = "standard_parser" if (!defined(&$pfunc));
+       &ui_print_header(undef, $text{$in{'tableclean'}."_edit"}, "");
+       $pfunc = &get_parser_func(\%in);
        @table = &read_table_file($in{'table'}, $pfunc);
        $row = $table[$in{'idx'}];
        }
@@ -31,10 +31,10 @@ print "<input type=hidden name=before value='$in{'before'}'>\n";
 print "<input type=hidden name=after value='$in{'after'}'>\n";
 
 print "<table border width=100%>\n";
-print "<tr $tb> <td><b>",$text{$in{'table'}."_header"},"</b></td> </tr>\n";
+print "<tr $tb> <td><b>",$text{$in{'tableclean'}."_header"},"</b></td> </tr>\n";
 print "<tr $cb> <td><table width=100%>\n";
 
-$ffunc = $in{'table'}."_form";
+$ffunc = $in{'tableclean'}."_form";
 &$ffunc(@$row);
 
 print "</table></td></tr></table>\n";
@@ -51,5 +51,5 @@ print "</table>\n";
 
 print "</form>\n";
 
-&ui_print_footer("list.cgi?table=$in{'table'}", $text{$in{'table'}."_return"});
+&ui_print_footer("list.cgi?table=$in{'table'}", $text{$in{'tableclean'}."_return"});
 
index d4dde12..183b769 100755 (executable)
@@ -1,16 +1,16 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # Display a form for editing or creating a comment
 
 require './shorewall-lib.pl';
 &ReadParse();
+&get_clean_table_name(\%in);
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
 if ($in{'new'}) {
        &ui_print_header(undef, $text{"comment_create"}, "");
        }
 else {
        &ui_print_header(undef, $text{"comment_edit"}, "");
-       $pfunc = $in{'table'}."_parser";
-       $pfunc = "standard_parser" if (!defined(&$pfunc));
+       $pfunc = &get_parser_func(\%in);
        @table = &read_table_file($in{'table'}, $pfunc);
        $row = $table[$in{'idx'}];
        }
@@ -33,5 +33,5 @@ else {
                             [ "delete", $text{'delete'} ] ]);
        }
 
-&ui_print_footer("list.cgi?table=$in{'table'}", $text{$in{'table'}."_return"});
+&ui_print_footer("list.cgi?table=$in{'table'}", $text{$in{'tableclean'}."_return"});
 
index 60cbe0c..803d121 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # index.cgi
 # Display icons for the various shorewall configuration files
 
@@ -18,7 +18,7 @@ else {
 
        &ui_print_header(undef, $text{'index_title'}, "", undef, 1, 1, 0,
                &help_search_link("shorewall", "doc", "google"),
-               undef, undef, &text('index_version', $shorewall_version));
+               undef, undef, &text('index_version', &get_printable_version($shorewall_version)));
 
        if (!-d $config{'config_dir'}) {
                # Config dir not found!
@@ -29,7 +29,7 @@ else {
        else {
                # Just show the file icons
                @files = grep { &can_access($_) } @shorewall_files;
-               @titles = map { $text{$_."_title"}."<br>($_)" } @files;
+               @titles = map { $text{&clean_name($_)."_title"}."<br>($_)" } @files;
                @links = map { "list.cgi?table=".$_ } @files;
                @icons = map { "images/".$_.".gif" } @files;
                &icons_table(\@links, \@titles, \@icons, 4);
index 2000bd3..e050169 100644 (file)
@@ -417,3 +417,29 @@ log_start=Started firewall
 log_refresh=Refreshed firewall
 log_restart=Restarted firewall
 log_clear=Cleared firewall
+
+shorewall_conf_title=Master configuration file
+shorewall_conf_desc=This page allows you to configure the global configuration variables.  NOTE: Changing the order of variables here is not recommended if you wish to preserve the relative position of comments in the configuration file.
+shorewall_conf_add=Add a new configuration variable.
+shorewall_conf_none=No shorewall configuration found.
+shorewall_conf_0=Variable
+shorewall_conf_1=Value
+shorewall_conf_return=configuration variables list
+shorewall_conf_edit=Edit configuration variable
+shorewall_conf_create=Create configuration variable
+shorewall_conf_header=Configuration variable details
+shorewall_conf_err=Failed to save configuration variable
+shorewall_conf_varname=Invalid variable name (must be a valid shell variable name)
+
+params_title=Custom parameters
+params_desc=This page allows you to configure Shorewall's custom parameters.  NOTE: Changing the order of parameters here is not recommended if you wish to preserve the relative position of comments in the configuration file.
+params_add=Add a new custom parameter.
+params_none=No custom parameters found.
+params_0=Parameter
+params_1=Value
+params_return=custom parameters list
+params_edit=Edit custom parameter
+params_create=Create custom parameter
+params_header=Custom parameter details
+params_err=Failed to save custom parameter
+params_varname=Invalid parameter name (must be a valid shell variable name)
index dec2931..1f12718 100755 (executable)
@@ -1,28 +1,30 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # list.cgi
 # Display the contents of some table
 
 require './shorewall-lib.pl';
 &ReadParse();
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-&ui_print_header(undef, $text{$in{'table'}."_title"}, "");
+&get_clean_table_name(\%in);
+&ui_print_header(undef, $text{$in{'tableclean'}."_title"}, "");
 
-$desc = $text{$in{'table'}."_desc"};
+$desc = $text{$in{'tableclean'}."_desc"};
 print "$desc<p>\n" if ($desc);
 
-$pfunc = $in{'table'}."_parser";
-$pfunc = "standard_parser" if (!defined(&$pfunc));
+$pfunc = &get_parser_func(\%in);
 @table = &read_table_file($in{'table'}, $pfunc);
-$cfunc = $in{'table'}."_columns";
+$cfunc = $in{'tableclean'}."_columns";
 $cols = &$cfunc() if (defined(&$cfunc));
-$nfunc = $in{'table'}."_colnames";
+$nfunc = $in{'tableclean'}."_colnames";
+#&debug_message("cfunc = $cfunc");
+#&debug_message("nfunc = $nfunc");
 if (defined(&$nfunc)) {
        @colnames = &$nfunc();
        }
 else {
        @colnames = ( );
-       for($j=0; defined($cols) ? ($j<$cols) : ($text{$in{'table'}."_".$j}); $j++) {
-               push(@colnames, $text{$in{'table'}."_".$j});
+       for($j=0; defined($cols) ? ($j<$cols) : ($text{$in{'tableclean'}."_".$j}); $j++) {
+               push(@colnames, $text{$in{'tableclean'}."_".$j});
                }
        }
 
@@ -30,7 +32,7 @@ else {
 @links = ( &select_all_link("d"),
           &select_invert_link("d"),
           "<a href='edit.cgi?table=$in{'table'}&new=1'>".
-           $text{$in{'table'}."_add"}."</a>" );
+           $text{$in{'tableclean'}."_add"}."</a>" );
 if (&version_atleast(3, 3, 3) && &indexof($in{'table'}, @comment_tables) >= 0) {
        push(@links, "<a href='editcmt.cgi?table=$in{'table'}&new=1'>".
                     $text{"comment_add"}."</a>");
@@ -48,7 +50,7 @@ if (@table) {
                $text{'list_add'}
                ], undef, 0, [ "width=5" ]);
 
-       $rfunc = $in{'table'}."_row";
+       $rfunc = $in{'tableclean'}."_row";
        for($i=0; $i<@table; $i++) {
                @t = @{$table[$i]};
                local @cols;
@@ -102,7 +104,7 @@ if (@table) {
        print &ui_columns_end();
        }
 else {
-       print "<b>",$text{$in{'table'}."_none"},"</b><p>\n";
+       print "<b>",$text{$in{'tableclean'}."_none"},"</b><p>\n";
        shift(@links); shift(@links);
        }
 print &ui_links_row(\@links);
index 49220f1..1523fd1 100755 (executable)
@@ -1,10 +1,11 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # Display the contents of a table file
 
 require './shorewall-lib.pl';
 &ReadParse();
+&get_clean_table_name(\%in);
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-&ui_print_header(undef, $text{$in{'table'}."_title"}, "");
+&ui_print_header(undef, $text{$in{'tableclean'}."_title"}, "");
 
 $file = "$config{'config_dir'}/$in{'table'}";
 $in{'table'} =~ /\.\./ && &error($text{'manual_efile'});
@@ -23,4 +24,4 @@ print "<input type=submit value='$text{'save'}'>\n";
 print "<input type=reset value='$text{'manual_reset'}'>\n";
 print "</form>\n";
 
-&ui_print_footer("list.cgi?table=$in{'table'}", $text{$in{'table'}."_return"});
+&ui_print_footer("list.cgi?table=$in{'table'}", $text{$in{'tableclean'}."_return"});
index 8608c78..53e8474 100644 (file)
@@ -1,8 +1,8 @@
-name=Shorewall
-desc=Shorewall Firewall
+name=Shoreline
+desc=Shoreline Firewall
 category=net
 os_support=*-linux
 depends=syslog
-longdesc=Lets you edit the most useful tables of the simple Shoreline Firewall
-desc_ca=Tallafocs Shorewall
-desc_es=Cortafuegos Shorewall
+longdesc=Lets you edit the most useful tables of the Shoreline Firewall
+desc_ca=Tallafocs Shoreline
+desc_es=Cortafuegos Shoreline
index 5f908db..2c9fb6d 100755 (executable)
@@ -1,13 +1,13 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # save.cgi
 # Updated, modify or delete a table entry
 
 require './shorewall-lib.pl';
 &ReadParse();
+&get_clean_table_name(\%in);
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-$pfunc = $in{'table'}."_parser";
-$pfunc = "standard_parser" if (!defined(&$pfunc));
-&error_setup($text{$in{'table'}."_err"});
+$pfunc = &get_parser_func(\%in);
+&error_setup($text{$in{'tableclean'}."_err"});
 
 &lock_table($in{'table'});
 if ($in{'delete'}) {
@@ -16,9 +16,9 @@ if ($in{'delete'}) {
        }
 else {
        # Validate inputs
-       $vfunc = $in{'table'}."_validate";
+       $vfunc = $in{'tableclean'}."_validate";
        @row = &$vfunc();
-       $jfunc = $in{'table'}."_join";
+       $jfunc = $in{'tableclean'}."_join";
        if (defined(&$jfunc)) {
                $line = &$jfunc(@row);
                }
index bd80c66..c7dfd1f 100755 (executable)
@@ -1,11 +1,10 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # Updated, modify or delete a comment
 
 require './shorewall-lib.pl';
 &ReadParse();
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-$pfunc = $in{'table'}."_parser";
-$pfunc = "standard_parser" if (!defined(&$pfunc));
+$pfunc = &get_parser_func(\%in);
 &error_setup($text{"comment_err"});
 
 &lock_table($in{'table'});
index 9c717fe..a3d1d73 100644 (file)
@@ -1,6 +1,8 @@
 # shorewall-lib.pl
 # Common functions for the shorewall configuration files
-# XXX rule sections
+# FIXME:
+# - rule sections
+# - read_shorewall_config & standard_parser do not allow quoted comment characters
 
 do '../web-lib.pl';
 &init_config();
@@ -8,6 +10,8 @@ do '../ui-lib.pl';
 
 # Get the version
 $shorewall_version = &get_shorewall_version(0);
+%shorewall_config = &read_shorewall_config();
+#&dump_shorewall_config();
 
 # get access permissions
 %access = &get_module_acl();
@@ -15,10 +19,18 @@ $shorewall_version = &get_shorewall_version(0);
 @shorewall_files = ( 'zones', 'interfaces', 'policy', 'rules', 'tos',
                     'masq', 'nat', 'proxyarp', 'routestopped',
                     'tunnels', 'hosts', 'blacklist',
-                    ( &version_atleast(2, 3) ? ( 'providers' ) : ( ) ) );
+                    ( &version_atleast(2, 3) ? ( 'providers' ) : ( ) ),
+                    'params', 'shorewall.conf',
+);
 @comment_tables = ( 'masq', 'nat', 'rules', 'tcrules' );
 
-# version_atleast(v1, v2, v3)
+sub debug_message
+{
+       print STDERR scalar(localtime).": shorewall-lib: @_\n";
+}
+
+# version_atleast(v1, v2, v3, ...)
+# - Check if the Shorewall version is greater than or equal to the one supplied.
 sub version_atleast
 {
 local @vsp = split(/\./, $shorewall_version);
@@ -30,6 +42,54 @@ for($i=0; $i<@vsp || $i<@_; $i++) {
 return 1;      # same!
 }
 
+sub read_shorewall_config
+{
+       local @ret;
+       open(SHOREWALL_CONF, "$config{'config_dir'}/shorewall.conf");
+       while (<SHOREWALL_CONF>) {
+               chomp;
+               s/\r//;
+               s/#.*$//;
+               @F = split( /=/, $_, 2 );
+               next if $#F != 1;
+               push @ret, ( $F[0], $F[1] );
+       }
+       close(SHOREWALL_CONF);
+       return @ret;
+}
+
+# dump_shorewall_config()
+# - Debugging code
+sub dump_shorewall_config
+{
+       for (sort keys %shorewall_config) {
+               print STDERR "$_=$shorewall_config{$_}\n";
+       }
+}
+
+# shorewall_config(var)
+sub shorewall_config
+{
+       if (exists $shorewall_config{$_[0]}  &&  defined $shorewall_config{$_[0]}) {
+               return $shorewall_config{$_[0]};
+       }
+       return '';
+}
+
+# return true if new zones format is in use
+sub new_zones_format
+{
+       # Shorewall 3.4.0 - 3.4.4 have a bug that prevents the old format from being used.
+       if (&version_atleast(3, 4)  &&  !&version_atleast(3, 4, 5)) {
+               return 1;
+       }
+       # Zones table is in new format in Shorewall 3, unless shorewall.conf has IPSECFILE=ipsec
+       if (!&version_atleast(3)  ||  &shorewall_config('IPSECFILE') eq 'ipsec') {
+               return 0;
+       }
+       return 1;
+}
+
 # read_table_file(table, &parserfunc)
 sub read_table_file
 {
@@ -244,6 +304,7 @@ sub unlock_table
 &unlock_file("$config{'config_dir'}/$_[0]");
 }
 
+# parser for whitespace-separated config files
 sub standard_parser
 {
 local $l = $_[0];
@@ -253,6 +314,52 @@ return undef if ($sp[0] eq "SECTION");
 return @sp ? \@sp : undef;
 }
 
+# parser for shell-style config files
+sub config_parser
+{
+    local $l = $_[0];
+    $l =~ s/#.*$//;
+    local @sp = split(/=/, $l, 2);
+    return @sp ? \@sp : undef;
+}
+
+# determine which parser function to use
+sub get_parser_func
+{
+    local $hashref = $_[0];
+    &get_clean_table_name($hashref);
+    &debug_message("table = $hashref->{'table'}, pfunc = $pfunc");
+    local $pfunc = $hashref->{'tableclean'}."_parser";
+    if (!defined(&$pfunc)) {
+       if ($hashref->{'tableclean'} =~ /^(params|shorewall_conf)$/) {
+           $pfunc = "config_parser";
+       }
+       else {
+           $pfunc = "standard_parser";
+       }
+    }
+    &debug_message("table = $hashref->{'table'}, pfunc = $pfunc");
+    return $pfunc;
+}
+
+# ensure that the passed string contains only characters valid in shell variable identifiers
+sub clean_name
+{
+    local $str = $_[0];
+    $str =~ s/\W/_/g;
+    return $str;
+}
+
+# get a table name that is clean enough to use as a function prefix
+sub get_clean_table_name
+{
+    local $hashref = $_[0];
+    if (!exists hashref->{'tableclean'}) {
+       $hashref->{'tableclean'} = &clean_name($in{'table'});
+       &debug_message("table = " . $hashref->{'table'} . ", tableclean = " . $hashref->{'tableclean'});
+    }
+}
+
 # zone_field(name, value, othermode, simplemode)
 sub zone_field
 {
@@ -276,7 +383,7 @@ elsif ($_[3] == 0) {
        $found = !$_[1] || $_[1] eq 'all' || &is_fw($_[1]);
        }
 foreach $z (@ztable) {
-       if (&version_atleast(3)) {
+       if (&new_zones_format()) {
                printf "<option value=%s %s>%s\n",
                        $z->[0], $_[1] eq $z->[0] ? "selected" : "", $z->[0];
                }
@@ -317,7 +424,7 @@ print "</select>\n";
 # Given a zone name, returns a description
 sub convert_zone
 {
-if (&version_atleast(3)) {
+if (&new_zones_format()) {
        # No descriptions in shorewall 3
        return $_[0];
        }
@@ -347,17 +454,21 @@ else {
 }
 
 # is_fw(zone)
+# - Checks if the supplied zone is the firewall zone.
+#   Now handles renaming of firewall zone in shorewall.conf.
 sub is_fw
 {
-return $_[0] eq '$FW' || $_[0] eq 'fw';
+       local $fw = &shorewall_config('FW');
+       $fw = 'fw' if ($fw eq '');
+       return $_[0] eq '$FW' || $_[0] eq $fw;
 }
 
 ################################# zones #######################################
 
 sub zones_parser
 {
-if (&version_atleast(3)) {
-       # Zones table is in new format in Shorewall 3
+if (&new_zones_format()) {
+       # New format
        local $l = $_[0];
        $l =~ s/#.*$//;
        local @r = split(/\s+/, $l);
@@ -378,12 +489,12 @@ else {
 
 sub zones_columns
 {
-return &version_atleast(3) ? 2 : 3;
+return &new_zones_format() ? 2 : 3;
 }
 
 sub zones_row
 {
-if (&version_atleast(3)) {
+if (&new_zones_format()) {
        return ( $_[0], $text{'zones_'.$_[1]} || $_[1] );
        }
 else {
@@ -393,7 +504,7 @@ else {
 
 sub zones_colnames
 {
-if (&version_atleast(3)) {
+if (&new_zones_format()) {
        return ( $text{'zones_0'}, $text{'zones_1new'} );
        }
 else {
@@ -403,7 +514,7 @@ else {
 
 sub zones_form
 {
-if (&version_atleast(3)) {
+if (&new_zones_format()) {
        # Shorewall 3 zones format
        print "<tr> <td><b>$text{'zones_0'}</b></td>\n";
        print "<td>",&ui_textbox("id", $_[0], 8),"</td>\n";
@@ -440,7 +551,7 @@ sub zones_validate
 {
 $in{'id'} =~ /^\S+$/ || &error($text{'zones_eid'});
 &is_fw($in{'id'}) && &error($text{'zones_efwid'});
-if (&version_atleast(3)) {
+if (&new_zones_format()) {
        # Parse new format
        $in{'opts'} =~ /^\S*$/ || &error($text{'zones_eopts'});
        $in{'opts_in'} =~ /^\S*$/ || &error($text{'zones_eopts_in'});
@@ -1506,6 +1617,64 @@ return ( $in{'name'}, $in{'number'}, $in{'mark'},
         $in{'copy'} || "-" );
 }
 
+################################ shorewall.conf ##################################
+
+sub conf_form
+{
+    local $msg1 = shift;
+    local $msg2 = shift;
+    local ($var, $val, $dummy) = @_;
+
+    &debug_message( "var = $var, val = $val");
+
+    $var =~ s/"/&#34;/g;
+    print "<tr><td><b>$msg1</b></td>\n";
+    print "<td><input name=var size=50 value=\"$var\"></td></tr>\n";
+
+    $val =~ s/"/&#34;/g;
+    print "<tr><td><b>$msg2</b></td>\n";
+    print "<td><input name=val size=50 value=\"$val\"></td></tr>\n";
+
+    print "</td></tr>\n";
+}
+
+sub shorewall_conf_columns
+{
+    return 2;
+}
+
+sub shorewall_conf_form
+{
+    &conf_form($text{'shorewall_conf_0'}, $text{'shorewall_conf_1'}, @_);
+}
+
+sub shorewall_conf_validate
+{
+    &debug_message("invar = $in{'var'}");
+    &error($text{'shorewall_conf_varname'}) unless $in{'var'} =~ /^\w+$/;
+    return ($in{'var'}.'='.$in{'val'});
+}
+
+################################ params ##################################
+
+sub params_columns
+{
+    return 2;
+}
+
+sub params_form
+{
+    &conf_form($text{'params_0'}, $text{'params_1'}, @_);
+}
+
+sub params_validate
+{
+    &debug_message("invar = $in{'var'}");
+    &error($text{'params_varname'}) unless $in{'var'} =~ /^\w+$/;
+    return ($in{'var'}.'='.$in{'val'});
+}
+
+
 #############################################################################
 
 # can_access(file)
@@ -1582,6 +1751,9 @@ foreach my $a ($config{'config_dir'}, $config{'macros'}) {
 return &unique(@rv);
 }
 
+$BETA_STR = "-Beta";
+$BETA_NUM = "\.0000\.";
+
 # get_shorewall_version(nocache)
 sub get_shorewall_version
 {
@@ -1591,9 +1763,10 @@ if (!$nocache && open(VERSION, "$module_config_directory/version")) {
        chop($version = <VERSION>);
        close(VERSION);
        }
-else {
+if (!$version) {
        local $out = `$config{'shorewall'} version 2>&1`;
        $out =~ s/\r//g;
+       $out =~ s/$BETA_STR/$BETA_NUM/i;                # Convert beta string to version number.
        if ($out =~ /(\n|^)([0-9\.]+)\n/) {
                $version = $2;
                }
@@ -1601,6 +1774,13 @@ else {
 return $version;
 }
 
+sub get_printable_version($)
+{
+       local $out = $_[0];
+       $out =~ s/$BETA_NUM/$BETA_STR/i;                # Convert version number back to string.
+       return $out;
+}
+
 sub list_protocols
 {
 local @stdprotos = ( 'tcp', 'udp', 'icmp' );
@@ -1637,5 +1817,7 @@ foreach $o (keys %opts) {
 print "</table>\n";
 }
 
+&debug_message("shorewall-lib.pl loaded");
+
 1;
 
index c0a2489..8148636 100755 (executable)
@@ -1,13 +1,11 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 # up.cgi
 # Move a row in a table up
 
 require './shorewall-lib.pl';
 &ReadParse();
 &can_access($in{'table'}) || &error($text{'list_ecannot'});
-
-$pfunc = $in{'table'}."_parser";
-$pfunc = "standard_parser" if (!defined(&$pfunc));
+$pfunc = &get_parser_func(\%in);
 &lock_table($in{'table'});
 &swap_table_rows($in{'table'}, $pfunc, $in{'idx'}, $in{'idx'}-1);
 &unlock_table($in{'table'});