Fix start/stop buttons

This commit is contained in:
Joe Cooper
2026-09-05 23:24:33 -05:00
parent e0b8113348
commit 3e91407f81
7 changed files with 125 additions and 7 deletions

View File

@@ -36,7 +36,7 @@ print ui_table_row(
foreach my $a (
qw(view active create setup chains sets rules raw delete
apply bootup import clear quick quick_ip quick_port
apply bootup service import clear quick quick_ip quick_port
quick_service quick_forward manual)
)
{
@@ -61,7 +61,7 @@ else {
}
foreach my $a (
qw(view active create setup chains sets rules raw delete
apply bootup import clear quick quick_ip quick_port
apply bootup service import clear quick quick_ip quick_port
quick_service quick_forward manual)
)
{

View File

@@ -10,6 +10,7 @@ raw=1
delete=1
apply=1
bootup=1
service=1
import=1
clear=1
quick=1

View File

@@ -854,14 +854,11 @@ if ($partial) {
print $rules_html;
my $init_support = foreign_check("init") && check_acl('bootup') &&
nftables_service_status() ? 1 : 0;
if (
@tables &&
(check_acl('active') ||
check_acl('setup') ||
check_manual_acl() ||
$init_support)
check_manual_acl())
)
{
print ui_hr();
@@ -881,10 +878,35 @@ if (
$text{'index_edit_manual'},
$text{'index_edit_manualdesc'}
) if (check_manual_acl());
print ui_buttons_end();
}
# Service controls, shown whether or not any rules are saved yet. Without
# them there is no way to see that the service is stopped or disabled, which
# is the normal state on a system that has never had a ruleset
my $svc = foreign_check("init") ? nftables_service_status() : 0;
my $can_service = $svc && check_acl('service');
my $can_bootup = $svc && check_acl('bootup');
if ($can_service || $can_bootup) {
print ui_hr();
print ui_buttons_start();
if ($can_service) {
if (nftables_service_running()) {
my $desc = $text{'index_stopdesc'};
$desc .= " ".$text{'index_stopflush'}
if (nftables_service_stop_flushes());
print ui_buttons_row("stop.cgi", $text{'index_stop'},
$desc);
}
else {
print ui_buttons_row("start.cgi", $text{'index_start'},
$text{'index_startdesc'});
}
}
print ui_buttons_row("bootup.cgi", $text{'index_bootup'},
$text{'index_bootupdesc'},
undef, ui_yesno_radio("boot", nftables_started_at_boot()))
if ($init_support);
if ($can_bootup);
print ui_buttons_end();
}

View File

@@ -93,6 +93,13 @@ quick_edup=An equivalent quick rule for $1 already exists.
quick_failed=Failed to save and apply quick rule: $1
index_unapply=Revert Configuration
index_unapplydesc=Click this button to reset the configuration listed above to the one that is currently active.
index_start=Start Firewall
index_startdesc=Load the saved nftables configuration into the kernel by starting the nftables service.
index_stop=Stop Firewall
index_stopdesc=Stop the nftables service.
index_stopflush=On this system stopping the service flushes the entire kernel ruleset, including tables belonging to other software.
start_err=Failed to start the nftables service
stop_err=Failed to stop the nftables service
index_bootup=Activate at Boot
index_bootupdesc=Change whether the system nftables service loads the saved rules at boot time or not.
bootup_einit=This system does not support boot-time service management from Webmin.
@@ -393,6 +400,7 @@ acl_raw=Edit raw rule text
acl_delete=Delete tables, chains and sets
acl_apply=Apply saved configuration
acl_bootup=Enable firewall at boot
acl_service=Start and stop the firewall service
acl_import=Import active tables
acl_clear=Clear active tables
acl_quick=Use quick controls

View File

@@ -287,6 +287,59 @@ init::disable_at_boot(nftables_service_name());
undef($nftables_service_status_cache);
}
# nftables_service_running()
# Returns true if the system nftables service has its ruleset loaded
sub nftables_service_running
{
return 0 if (!nftables_service_status());
foreign_require("init", "init-lib.pl");
no warnings 'once';
if (($init::init_mode || "") eq "systemd") {
return init::is_active_systemd(
init::action_unit(nftables_service_name())) ? 1 : 0;
}
my $file = init::action_filename(nftables_service_name());
return 0 if (!$file || !-x $file);
return init::action_running($file) == 1 ? 1 : 0;
}
# nftables_service_stop_flushes()
# Returns true if stopping the service flushes the whole kernel ruleset. Most
# distributions do exactly that, which takes out tables belonging to other
# software as well, so the admin is warned before doing it
sub nftables_service_stop_flushes
{
my $unit_file = nftables_service_unit_file();
return 0 if (!$unit_file);
my $data = read_file_contents($unit_file);
return 0 if (!$data);
foreach my $l (split(/\r?\n/, $data)) {
next if ($l !~ /^\s*ExecStop\s*=/);
return 1 if ($l =~ /flush\s+ruleset/);
}
return 0;
}
# start_nftables_service()
# Starts the system nftables service, loading the saved ruleset
sub start_nftables_service
{
foreign_require("init", "init-lib.pl");
my ($ok, $err) = init::start_action(nftables_service_name());
undef($nftables_service_status_cache);
return $ok ? undef : $err;
}
# stop_nftables_service()
# Stops the system nftables service
sub stop_nftables_service
{
foreign_require("init", "init-lib.pl");
my ($ok, $err) = init::stop_action(nftables_service_name());
undef($nftables_service_status_cache);
return $ok ? undef : $err;
}
# legacy_nftables_rules_files()
# Returns the private rules files that releases before the switch to the
# system nftables configuration wrote to

17
nftables/start.cgi Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/perl
# start.cgi
# Start the system nftables service
require './nftables-lib.pl'; ## no critic
use strict;
use warnings;
our (%text);
error_setup($text{'start_err'});
assert_acl('service');
nftables_service_status() || error($text{'bootup_eservice'});
my $err = start_nftables_service();
error($err) if ($err);
webmin_log("start");
redirect("index.cgi");

17
nftables/stop.cgi Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/perl
# stop.cgi
# Stop the system nftables service
require './nftables-lib.pl'; ## no critic
use strict;
use warnings;
our (%text);
error_setup($text{'stop_err'});
assert_acl('service');
nftables_service_status() || error($text{'bootup_eservice'});
my $err = stop_nftables_service();
error($err) if ($err);
webmin_log("stop");
redirect("index.cgi");