📄 save_record.cgi
字号:
#! /usr/bin/perl## B9DDNS - BIND 9 dynamic DNS webmin module.# Copyright (C) 2003 John Horne. <john.horne@plymouth.ac.uk># Copyright (C) 2004 John Horne. <john.horne@plymouth.ac.uk>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.### Creates, deletes or updates a record of some type.#use strict;no strict 'vars';require './b9ddns-lib.pl';my $ipv4_zone = my $ipv4_rec = my $reverse = my $dynamic = my $ttl = 0;my $serial = my $new_serial = my $new = my $i = 0;my $old_rev_dynamic = my $new_rev_dynamic = 0;my $old_rev_serial = my $new_rev_serial = 0;my $only_ttl_changed = 0;my $conf = my $zone = my $view = my $rec = my $origin = '';my $oconf = my $ofile = my $orec = '';my $fwdconf = my $fwdfile = my $fwdrec = '';my $revconf = my $revfile = my $revrec = '';my $value = my $name = my $type = my $file = '';my $sfx = my $zn = my $z = my $v = '';my $rname = my $rtype = my $zone_ref = '';my $rec_name = my $oldname = my $oldvalue = '';my @zone_list = my @recs = my @orecs = ();&ReadParse();%access = &get_module_acl();if ($access{'ro'}) { &terror('master_ero');}$conf = &get_config();if ($in{'view'}) { $view = $conf->[$in{'view'}]; $conf = $view->{'members'};}@zone_list = &find('zone', $conf);$origin = lc($in{'origin'});$origin .= '.' unless ($origin =~ /\.$/o);($zone) = grep { $origin =~ /^$_->{'value'}\.?$/i } @zone_list;unless (&can_edit_zone(\%access, $zone, $view)) { &terror('recs_ecannot');}$file = $in{'file'};$zone_ref = &get_zone_data($zone);$dynamic = $zone_ref->[1];if ($dynamic) { if ($dynamic == 2) { &terror('recs_eupdate'); }}else { &lock_file($config{'chroot'} . &absolute_path($file));}%sd_zones = ();@recs = &get_zone($zone, $file, $origin, undef, $in{'ztype'});## Can we modify the serial number?#$new_serial = &check_serial_number($zone_ref, $zone, \@recs, undef);$new++ if ($in{'new'});$type = $in{'type'};$oldname = lc($in{'oldname'});$oldvalue = lc($in{'oldvalue'});if ($origin =~ /\.(in-addr|ip6)\.arpa\.$/o) { $reverse++; $ipv4_zone++ if ($1 eq 'in-addr');}&error_setup($text{'edit_err'});## Get the old record if necessary.#if (defined($in{'num'})) { $rec = $recs[$in{'num'}]; $rec_name = $rec->{'fqdn'};}else { $rec = $rec_name = undef;}## This is a bit messy but we must check whether we can update the *old*# reverse/forward zone's SOA serial number *before* we remove or change the# reverse/forward record.## Ultimately, and in the worst-case scenario, we shall have to check the serial# number for 3 zones - the old and new reverse zones and the new forward zone.# If any of these fail then the entire operation should be aborted.#if (($in{'rev'} || $in{'fwd'}) && ($oldname !~ /\*/o || $in{'delete'}) && ($in{'delete'} || ! $new)) { if ($in{'rev'}) { ($oconf, $ofile, $orec) = &find_reverse($oldvalue, $oldname); } else { ($oconf, $ofile, $orec) = &find_forward($oldvalue, $oldname, $ipv4_zone); } ($old_rev_serial, $old_rev_dynamic) = &check_rev_serial($oconf);}## For certain record types we must qualify the rdata domain name - for example,# a CNAME record may be stored using abbreviated names as in 'www in cname# fred'. We must do this now in the case of existing dynamic records since# they will require FQDN names being specified, and we may be about to delete# the record. For static zones the conversion, if required, is done later on.#if ($dynamic && ! $new) { $i = &convert_value($type, undef); if ($i >= 0) { $oldvalue = $rec->{'values'}->[$i] = &convert_fqdn(1, $oldvalue, $origin, 1); }}## Check for deleting a record.#if ($in{'delete'}) { # # First check if we are deleting a top-level name. # if ($reverse) { if ($in{'fwd'}) { unless (&check_tld($oldvalue, $oconf, \%access, 'master', $type)) { &terror('edit_tld'); } } } else { unless (&check_tld($rec_name, $origin, \%access, $in{'ztype'}, $type)) { &terror('edit_tld'); } if ($type eq 'DNAME') { unless (&check_sd($rec_name, $origin, \%access, $in{'ztype'}, $type)) { &terror('edit_sd'); } } } &fix_oldtxt_rec() if ($type eq 'TXT'); &delete_record($zone, $file, $rec); &bump_soa_record($zone, \@recs, $new_serial); &delete_rev_rec(); # Delete any reverse or forward record. &unlock_all_files(); &webmin_log('delete', 'record', $origin, $rec); &redirect("edit_recs.cgi?index=$in{'index'}&view=$in{'view'}&type=$in{'redirtype'}&sort=$in{'sort'}&file=${file}&ztype=$in{'ztype'}"); exit;}## Parse the inputs.### Are wildcards allowed in the name? Generally wildcards are accepted for most# record types. They are not allowed for NS and DNAME records. However, we also# restrict the use of wildcards to specific types since their use in other# records could either lead to problems or simply be confusing.#&trim($in{'name'});unless ($in{'name'}) { &terror('edit_emissing');}elsif (! $config{'allow_wild'} && $in{'name'} =~ /\*/o) { &terror('wild_no', $in{'name'});}else { $i = ($type =~ /^(A|AAAA|PTR|MX|CNAME|TXT|RP|LOC|HINFO)$/o); $name = &convert_fqdn(1, $in{'name'}, $origin, 1); if ($reverse) { if ($ipv4_zone) { # IPv4 address. $v = &compress_ip(&arpa_to_ip($name)); $name = &ip_to_arpa($v); } else { # IPv6 address. $v = &ip6arpa_to_net($name); $v = &compress_ip6($v) unless ($type eq 'DNAME'); $name = &net_to_ip6arpa($v); } unless (&valipaddr($v, $origin, 1, $i, 1, $ipv4_zone)) { &terror(($ipv4_zone) ? 'edit_eip' : 'edit_eip6', $in{'name'}); } } else { unless (&valdnsname($name, $i, $origin)) { &terror('edit_ename', $in{'name'}); } }}if ($in{'ttl_def'}) { $ttl = 0;}else { &trim($in{'ttl'}); $ttl = &convert_time(0, $in{'ttl'} . $in{'ttlunit'}) if ($in{'ttl'}); unless ($ttl) { unless ($in{'ttl'}) { $in{'ttl'} = $text{'nothing'}; $in{'ttlunit'} = ''; } &terror('edit_ettl', $in{'ttl'} . $in{'ttlunit'}); }}&trim($in{'comment'}); # Strip leading and trailing spaces.&trim($in{'value0'});$value = $in{'value0'};for ($i = 1; defined($in{"value$i"}); $i++) { &trim($in{"value$i"}); $value .= ' ' . $in{"value$i"};}## Now carry out checks specific to the record type.#if ($type eq 'PTR') { if ($value) { $value .= '.' unless ($value =~ /\.$/o); unless (&valdnsname($value, 0, $origin)) { &terror('edit_ehost', $value); } } else { &terror('edit_emissing_value'); } # # Check to see if we are creating a record that already exists. # if ($new) { ($oconf, $ofile, $orec) = &find_reverse($name, $value); if ($orec) { &terror('edit_edupname', $value); } else { # Reset these just in case. $oconf = $ofile = $orec = ''; } } # # Find the forward zone. Then check if we can update the SOA serial # number, that the top-level name or sub-domain is okay, and that we # can actually update the forward zone. # ($fwdconf, $fwdfile, $fwdrec) = &find_forward($value, $name, $ipv4_zone); if ($fwdconf) { if ($access{'rev_updt_must'} && ! &can_edit_forward($fwdconf)) { &terror('edit_no_updt_fwd'); } if ($in{'fwd'} && $name !~ /\*/o) { ($new_rev_serial, $new_rev_dynamic) = &check_rev_serial($fwdconf); # # If we have asked to create the forward record, then # check that we are allowed to create a top-level name # if one has been specified. # if ($new) { unless (&check_tld($value, $fwdconf, \%access, 'master', $type)) { &terror('edit_tld'); } unless (&check_sd($value, $fwdconf, \%access, 'master', $type)) { &terror('edit_sd'); } } elsif (lc($value) ne $oldvalue || ! $fwdrec) { if (! &check_tld($value, $fwdconf, \%access, 'master', $type) || ($orec && ! &check_tld($oldvalue, $oconf, \%access, 'master', $type))) { &terror('edit_tld'); } if (! &check_sd($value, $fwdconf, \%access, 'master', $type) || ($orec && ! &check_sd($oldvalue, $oconf, \%access, 'master', $type))) { &terror('edit_sd'); } } } } elsif ($config{'fwd_must'} || $access{'rev_updt_must'}) { &terror('edit_efwdmust'); } # # If necessary we must check if the IP address is already in use. # We only do this for new records or ones where the address has been # changed, and that the forward record is to be created or updated. # if ($ipv4_zone) { $v = &compress_ip(&arpa_to_ip($name)); } else { $v = &compress_ip6(&ip6arpa_to_net($name)); } # # Check to see if the IP address is already in use. # if (($new || $oldname ne $name) && &ip_in_use($conf, $v, $value, ($ipv4_zone ? 'A' : 'AAAA'), $origin, $access{'no_multiple'})) { &terror('edit_edupip', $v); }}elsif ($type eq 'A' || $type eq 'AAAA') { $ipv4_rec = ($type eq 'A'); if ($value) { $value = ($ipv4_rec) ? &compress_ip($value) : &compress_ip6($value); unless (&valipaddr($value, $origin, 0, 0, 0, $ipv4_rec)) { &terror(($ipv4_rec) ? 'edit_eip' : 'edit_eip6', $value); } } else { &terror('edit_eipmissing_value'); } # # Check to see if we are creating a record that already exists. # if ($new) { ($oconf, $ofile, $orec) = &find_forward($name, $value, $ipv4_rec); if ($orec) { &terror('edit_edupip', $name); } else { # Reset these just in case. $oconf = $ofile = $orec = ''; } } # # Check that the reverse zone exists if required, and that we can # update the SOA serial number. # ($revconf, $revfile, $revrec) = &find_reverse($value, $name); if ($revconf) { if ($access{'rev_updt_must'} && ! &can_edit_reverse($revconf)) { &terror('edit_no_updt_rev'); } if ($in{'rev'} && $name !~ /\*/o) { ($new_rev_serial, $new_rev_dynamic) = &check_rev_serial($revconf); } } elsif ($config{'rev_must'} || $access{'rev_updt_must'}) { &terror('edit_erevmust'); } # # Check to see if the IP address is already in use. # if (($new || $oldvalue ne $value) && &ip_in_use($conf, $value, $rec_name, $type, undef, $access{'no_multiple'})) { &terror('edit_edupip', $value); }}elsif ($type eq 'NS') { unless ($value) { &terror('edit_emissing_value'); } if ($value eq '@' || &valdnsname($value, 0, $origin)) { $value = &convert_fqdn(1, $value, $origin, 1); } else { &terror('edit_ens', $value); }}elsif ($type eq 'CNAME') { unless ($value) { &terror('edit_emissing_value'); } $value = &convert_fqdn(1, $value, $origin, 1); if ($value =~ /(\.(in-addr|ip6)\.arpa\.)$/o) { if ($2 eq 'in-addr') { $v = &compress_ip(&arpa_to_ip($value));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -