#!/usr/local/bin/perl
# Edit global Kea DHCP options for DHCPv4 or DHCPv6.

use strict;
use warnings;
require './kea-dhcp-lib.pl';    ## no critic
&ReadParse();
our (%in, %text);
&error_setup($text{'eacl_aviol'});

my $ver = $in{'version'} == 6 ? 6 : 4;
my %access = &get_module_acl();
&error("$text{'eacl_np'} $text{'eacl_pedit'.$ver}")
	if (!$access{'edit'.$ver});
my ($c, $root, $data, $err) = &kea_read_dhcp_config($ver);
&error($err) if ($err);

# Render one global settings form for either Dhcp4 or Dhcp6. Each tab writes
# back to the same JSON root object, so the save handler can update all fields
# in one pass without losing hidden tab values.
&ui_print_header(undef, &text('options_title', $ver), "", undef, 1, 1);
print &kea_comment_loss_warning($c);
print &ui_alert_box($text{'dhcp6_ra_warn'}, "warn", undef, undef, "")
	if ($ver == 6);
print &ui_form_start("save_options.cgi", "post");
print &ui_hidden("version", $ver);

my @tabs = (
	[ 'interfaces', $text{'tab_interfaces'} ],
	[ 'storage', $text{'tab_storage'} ],
	[ 'logging', $text{'tab_logging'} ],
	[ 'ddns_sender', $text{'tab_ddns_sender'} ],
	[ 'timers', $text{'tab_timers'} ],
	[ 'options', $text{'tab_options'} ],
	[ 'advanced', $text{'tab_advanced'} ],
	);
print &ui_tabs_start(\@tabs, "mode", $in{'mode'} || "interfaces", 1);

# Interfaces decide whether Kea listens at all. The DHCPv4 socket mode is kept
# beside the interface list because it only affects packet capture on DHCPv4.
print &ui_tabs_start_tab("mode", "interfaces");
print &ui_div($text{'interfaces_desc'});
my $ifconf = ref($root->{'interfaces-config'}) eq 'HASH' ?
	$root->{'interfaces-config'} : { };
my $ifaces = ref($ifconf->{'interfaces'}) eq 'ARRAY' ?
	join(" ", @{$ifconf->{'interfaces'}}) : "";
print &ui_table_start($text{'interfaces_title'}, "width=100%", 4);
print &ui_table_row(&kea_field_hlink('interfaces', $text{'interfaces_list'}),
	&ui_textbox("interfaces", $ifaces, 60));
if ($ver == 4) {
	print &ui_table_row(&kea_field_hlink('dhcp-socket-type',
					     $text{'interfaces_socket'}),
		&ui_select("dhcp-socket-type", $ifconf->{'dhcp-socket-type'} || "",
			[ [ "", $text{'socket_default'} ],
			  [ "raw", $text{'socket_raw'} ],
			  [ "udp", $text{'socket_udp'} ] ]));
	}
print &ui_table_end();
print &ui_tabs_end_tab("mode", "interfaces");

# Storage and control sockets are global daemon settings, not subnet settings.
print &ui_tabs_start_tab("mode", "storage");
print &ui_div($text{'storage_desc'});
my $lease = ref($root->{'lease-database'}) eq 'HASH' ?
	$root->{'lease-database'} : { };
print &ui_table_start($text{'lease_database'}, "width=100%", 4);
print &ui_table_row(&kea_field_hlink('lease-database-type', $text{'lease_type'}),
	&ui_textbox("lease_type", $lease->{'type'} || "", 20));
print &ui_table_row(&kea_field_hlink('lfc-interval',
				     $text{'lease_lfc_interval'}),
	&ui_textbox("lease_lfc_interval", $lease->{'lfc-interval'} || "", 12));
print &ui_table_row(&kea_field_hlink('lease-database-name',
				     $text{'lease_name'}),
	&ui_textbox("lease_name", $lease->{'name'} || "", 30));
print &ui_table_row(&kea_field_hlink('lease-database-host',
				     $text{'lease_host'}),
	&ui_textbox("lease_host", $lease->{'host'} || "", 30));
print &ui_table_row(&kea_field_hlink('lease-database-port',
				     $text{'lease_port'}),
	&ui_textbox("lease_port", $lease->{'port'} || "", 8));
print &ui_table_row(&kea_field_hlink('lease-database-user',
				     $text{'lease_user'}),
	&ui_textbox("lease_user", $lease->{'user'} || "", 24));
my $password_note = $lease->{'password'} ?
	" ".&ui_tag('small', $text{'secret_keep_blank'}, {
		'style' => 'color:var(--text-color-light, #777)' }) : "";
print &ui_table_row(&kea_field_hlink('lease-database-password',
				     $text{'lease_password'}),
	&ui_password("lease_password", "", 24).$password_note);
print &ui_table_end();

my $socket = ref($root->{'control-socket'}) eq 'HASH' ?
	$root->{'control-socket'} : { };
print &ui_table_start($text{'control_socket'}, "width=100%", 4);
print &ui_table_row(&kea_field_hlink('control-socket-type',
				     $text{'control_socket_type'}),
	&ui_select("control_socket_type", $socket->{'socket-type'} || "",
		[ [ "", $text{'socket_default'} ],
		  [ "unix", "Unix" ] ]));
print &ui_table_row(&kea_field_hlink('control-socket-name',
				     $text{'control_socket_name'}),
	&ui_textbox("control_socket_name", $socket->{'socket-name'} || "", 50));
print &ui_table_end();
print &ui_tabs_end_tab("mode", "storage");

# Logger settings live at the daemon root, beside lease database and timers.
print &ui_tabs_start_tab("mode", "logging");
print &ui_div($text{'logging_desc'});
print &ui_subheading($text{'logging_loggers'});
&kea_logger_rows($root->{'loggers'}, "log_");
print &ui_tabs_end_tab("mode", "logging");

# DHCP-DDNS sender settings control whether this daemon submits name-change
# requests to the standalone D2 daemon. They are distinct from D2's own
# listener/zones/keys settings.
print &ui_tabs_start_tab("mode", "ddns_sender");
print &ui_div(&text('ddns_sender_settings_desc', $ver));
my $ddns = ref($root->{'dhcp-ddns'}) eq 'HASH' ?
	$root->{'dhcp-ddns'} : { };
my $bool_opts = [
	[ "", $text{'inherit_default'} ],
	[ "true", $text{'yes'} ],
	[ "false", $text{'no'} ],
	];
print &ui_table_start($text{'ddns_sender_connectivity'}, "width=100%", 4);
print &ui_table_row(&kea_field_hlink('ddns-enable-updates',
				     $text{'ddns_enable_updates'}),
	&ui_select("ddns_enable_updates",
		&kea_bool_value($ddns->{'enable-updates'}), $bool_opts));
print &ui_table_row(&kea_field_hlink('ddns-server-ip',
				     $text{'ddns_server_ip'}),
	&ui_textbox("ddns_server_ip", $ddns->{'server-ip'} || "", 24));
print &ui_table_row(&kea_field_hlink('ddns-server-port',
				     $text{'ddns_server_port'}),
	&ui_textbox("ddns_server_port",
		    defined($ddns->{'server-port'}) ? $ddns->{'server-port'} : "",
		    8));
print &ui_table_row(&kea_field_hlink('ddns-sender-ip',
				     $text{'ddns_sender_ip'}),
	&ui_textbox("ddns_sender_ip", $ddns->{'sender-ip'} || "", 24));
print &ui_table_row(&kea_field_hlink('ddns-sender-port',
				     $text{'ddns_sender_port'}),
	&ui_textbox("ddns_sender_port",
		    defined($ddns->{'sender-port'}) ? $ddns->{'sender-port'} : "",
		    8));
print &ui_table_row(&kea_field_hlink('ddns-max-queue-size',
				     $text{'ddns_max_queue_size'}),
	&ui_textbox("ddns_max_queue_size",
		    defined($ddns->{'max-queue-size'}) ?
			$ddns->{'max-queue-size'} : "", 10));
print &ui_table_row(&kea_field_hlink('ncr-protocol',
				     $text{'ddns_ncr_protocol'}),
	&ui_select("ddns_ncr_protocol", $ddns->{'ncr-protocol'} || "",
		&kea_select_options($ddns->{'ncr-protocol'},
				    $text{'socket_default'}, 'UDP')));
print &ui_table_row(&kea_field_hlink('ncr-format',
				     $text{'ddns_ncr_format'}),
	&ui_select("ddns_ncr_format", $ddns->{'ncr-format'} || "",
		&kea_select_options($ddns->{'ncr-format'},
				    $text{'socket_default'}, 'JSON')));
print &ui_table_end();

print &ui_table_start($text{'ddns_sender_behavior'}, "width=100%", 4);
my %ddns_bool_labels = (
	'ddns-send-updates' => $text{'ddns_send_updates'},
	'ddns-override-no-update' => $text{'ddns_override_no_update'},
	'ddns-override-client-update' => $text{'ddns_override_client_update'},
	'ddns-update-on-renew' => $text{'ddns_update_on_renew'},
	);
foreach my $k ('ddns-send-updates', 'ddns-override-no-update',
	       'ddns-override-client-update', 'ddns-update-on-renew') {
	print &ui_table_row(&kea_field_hlink($k, $ddns_bool_labels{$k}),
		&ui_select($k, &kea_bool_value($root->{$k}), $bool_opts));
	}
print &ui_table_row(&kea_field_hlink('ddns-replace-client-name',
				     $text{'ddns_replace_client_name'}),
	&ui_select("ddns-replace-client-name",
		$root->{'ddns-replace-client-name'} || "",
		&kea_select_options($root->{'ddns-replace-client-name'},
				    $text{'socket_default'},
				    'never', 'when-present',
				    'when-not-present', 'always')));
my %ddns_text_labels = (
	'ddns-generated-prefix' => $text{'ddns_generated_prefix'},
	'ddns-qualifying-suffix' => $text{'ddns_qualifying_suffix'},
	'ddns-conflict-resolution-mode' => $text{'ddns_conflict_resolution_mode'},
	'hostname-char-set' => $text{'hostname_char_set'},
	'hostname-char-replacement' => $text{'hostname_char_replacement'},
	);
foreach my $k ('ddns-generated-prefix', 'ddns-qualifying-suffix',
	       'ddns-conflict-resolution-mode', 'hostname-char-set',
	       'hostname-char-replacement') {
	print &ui_table_row(&kea_field_hlink($k, $ddns_text_labels{$k}),
		&ui_textbox($k, defined($root->{$k}) ? $root->{$k} : "", 32));
	}
print &ui_table_end();
print &ui_tabs_end_tab("mode", "ddns_sender");

# Timer defaults apply only when shared networks or subnets do not override.
print &ui_tabs_start_tab("mode", "timers");
print &ui_div($text{'timers_desc'});
print &ui_table_start($text{'options_timers'}, "width=100%", 4);
foreach my $k ('renew-timer', 'rebind-timer', 'valid-lifetime',
	       'min-valid-lifetime', 'max-valid-lifetime') {
	print &ui_table_row(&kea_field_hlink($k),
		&ui_textbox($k, defined($root->{$k}) ? $root->{$k} : "", 12));
	}
print &ui_table_row(&kea_field_hlink('preferred-lifetime'),
	&ui_textbox("preferred-lifetime",
		    defined($root->{'preferred-lifetime'}) ? $root->{'preferred-lifetime'} : "", 12))
	if ($ver == 6);
print &ui_table_end();
print &ui_tabs_end_tab("mode", "timers");

# Common options get named fields; everything else remains editable in the
# additional option-data table below them.
print &ui_tabs_start_tab("mode", "options");
print &ui_div($text{'options_desc'});
&kea_common_option_rows($root->{'option-data'}, $ver, "common_");
&kea_option_data_section($root->{'option-data'}, "opt_", $ver, 1);
print &ui_tabs_end_tab("mode", "options");

# Advanced fields are valid Kea globals but are easy to misuse, so keep them
# away from the everyday options page.
print &ui_tabs_start_tab("mode", "advanced");
print &ui_div(&text('global_advanced_desc', $ver));
print &ui_table_start($text{'global_advanced'}, "width=100%", 4);
if ($ver == 4) {
	print &ui_table_row(&kea_field_hlink('authoritative'),
		&ui_select("authoritative", &kea_bool_value($root->{'authoritative'}),
			[ [ "", $text{'inherit_default'} ],
			  [ "true", $text{'yes'} ],
			  [ "false", $text{'no'} ] ]));
	}
&kea_advanced_option_rows($root->{'option-data'}, $ver, "adv_");
if ($ver == 4) {
	foreach my $k ('next-server', 'server-hostname', 'boot-file-name') {
		print &ui_table_row(&kea_field_hlink($k),
			&ui_textbox($k, defined($root->{$k}) ? $root->{$k} : "", 40));
		}
	}
print &ui_table_end();
print &ui_tabs_end_tab("mode", "advanced");
print &ui_tabs_end();

print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("index.cgi?mode=dhcp$ver", $text{'index_return'});
