# Functions for managing BIND 4 and 8/9 records files use strict; use warnings; no warnings 'redefine'; no warnings 'uninitialized'; # Globals from Webmin or bind8-lib.pl our (%config, %text, %in); our $module_config_directory; our $bind_version; our $ipv6revzone = $config{'ipv6_mode'} ? "ip6.arpa" : "ip6.int"; # read_zone_file(file, origin, [previous], [only-soa], [no-chroot]) # Reads a DNS zone file and returns a data structure of records. The origin # must be a domain without the trailing dot, or just . sub read_zone_file { my ($file, $line, @tok, @lnum, @coms, @rv, $origin, @inc, @oset, $comment); $origin = $_[1]; if (&has_ndc() == 2) { # Flush the zone file &backquote_command( $config{'rndc_cmd'}. ($config{'rndc_conf'} ? " -c $config{'rndc_conf'}" : ""). " sync ".quotemeta($origin)." 2>&1 </dev/null"); } if ($origin ne ".") { # Remove trailing dots in origin name, as they are added automatically # in the code below. $origin =~ s/\.*$//; } $file = &absolute_path($_[0]); my $rootfile = $_[4] ? $file : &make_chroot($file); my $FILE; if (&is_raw_format_records($rootfile)) { # Convert from raw format first &has_command("named-compilezone") || &error("Zone file $rootfile is in raw format, but the ". "named-compilezone command is not installed"); open($FILE, "named-compilezone -f raw -F text -o - $origin $rootfile |"); } else { # Can read text format records directly open($FILE, "<", $rootfile); } my $lnum = 0; my ($gotsoa, $aftersoa) = (0, 0); while($line = <$FILE>) { my ($glen, $merged_2, $merge); $glen = 0; # strip comments (# is not a valid comment separator here!) $line =~ s/\r|\n//g; # parsing splited into separate cases to fasten it if ($line =~ /;/ && ($line =~ /[^\\]/ && $line =~ /^((?:[^;\"]+|\"\"|(?:\"(?:[^\"]*)\"))*);(.*)/) || ($line =~ /[^\"]/ && $line =~ /^((?:[^;\\]|\\.)*);(.*)/) || # expresion below is the most general, but very slow # if ";" is quoted somewhere $line =~ /^((?:(?:[^;\"\\]|\\.)+|(?:\"(?:[^\"\\]|\\.)*\"))*);(.*)/) { $comment = $2; $line = $1; if ($line =~ /^[^"]*"[^"]*$/) { # Line has only one ", meaning that a ; in the middle # of a quoted string broke it! Fix up $line .= ";".$comment; $comment = ""; } } else { $comment = ""; } # split line into tokens my $oset = 0; while(1) { $merge = 1; my $base_oset = 0; if ($line =~ /^(\s*)\"((?:[^\"\\]|\\.)*)\"(.*)/ || $line =~ /^(\s*)((?:[^\s\(\)\"\\]|\\.)+)(.*)/ || ($merge = 0) || $line =~ /^(\s*)([\(\)])(.*)/) { if ($glen == 0) { $oset += length($1); } else { $glen += length($1); } $glen += length($2); $merged_2 .= $2; $line = $3; if (!$merge || $line =~ /^([\s\(\)]|$)/) { push(@tok, $merged_2); push(@lnum, $lnum); push(@oset, $oset); push(@coms, $comment); $comment = ""; # Check if we have the SOA if (uc($merged_2) eq "SOA") { $gotsoa = 1; } elsif ($gotsoa) { $aftersoa++; } $merged_2 = ""; $oset += $glen; $glen = 0; } } else { last; } } $lnum++; # Check if we have a complete SOA record if ($aftersoa > 10 && $_[3]) { last; } } close($FILE); # parse into data structures my $i = 0; my $num = 0; my $currttl = undef; while($i < @tok) { if ($tok[$i] =~ /^\$origin$/i) { # $ORIGIN directive (may be relative or absolute) if ($tok[$i+1] =~ /^(\S*)\.$/) { $origin = $1 ? $1 : "."; } elsif ($origin eq ".") { $origin = $tok[$i+1]; } else { $origin = "$tok[$i+1].$origin"; } $i += 2; } elsif ($tok[$i] =~ /^\$include$/i) { # including another file if ($lnum[$i+1] == $lnum[$i+2]) { # $INCLUDE zonefile origin my $inc_origin; if ($tok[$i+2] =~ /^(\S+)\.$/) { $inc_origin = $1 ? $1 : "."; } elsif ($origin eq ".") { $inc_origin = $tok[$i+2]; } else { $inc_origin = "$tok[$i+2].$origin"; } @inc = &read_zone_file($tok[$i+1], $inc_origin, @rv ? $rv[$#rv] : undef); $i += 3; } else { # $INCLUDE zonefile @inc = &read_zone_file($tok[$i+1], $origin, @rv ? $rv[$#rv] : undef); $i += 2; } foreach my $j (@inc) { $j->{'num'} = $num++; } push(@rv, @inc); } elsif ($tok[$i] =~ /^\$generate$/i) { # a generate directive .. add it as a special record my $gen = { 'file' => $file, 'rootfile' => $rootfile, 'comment' => $coms[$i], 'line' => $lnum[$i], 'num' => $num++, 'type' => '' }; my @gv; while($lnum[++$i] == $gen->{'line'}) { push(@gv, $tok[$i]); } $gen->{'generate'} = \@gv; push(@rv, $gen); } elsif ($tok[$i] =~ /^\$ttl$/i) { # a ttl directive $i++; my $defttl = { 'file' => $file, 'rootfile' => $rootfile, 'line' => $lnum[$i], 'num' => $num++, 'defttl' => $tok[$i++], 'type' => '' }; push(@rv, $defttl); $currttl = $defttl->{'defttl'}; } elsif ($tok[$i] =~ /^\$(\S+)/i) { # some other special directive my $ln = $lnum[$i]; while($lnum[$i] == $ln) { $i++; } } else { # A DNS record line my(%dir, @values, $l); $dir{'line'} = $lnum[$i]; $dir{'file'} = $file; $dir{'rootfile'} = $rootfile; $dir{'comment'} = $coms[$i]; if ($tok[$i] =~ /^(in|hs)$/i && $oset[$i] > 0) { # starting with a class $dir{'class'} = uc($tok[$i]); $i++; } elsif ($tok[$i] =~ /^\d/ && $tok[$i] !~ /in-addr/i && $oset[$i] > 0 && $tok[$i+1] =~ /^(in|hs)$/i) { # starting with a TTL and class $dir{'ttl'} = $tok[$i]; $dir{'class'} = uc($tok[$i+1]); $i += 2; } elsif ($tok[$i+1] =~ /^(in|hs)$/i) { # starting with a name and class $dir{'name'} = $tok[$i]; $dir{'class'} = uc($tok[$i+1]); $i += 2; } elsif ($oset[$i] > 0 && $tok[$i] =~ /^\d+/) { # starting with just a ttl $dir{'ttl'} = $tok[$i]; $dir{'class'} = "IN"; $i++; } elsif ($oset[$i] > 0) { # starting with nothing $dir{'class'} = "IN"; } elsif ($tok[$i+1] =~ /^\d/ && $tok[$i+2] =~ /^(in|hs)$/i) { # starting with a name, ttl and class $dir{'name'} = $tok[$i]; $dir{'ttl'} = $tok[$i+1]; $dir{'class'} = uc($tok[$i+2]); $i += 3; } elsif ($tok[$i+1] =~ /^\d/) { # starting with a name and ttl $dir{'name'} = $tok[$i]; $dir{'ttl'} = $tok[$i+1]; $dir{'class'} = "IN"; $i += 2; } else { # starting with a name $dir{'name'} = $tok[$i]; $dir{'class'} = "IN"; $i++; } if (!defined($dir{'name'}) || $dir{'name'} eq '') { my $prv; # Name comes from previous record for(my $p=$#rv; $p>=0; $p--) { $prv = $rv[$p]; last if ($prv->{'name'}); } $prv ||= $_[2]; $prv || &error(&text('efirst', $lnum[$i]+1, $file)); $dir{'name'} = $prv->{'name'}; $dir{'realname'} = $prv->{'realname'}; } else { $dir{'realname'} = $dir{'name'}; } $dir{'type'} = uc($tok[$i++]); # read values until end of line, unless a ( is found, in which # case read till the ) $l = $lnum[$i]; while($i < @tok && $lnum[$i] == $l) { if ($tok[$i] eq "(") { my $olnum = $lnum[$i]; while($tok[++$i] ne ")") { push(@values, $tok[$i]); if ($i >= @tok) { &error("No ending ) found for ". "( at $olnum in $file"); } } $i++; # skip ) last; } push(@values, $tok[$i++]); } $dir{'values'} = \@values; $dir{'eline'} = $lnum[$i-1]; $dir{'realttl'} = $dir{'ttl'} || $currttl; # Work out canonical form, and maybe use it my $canon = $dir{'name'}; if ($canon eq "@") { $canon = $origin eq "." ? "." : "$origin."; } elsif ($canon !~ /\.$/) { $canon .= $origin eq "." ? "." : ".$origin."; } if (!$config{'short_names'}) { $dir{'name'} = $canon; } $dir{'canon'} = $canon; $dir{'num'} = $num++; # If this is an SPF record .. adjust the class my $spf; if ($dir{'type'} eq 'TXT' && !$config{'spf_record'} && ($spf=&parse_spf(@{$dir{'values'}}))) { if (!$spf->{'other'} || !@{$spf->{'other'}}) { $dir{'type'} = 'SPF'; } } # If this is a DMARC record .. adjust the class my $dmarc; if ($dir{'type'} eq 'TXT' && ($dmarc=&parse_dmarc(@{$dir{'values'}}))) { if (!$dmarc->{'other'} || !@{$dmarc->{'other'}}) { $dir{'type'} = 'DMARC'; } } push(@rv, \%dir); # Stop processing if this was an SOA record if ($dir{'type'} eq 'SOA' && $_[3]) { last; } } } return @rv; } # files_in_zone_file(file) # Quickly finds all includes in a zone file sub files_in_zone_file { my ($file) = @_; my @rv = ( $file ); my $fh; open($fh, "<", $file); while(<$fh>) { if (/^\$include\s+(\S+)/) { my $inc = $1; push(@rv, &files_in_zone_file($inc)); } } close($fh); return @rv; } # create_record(file, name, ttl, class, type, values, comment) # Add a new record of some type to some zone file sub create_record { my ($file, @rec) = @_; my $fn = &make_chroot(&absolute_path($file)); &is_raw_format_records($fn) && &error("Raw format zone files cannot be edited"); my $lref = &read_file_lines($fn); push(@$lref, &make_record(@rec)); &flush_file_lines($fn); } # create_multiple_records(file, &records) # Create records from structures sub create_multiple_records { my ($file, $recs) = @_; my $fn = &make_chroot(&absolute_path($file)); &is_raw_format_records($fn) && &error("Raw format zone files cannot be edited"); my $lref = &read_file_lines($fn); foreach my $r (@$recs) { push(@$lref, &make_record($r->{'name'}, $r->{'ttl'}, $r->{'class'}, $r->{'type'}, join(" ", @{$r->{'values'}}), $r->{'comment'})); } &flush_file_lines($fn); } # modify_record(file, &old, name, ttl, class, type, values, comment) # Updates an existing record in some zone file sub modify_record { my $fn = &make_chroot(&absolute_path($_[0])); &is_raw_format_records($fn) && &error("Raw format zone files cannot be edited"); my $lref = &read_file_lines($fn); my $lines = $_[1]->{'eline'} - $_[1]->{'line'} + 1; splice(@$lref, $_[1]->{'line'}, $lines, &make_record(@_[2..$#_])); &flush_file_lines($fn); } # delete_record(file, &old) # Deletes a record in some zone file sub delete_record { my ($file, $r) = @_; my $fn = &make_chroot(&absolute_path($file)); &is_raw_format_records($fn) && &error("Raw format zone files cannot be edited"); my $lref = &read_file_lines($fn); my $lines = $r->{'eline'} - $r->{'line'} + 1; splice(@$lref, $r->{'line'}, $lines); &flush_file_lines($fn); } # delete_multiple_records(file, &records) # Delete many records from the same file at once sub delete_multiple_records { my ($file, $recs) = @_; my $fn = &make_chroot(&absolute_path($file)); &is_raw_format_records($fn) && &error("Raw format zone files cannot be edited"); my $lref = &read_file_lines($fn); foreach my $r (sort { $b->{'line'} <=> $a->{'line'} } @$recs) { my $lines = $r->{'eline'} - $r->{'line'} + 1; splice(@$lref, $r->{'line'}, $lines); } &flush_file_lines($fn); } # create_generator(file, range, lhs, type, rhs, [comment]) # Add a new $generate line to some zone file sub create_generator { my $f = &make_chroot(&absolute_path($_[0])); my $lref = &read_file_lines($f); push(@$lref, join(" ", '$generate', @_[1..4]). ($_[5] ? " ;$_[5]" : "")); &flush_file_lines($f); } # modify_generator(file, &old, range, lhs, type, rhs, [comment]) # Updates an existing $generate line in some zone file sub modify_generator { my $f = &make_chroot(&absolute_path($_[0])); my $lref = &read_file_lines($f); $lref->[$_[1]->{'line'}] = join(" ", '$generate', @_[2..5]). ($_[6] ? " ;$_[6]" : ""); &flush_file_lines($f); } # delete_generator(file, &old) # Deletes a $generate line in some zone file sub delete_generator { my $f = &make_chroot(&absolute_path($_[0])); my $lref = &read_file_lines($f); splice(@$lref, $_[1]->{'line'}, 1); &flush_file_lines($f); } # create_defttl(file, value) # Adds a $ttl line to a records file sub create_defttl { my $f = &make_chroot(&absolute_path($_[0])); my $lref = &read_file_lines($f); splice(@$lref, 0, 0, "\$ttl $_[1]"); &flush_file_lines($f); } # modify_defttl(file, &old, value) # Updates the $ttl line with a new value sub modify_defttl { my $f = &make_chroot(&absolute_path($_[0])); my $lref = &read_file_lines($f); $lref->[$_[1]->{'line'}] = "\$ttl $_[2]"; &flush_file_lines($f); } # delete_defttl(file, &old) # Removes the $ttl line from a records file sub delete_defttl { my $f = &make_chroot(&absolute_path($_[0])); my $lref = &read_file_lines($f); splice(@$lref, $_[1]->{'line'}, 1); &flush_file_lines($f); } # make_record(name, ttl, class, type, values, comment) # Returns a string for some zone record sub make_record { my ($name, $ttl, $cls, $type, $values, $cmt) = @_; $type = $type eq "SPF" && !$config{'spf_record'} ? "TXT" : $type eq "DMARC" ? "TXT" : $type; return $name. (defined($ttl) && $ttl ne "" ? "\t".$ttl : ""). "\t".$cls. "\t".$type. "\t".$values. (defined($cmt) && $cmt ne "" ? "\t;$cmt" : ""); } # bump_soa_record(file, &records) # Increase the serial number in some SOA record by 1 sub bump_soa_record { my($r, $v, $vals); for(my $i=0; $i<@{$_[1]}; $i++) { $r = $_[1]->[$i]; if ($r->{'type'} eq "SOA") { $v = $r->{'values'}; # already set serial if no acl allow it to update or update # is disabled my $serial = $v->[2]; if ($config{'updserial_on'}) { # automatically handle serial numbers ? $serial = &compute_serial($v->[2]); } $vals = "$v->[0] $v->[1] (\n\t\t\t$serial\n\t\t\t$v->[3]\n". "\t\t\t$v->[4]\n\t\t\t$v->[5]\n\t\t\t$v->[6] )"; &modify_record($r->{'file'}, $r, $r->{'realname'}, $r->{'ttl'}, $r->{'class'}, $r->{'type'}, $vals); } } } # date_serial() # Returns a string like YYYYMMDD sub date_serial { my $now = time(); my @tm = localtime($now); return sprintf "%4.4d%2.2d%2.2d", $tm[5]+1900, $tm[4]+1, $tm[3]; } # get_zone_defaults(&hash) sub get_zone_defaults { my ($zd) = @_; if (!&read_file("$module_config_directory/zonedef", $zd)) { $zd->{'refresh'} = 3600; $zd->{'retry'} = 600; $zd->{'expiry'} = 1209600; $zd->{'minimum'} = 3600; $zd->{'refunit'} = ""; $zd->{'retunit'} = ""; $zd->{'expunit'} = ""; $zd->{'minunit'} = ""; } else { $zd->{'refunit'} = $1 if ($zd->{'refresh'} =~ s/([^0-9])$//); $zd->{'retunit'} = $1 if ($zd->{'retry'} =~ s/([^0-9])$//); $zd->{'expunit'} = $1 if ($zd->{'expiry'} =~ s/([^0-9])$//); $zd->{'minunit'} = $1 if ($zd->{'minimum'} =~ s/([^0-9])$//); } } # save_zone_defaults(&array) sub save_zone_defaults { &write_file("$module_config_directory/zonedef", $_[0]); } # allowed_zone_file(&access, file) sub allowed_zone_file { return 0 if ($_[1] =~ /\.\./); return 0 if (-l $_[1] && !&allowed_zone_file($_[0], readlink($_[1]))); my $l = length($_[0]->{'dir'}); return length($_[1]) > $l && substr($_[1], 0, $l) eq $_[0]->{'dir'}; } # sort_records(list) sub sort_records { return @_ if (!@_); my $s = $in{'sort'} ? $in{'sort'} : $config{'records_order'}; if ($s == 1) { # Sort by name if ($_[0]->{'type'} eq "PTR") { my @rv = sort ptr_sort_func @_; return @rv; } else { my @rv = sort { $a->{'name'} cmp $b->{'name'} } @_; return @rv; } } elsif ($s == 2) { # Sort by value if ($_[0]->{'type'} eq "A") { my @rv = sort ip_sort_func @_; return @rv; } elsif ($_[0]->{'type'} eq "MX") { my @rv = sort { $a->{'values'}->[1] cmp $b->{'values'}->[1] } @_; return @rv; } else { my @rv = sort { $a->{'values'}->[0] cmp $b->{'values'}->[0] } @_; return @rv; } } elsif ($s == 3) { # Sort by IP address or by value if there is no IP if ($_[0]->{'type'} eq "A") { my @rv = sort ip_sort_func @_; return @rv; } elsif ($_[0]->{'type'} eq "PTR") { my @rv = sort ptr_sort_func @_; return @rv; } elsif ($_[0]->{'type'} eq "MX") { my @rv = sort { $a->{'values'}->[1] cmp $b->{'values'}->[1] } @_; return @rv; } else { my @rv = sort { $a->{'values'}->[0] cmp $b->{'values'}->[0] } @_; return @rv; } } elsif ($s == 4) { # Sort by comment my @rv = sort { $b->{'comment'} cmp $a->{'comment'} } @_; return @rv; } elsif ($s == 5) { # Sort by type my @rv = sort { $a->{'type'} cmp $b->{'type'} } @_; return @rv; } else { return @_; } } sub ptr_sort_func { $a->{'name'} =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/; my ($a1, $a2, $a3, $a4) = ($1, $2, $3, $4); $b->{'name'} =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/; return $a4 < $4 ? -1 : $a4 > $4 ? 1 : $a3 < $3 ? -1 : $a3 > $3 ? 1 : $a2 < $2 ? -1 : $a2 > $2 ? 1 : $a1 < $1 ? -1 : $a1 > $1 ? 1 : 0; } sub ip_sort_func { $a->{'values'}->[0] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/; my ($a1, $a2, $a3, $a4) = ($1, $2, $3, $4); $b->{'values'}->[0] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/; return $a1 < $1 ? -1 : $a1 > $1 ? 1 : $a2 < $2 ? -1 : $a2 > $2 ? 1 : $a3 < $3 ? -1 : $a3 > $3 ? 1 : $a4 < $4 ? -1 : $a4 > $4 ? 1 : 0; } # arpa_to_ip(name) # Converts an address like 4.3.2.1.in-addr.arpa. to 1.2.3.4 sub arpa_to_ip { if ($_[0] =~ /^([\d\-\.\/]+)\.in-addr\.arpa/i) { return join('.',reverse(split(/\./, $1))); } return $_[0]; } # ip_to_arpa(address) # Converts an IP address like 1.2.3.4 to 4.3.2.1.in-addr.arpa. sub ip_to_arpa { if ($_[0] =~ /^([\d\-\.\/]+)$/) { return join('.',reverse(split(/\./,$1))).".in-addr.arpa."; } return $_[0]; } # ip6int_to_net(name) # Converts an address like a.b.c.d.4.3.2.1.ip6.int. to 1234:dcba:: sub ip6int_to_net { my $n; my $addr = $_[0]; if ($addr =~ /^([\da-f]\.)+$ipv6revzone/i) { $addr =~ s/\.$ipv6revzone/\./i; $addr = reverse(split(/\./, $addr)); $addr =~ s/([\w]{4})/$1:/g; $n = ($addr =~ s/([\w])/$1/g) * 4; $addr =~ s/(\w+)$/$+0000/; $addr =~ s/([\w]{4})0+$/$1:/; $addr =~ s/$/:/; $addr =~ s/:0{1,3}/:/g; if ($n > 112) { $addr =~ s/::$//; $addr =~ s/(:0)+:/::/; } if ($n < 128) { return $addr."/$n"; } return $addr } return $_[0]; } # net_to_ip6int(address, [bits]) # Converts an IPv6 address like 1234:dcba:: to a.b.c.d.4.3.2.1.ip6.int. sub net_to_ip6int { my $addr = lc($_[0]); my $n = $_[1] ? $_[1] >> 2 : 0; if (&check_ip6address($addr)) { $addr = reverse(split(/\:/, &expandall_ip6($addr))); $addr =~ s/(\w)/$1\./g; if ($n > 0) { $addr = substr($addr, -2 * $n, 2 * $n); } $addr = $addr.$ipv6revzone."."; } return $addr; } our $uscore = $config{'allow_underscore'} ? "_" : ""; our $star = $config{'allow_wild'} ? "\\*" : ""; # valdnsname(name, wild, origin) sub valdnsname { my($fqdn); $fqdn = $_[0] !~ /\.$/ ? "$_[0].$_[2]." : $_[0]; if (length($fqdn) > 255) { &error(&text('edit_efqdn', $fqdn)); } if ($_[0] =~ /[^\.]{64}/) { # no label longer than 63 chars &error(&text('edit_elabel', $_[0])); } return ((($_[1] && $config{'allow_wild'}) ? (($_[0] =~ /^[\*A-Za-z0-9\-\.$uscore]+$/) && ($_[0] !~ /.\*/ || $bind_version >= 9) # "*" can be only the first # char, for bind 8 && ($_[0] !~ /\*[^\.]/)) # a "." must always follow "*" : ($_[0] =~ /^[\A-Za-z0-9\-\.$uscore]+$/)) && ($_[0] !~ /\.\./) # no ".." inside && ($_[0] !~ /^\../) # no "." at the beginning && ($_[0] !~ /^\-/) # no "-" at the beginning && ($_[0] !~ /\-$/) # no "-" at the end && ($_[0] !~ /\.\-/) # no ".-" inside && ($_[0] !~ /\-\./) # no "-." inside && ($_[0] !~ /\.[0-9]+\.$/)); # last label in FQDN may not be # purely numeric } # valemail(email) sub valemail { return $_[0] eq "." || $_[0] =~ /^[A-Za-z0-9\.\-]+$/ || $_[0] =~ /(\S*)\@(\S*)/ && &valdnsname($2, 0, ".") && $1 =~ /[a-z][\w\-\.$uscore]+/i; } # absolute_path(path) # If a path does not start with a /, prepend the base directory sub absolute_path { my ($path) = @_; if ($path =~ /^([a-zA-Z]:)?\//) { return $path; } return &base_directory()."/".$path; } # parse_spf(text, ...) # If some text looks like an SPF TXT record, return a parsed hash ref sub parse_spf { my $txt = join(" ", @_); if ($txt =~ /^v=spf1/) { my @w = split(/\s+/, $txt); my $spf = { }; foreach my $w (@w) { $w = lc($w); if ($w eq "a" || $w eq "mx" || $w eq "ptr") { $spf->{$w} = 1; } elsif ($w =~ /^(a|mx|ip4|ip6|ptr|include|exists):(\S+)$/) { push(@{$spf->{"$1:"}}, $2); } elsif ($w eq "-all") { $spf->{'all'} = 3; } elsif ($w eq "~all") { $spf->{'all'} = 2; } elsif ($w eq "?all") { $spf->{'all'} = 1; } elsif ($w eq "+all" || $w eq "all") { $spf->{'all'} = 0; } elsif ($w eq "v=spf1") { # Ignore this } elsif ($w =~ /^(redirect|exp)=(\S+)$/) { # Modifier for domain redirect or expansion $spf->{$1} = $2; } else { push(@{$spf->{'other'}}, $w); } } return $spf; } return undef; } # join_spf(&spf) # Converts an SPF record structure to a string, designed to be inserted into # quotes in a TXT record. If it is longer than 255 bytes, it will be split # into multiple quoted strings. sub join_spf { my ($spf) = @_; my @rv = ( "v=spf1" ); foreach my $s ("a", "mx", "ptr") { push(@rv, $s) if ($spf->{$s}); } foreach my $s ("a", "mx", "ip4", "ip6", "ptr", "include", "exists") { if ($spf->{"$s:"}) { foreach my $v (@{$spf->{"$s:"}}) { push(@rv, "$s:$v"); } } } if ($spf->{'other'}) { push(@rv, @{$spf->{'other'}}); } foreach my $m ("redirect", "exp") { if ($spf->{$m}) { push(@rv, $m."=".$spf->{$m}); } } if ($spf->{'all'} == 3) { push(@rv, "-all"); } elsif ($spf->{'all'} == 2) { push(@rv, "~all"); } elsif ($spf->{'all'} == 1) { push(@rv, "?all"); } elsif ($spf->{'all'} eq '0') { push(@rv, "all"); } my @rvwords; my $rvword = ""; while(@rv) { my $w = shift(@rv); if (length($rvword)+length($w)+1 >= 255) { $rvword .= " "; push(@rvwords, $rvword); $rvword = ""; } $rvword .= " " if ($rvword); $rvword .= $w; } push(@rvwords, $rvword); return join("\" \"", @rvwords); } # parse_dmarc(text, ...) # If some text looks like an DMARC TXT record, return a parsed hash ref sub parse_dmarc { my $txt = join(" ", @_); if ($txt =~ /^v=dmarc1/i) { my @w = split(/;\s*/, $txt); my $dmarc = { }; foreach my $w (@w) { $w = lc($w); if ($w =~ /^(v|pct|ruf|rua|p|sp|adkim|aspf|fo|rf|ri)=(\S+)$/i) { $dmarc->{$1} = $2; } else { push(@{$dmarc->{'other'}}, $w); } } return $dmarc; } return undef; } # join_dmarc(&dmarc) # Converts a DMARC record structure to a string, designed to be inserted into # quotes in a TXT record. If it is longer than 255 bytes, it will be split # into multiple quoted strings. sub join_dmarc { my ($dmarc) = @_; my @rv = ( "v=DMARC1" ); foreach my $s ("p", "pct", "ruf", "rua", "sp", "adkim", "aspf", "fo", "rf", "ri") { if ($dmarc->{$s} && $dmarc->{$s} ne '') { push(@rv, $s."=".$dmarc->{$s}); } } if ($dmarc->{'other'}) { push(@rv, @{$dmarc->{'other'}}); } my @rvwords; my $rvword = ""; while(@rv) { my $w = shift(@rv); if (length($rvword)+length($w)+1 >= 255) { push(@rvwords, $rvword); $rvword = ""; } $rvword .= "; " if ($rvword); $rvword .= $w; } push(@rvwords, $rvword); return join("\" \"", @rvwords); } # join_record_values(&record) # Given the values for a record, joins them into a space-separated string # with quoting if needed sub join_record_values { my ($r) = @_; if ($r->{'type'} eq 'SOA') { # Multiliple lines, with brackets my $v = $r->{'values'}; return "$v->[0] $v->[1] (\n\t\t\t$v->[2]\n\t\t\t$v->[3]\n". "\t\t\t$v->[4]\n\t\t\t$v->[5]\n\t\t\t$v->[6] )"; } else { # All one one line my @rv; foreach my $v (@{$r->{'values'}}) { push(@rv, $v =~ /\s|;/ ? "\"$v\"" : $v); } return join(" ", @rv); } } # compute_serial(old) # Given an old serial number, returns a new one using the configured method sub compute_serial { my ($old) = @_; if ($config{'soa_style'} == 1 && $old =~ /^(\d{8})(\d\d)$/) { if ($1 >= &date_serial()) { if ($2 >= 99) { # Have to roll over to next day return sprintf "%d%2.2d", $1+1, $config{'soa_start'}; } else { # Just increment within this day return sprintf "%d%2.2d", $1, $2+1; } } else { # A new day has come return &date_serial().sprintf("%2.2d", $config{'soa_start'}); } } elsif ($config{'soa_style'} == 2) { # Unix time my $rv = time(); while($rv <= $old) { $rv = $old + 1; } return $rv; } else { # Incrementing number return $old+1; } } # convert_to_absolute(short, origin) # Make a short name like foo a fully qualified name like foo.domain.com. sub convert_to_absolute { my ($name, $origin) = @_; if ($name eq $origin || $name =~ /\.\Q$origin\E$/) { # Name already ends in domain name - add . automatically, so we don't # re-append the domain name. $name .= "."; } my $rv = $name eq "" ? "$origin." : $name eq "@" ? "$origin." : $name !~ /\.$/ ? "$name.$origin." : $name; $rv =~ s/\.+$/\./; return $rv; } # get_zone_file(&zone|&zonename, [absolute]) # Returns the relative-to-chroot path to a domain's zone file. # If absolute is 1, the path is made absolute. If 2, it is also un-chrooted sub get_zone_file { my ($z, $abs) = @_; $abs ||= 0; my $fn; if ($z->{'members'}) { my $file = &find("file", $z->{'members'}); return undef if (!$file); $fn = $file->{'values'}->[0]; } else { $fn = $z->{'file'}; } return undef if (!$fn); if ($abs) { $fn = &absolute_path($fn); } if ($abs == 2) { $fn = &make_chroot($fn); } return $fn; } # get_dnskey_record(&zone|&zonename, [&records]) # Returns the DNSKEY record(s) for some domain, or undef if none sub get_dnskey_record { my ($z, $recs) = @_; my $dom = $z->{'members'} ? $z->{'values'}->[0] : $z->{'name'}; my @rv; if ($dom) { if (!$recs) { # Need to get zone file and thus records my $fn = &get_zone_file($z); $recs = [ &read_zone_file($fn, $dom) ]; } # Find the record foreach my $r (@$recs) { if ($r->{'type'} eq 'DNSKEY' && $r->{'name'} eq $dom.'.') { push(@rv, $r); } } } return wantarray ? @rv : $rv[0]; } # record_id(&r) # Returns a unique ID string for a record, based on the name and value sub record_id { my ($r) = @_; return $r->{'name'}."/".$r->{'type'}. (uc($r->{'type'}) eq 'SOA' || !$r->{'values'} ? '' : '/'.join('/', @{$r->{'values'}})); } # find_record_by_id(&recs, id, index) # Find a record by ID and possibly index sub find_record_by_id { my ($recs, $id, $num) = @_; my @rv = grep { &record_id($_) eq $id } @$recs; if (!@rv) { return undef; } elsif (@rv == 1) { return $rv[0]; } else { # Multiple matches .. find the one with the right index @rv = grep { $_->{'num'} == $num } @rv; return @rv ? $rv[0] : undef; } } # get_dnskey_rrset(&zone, [&records]) # Returns the DNSKEY recordset for some domain, or an empty array if none sub get_dnskey_rrset { my ($z, $recs) = @_; my @rv = (); my $dom = $z->{'members'} ? $z->{'values'}->[0] : $z->{'name'}; if (!$recs) { # Need to get zone file and thus records my $fn = &get_zone_file($z); $recs = [ &read_zone_file($fn, $dom) ]; } # Find the record foreach my $r (@$recs) { if ($r->{'type'} eq 'DNSKEY' && $r->{'name'} eq $dom.'.') { push(@rv, $r); } } return @rv; } # is_raw_format_records(file) # Checks if a zone file is in BIND's new raw or text format sub is_raw_format_records { my ($file) = @_; open(my $RAW, "<", $file) || return 0; my $buf; read($RAW, $buf, 3); close($RAW); return $buf eq "\0\0\0"; } 1;
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
images | Folder | 0755 |
|
|
lang | Folder | 0755 |
|
|
CHANGELOG | File | 12.67 KB | 0644 |
|
acl_security.pl | File | 10.25 KB | 0755 |
|
backup_config.pl | File | 1.47 KB | 0755 |
|
bind8-lib.pl | File | 115.83 KB | 0755 |
|
cgi_args.pl | File | 1.92 KB | 0755 |
|
check_zone.cgi | File | 1.04 KB | 0755 |
|
close.cgi | File | 342 B | 0755 |
|
conf_acls.cgi | File | 989 B | 0755 |
|
conf_controls.cgi | File | 2.34 KB | 0755 |
|
conf_dnssec.cgi | File | 936 B | 0755 |
|
conf_dnssectools.cgi | File | 2.16 KB | 0755 |
|
conf_files.cgi | File | 1.19 KB | 0755 |
|
conf_forwarding.cgi | File | 1.54 KB | 0755 |
|
conf_keys.cgi | File | 1.07 KB | 0755 |
|
conf_logging.cgi | File | 4.85 KB | 0755 |
|
conf_manual.cgi | File | 1.21 KB | 0755 |
|
conf_misc.cgi | File | 1.95 KB | 0755 |
|
conf_ncheck.cgi | File | 807 B | 0755 |
|
conf_net.cgi | File | 3.49 KB | 0755 |
|
conf_rndc.cgi | File | 1.15 KB | 0755 |
|
conf_servers.cgi | File | 1.8 KB | 0755 |
|
conf_trusted.cgi | File | 2.84 KB | 0755 |
|
conf_zonedef.cgi | File | 4.9 KB | 0755 |
|
config-AlmaLinux-6.0-ALL | File | 989 B | 0644 |
|
config-CentOS-Linux-6.0-7.9 | File | 997 B | 0644 |
|
config-CentOS-Linux-8.0-ALL | File | 989 B | 0644 |
|
config-CentOS-Stream-Linux-8.0-ALL | File | 989 B | 0644 |
|
config-CloudLinux-8.0-ALL | File | 989 B | 0644 |
|
config-Oracle-Linux-8.0-ALL | File | 989 B | 0644 |
|
config-Redhat-Enterprise-Linux-6.0-7.9 | File | 976 B | 0644 |
|
config-Redhat-Enterprise-Linux-8.0-ALL | File | 989 B | 0644 |
|
config-Rocky-Linux-6.0-ALL | File | 989 B | 0644 |
|
config-Scientific-Linux-6.0-ALL | File | 935 B | 0644 |
|
config-aix | File | 717 B | 0644 |
|
config-cobalt-linux | File | 722 B | 0644 |
|
config-coherent-linux | File | 857 B | 0644 |
|
config-corel-linux | File | 722 B | 0644 |
|
config-debian-linux | File | 722 B | 0644 |
|
config-debian-linux-10.0-ALL | File | 991 B | 0644 |
|
config-debian-linux-2.2 | File | 727 B | 0644 |
|
config-debian-linux-3.0 | File | 842 B | 0644 |
|
config-debian-linux-3.1-9.0 | File | 934 B | 0644 |
|
config-freebsd-12.0-ALL | File | 790 B | 0644 |
|
config-freebsd-2.1-2.2 | File | 728 B | 0644 |
|
config-freebsd-3.0 | File | 729 B | 0644 |
|
config-freebsd-3.1-3.5 | File | 722 B | 0644 |
|
config-freebsd-4.0-11.0 | File | 757 B | 0644 |
|
config-generic-linux | File | 750 B | 0644 |
|
config-gentoo-linux | File | 827 B | 0644 |
|
config-hpux | File | 722 B | 0644 |
|
config-irix | File | 722 B | 0644 |
|
config-macos | File | 728 B | 0644 |
|
config-macos-1.3-ALL | File | 789 B | 0644 |
|
config-mandrake-linux | File | 814 B | 0644 |
|
config-mandrake-linux-10.2-ALL | File | 802 B | 0644 |
|
config-msc-linux | File | 788 B | 0644 |
|
config-netbsd | File | 729 B | 0644 |
|
config-open-linux | File | 798 B | 0644 |
|
config-openSUSE-Linux-15.0-ALL | File | 938 B | 0644 |
|
config-openbsd-2.5-3.1 | File | 722 B | 0644 |
|
config-openbsd-3.2-ALL | File | 740 B | 0644 |
|
config-openmamba-linux | File | 798 B | 0644 |
|
config-openserver | File | 722 B | 0644 |
|
config-osf1 | File | 722 B | 0644 |
|
config-pardus-linux | File | 875 B | 0644 |
|
config-redhat-linux-7.0-ALL | File | 989 B | 0644 |
|
config-redhat-linux-ALL-6.0 | File | 997 B | 0644 |
|
config-slackware-linux | File | 722 B | 0644 |
|
config-slackware-linux-8.0-ALL | File | 756 B | 0644 |
|
config-sol-linux | File | 850 B | 0644 |
|
config-solaris | File | 737 B | 0644 |
|
config-solaris-10-ALL | File | 835 B | 0644 |
|
config-solaris-7-9 | File | 725 B | 0644 |
|
config-suse-linux | File | 722 B | 0644 |
|
config-suse-linux-8.2 | File | 882 B | 0644 |
|
config-suse-linux-9.0-9.2 | File | 995 B | 0644 |
|
config-suse-linux-9.3-ALL | File | 1.03 KB | 0644 |
|
config-syno-linux | File | 683 B | 0644 |
|
config-trustix-linux | File | 927 B | 0644 |
|
config-trustix-linux-2.1 | File | 923 B | 0644 |
|
config-trustix-linux-2.2-ALL | File | 939 B | 0644 |
|
config-turbo-linux | File | 722 B | 0644 |
|
config-united-linux | File | 822 B | 0644 |
|
config-unixware | File | 763 B | 0644 |
|
config-windows | File | 1.17 KB | 0644 |
|
config.info | File | 4.02 KB | 0644 |
|
config.info.bg | File | 6.88 KB | 0644 |
|
config.info.ca | File | 4.5 KB | 0644 |
|
config.info.cs | File | 3.34 KB | 0644 |
|
config.info.de | File | 4.6 KB | 0644 |
|
config.info.es | File | 3.33 KB | 0644 |
|
config.info.fa | File | 4.7 KB | 0644 |
|
config.info.fr | File | 4.92 KB | 0644 |
|
config.info.hu | File | 0 B | 0644 |
|
config.info.ja | File | 4.03 KB | 0644 |
|
config.info.ms | File | 1.12 KB | 0644 |
|
config.info.nl | File | 4.1 KB | 0644 |
|
config.info.no | File | 4 KB | 0644 |
|
config.info.pl | File | 4.42 KB | 0644 |
|
config.info.pt_BR | File | 3.86 KB | 0644 |
|
config.info.ru | File | 3.02 KB | 0644 |
|
config.info.sv | File | 1.02 KB | 0644 |
|
config.info.tr | File | 646 B | 0644 |
|
config.info.uk | File | 3.14 KB | 0644 |
|
config.info.zh | File | 750 B | 0644 |
|
config.info.zh_TW | File | 364 B | 0644 |
|
convert_master.cgi | File | 1.02 KB | 0755 |
|
convert_slave.cgi | File | 1.44 KB | 0755 |
|
cpan_modules.pl | File | 143 B | 0644 |
|
create_delegation.cgi | File | 1.77 KB | 0755 |
|
create_forward.cgi | File | 2.09 KB | 0755 |
|
create_hint.cgi | File | 1.47 KB | 0755 |
|
create_master.cgi | File | 5.61 KB | 0755 |
|
create_slave.cgi | File | 4.1 KB | 0755 |
|
create_view.cgi | File | 1.5 KB | 0755 |
|
db.cache | File | 2.44 KB | 0644 |
|
defaultacl | File | 219 B | 0644 |
|
delegation_form.cgi | File | 1.3 KB | 0755 |
|
delete_recs.cgi | File | 2.66 KB | 0755 |
|
delete_view.cgi | File | 2.34 KB | 0755 |
|
delete_zone.cgi | File | 5.3 KB | 0755 |
|
disable_zonedt.cgi | File | 934 B | 0755 |
|
disable_zonekey.cgi | File | 928 B | 0755 |
|
dns_boot.cgi | File | 2.56 KB | 0755 |
|
edit_delegation.cgi | File | 1.11 KB | 0755 |
|
edit_forward.cgi | File | 1.82 KB | 0755 |
|
edit_hint.cgi | File | 1 KB | 0755 |
|
edit_master.cgi | File | 5.75 KB | 0755 |
|
edit_options.cgi | File | 1.62 KB | 0755 |
|
edit_record.cgi | File | 1.13 KB | 0755 |
|
edit_recs.cgi | File | 7.59 KB | 0755 |
|
edit_slave.cgi | File | 3.93 KB | 0755 |
|
edit_soa.cgi | File | 2.51 KB | 0755 |
|
edit_soptions.cgi | File | 2.27 KB | 0755 |
|
edit_stub.cgi | File | 3.93 KB | 0755 |
|
edit_text.cgi | File | 1.26 KB | 0755 |
|
edit_view.cgi | File | 2.12 KB | 0755 |
|
edit_zonedt.cgi | File | 6.52 KB | 0755 |
|
edit_zonekey.cgi | File | 4.13 KB | 0755 |
|
enable_zonedt.cgi | File | 1.12 KB | 0755 |
|
enable_zonekey.cgi | File | 1.42 KB | 0755 |
|
feedback_files.pl | File | 588 B | 0755 |
|
find_free.cgi | File | 5.59 KB | 0755 |
|
find_zones.cgi | File | 3.89 KB | 0755 |
|
fix_trusted.cgi | File | 1 KB | 0755 |
|
forward_form.cgi | File | 1.38 KB | 0755 |
|
free_chooser.cgi | File | 2 KB | 0755 |
|
freeze_zone.cgi | File | 992 B | 0755 |
|
hint_form.cgi | File | 1.79 KB | 0755 |
|
index.cgi | File | 17.51 KB | 0755 |
|
install_check.pl | File | 513 B | 0755 |
|
list_gen.cgi | File | 1.95 KB | 0755 |
|
list_slaves.cgi | File | 3.28 KB | 0755 |
|
log_parser.pl | File | 2.47 KB | 0755 |
|
mass_create.cgi | File | 7.33 KB | 0755 |
|
mass_delete.cgi | File | 3.42 KB | 0755 |
|
mass_form.cgi | File | 1.44 KB | 0755 |
|
mass_rcreate.cgi | File | 3.56 KB | 0755 |
|
mass_rcreate_form.cgi | File | 1.49 KB | 0755 |
|
mass_rdelete.cgi | File | 1.87 KB | 0755 |
|
mass_rdelete_form.cgi | File | 1.3 KB | 0755 |
|
mass_update.cgi | File | 3 KB | 0755 |
|
mass_update_form.cgi | File | 1.07 KB | 0755 |
|
master_form.cgi | File | 3.48 KB | 0755 |
|
module.info | File | 279 B | 0644 |
|
module.info.af | File | 0 B | 0644 |
|
module.info.af.auto | File | 116 B | 0644 |
|
module.info.ar | File | 0 B | 0644 |
|
module.info.ar.auto | File | 152 B | 0644 |
|
module.info.be | File | 0 B | 0644 |
|
module.info.be.auto | File | 173 B | 0644 |
|
module.info.bg | File | 30 B | 0644 |
|
module.info.bg.auto | File | 143 B | 0644 |
|
module.info.ca | File | 106 B | 0644 |
|
module.info.ca.auto | File | 16 B | 0644 |
|
module.info.cs | File | 24 B | 0644 |
|
module.info.cs.auto | File | 105 B | 0644 |
|
module.info.da | File | 0 B | 0644 |
|
module.info.da.auto | File | 122 B | 0644 |
|
module.info.de | File | 113 B | 0644 |
|
module.info.de.auto | File | 15 B | 0644 |
|
module.info.el | File | 0 B | 0644 |
|
module.info.el.auto | File | 199 B | 0644 |
|
module.info.es | File | 29 B | 0644 |
|
module.info.es.auto | File | 90 B | 0644 |
|
module.info.eu | File | 0 B | 0644 |
|
module.info.eu.auto | File | 129 B | 0644 |
|
module.info.fa | File | 0 B | 0644 |
|
module.info.fa.auto | File | 164 B | 0644 |
|
module.info.fi | File | 0 B | 0644 |
|
module.info.fi.auto | File | 129 B | 0644 |
|
module.info.fr | File | 41 B | 0644 |
|
module.info.fr.auto | File | 113 B | 0644 |
|
module.info.he | File | 0 B | 0644 |
|
module.info.he.auto | File | 147 B | 0644 |
|
module.info.hr | File | 0 B | 0644 |
|
module.info.hr.auto | File | 124 B | 0644 |
|
module.info.hu | File | 27 B | 0644 |
|
module.info.hu.auto | File | 125 B | 0644 |
|
module.info.it | File | 0 B | 0644 |
|
module.info.it.auto | File | 107 B | 0644 |
|
module.info.ja | File | 27 B | 0644 |
|
module.info.ja.auto | File | 134 B | 0644 |
|
module.info.ko | File | 25 B | 0644 |
|
module.info.ko.auto | File | 111 B | 0644 |
|
module.info.lt | File | 0 B | 0644 |
|
module.info.lt.auto | File | 128 B | 0644 |
|
module.info.lv | File | 0 B | 0644 |
|
module.info.lv.auto | File | 132 B | 0644 |
|
module.info.ms | File | 110 B | 0644 |
|
module.info.ms.auto | File | 13 B | 0644 |
|
module.info.mt | File | 0 B | 0644 |
|
module.info.mt.auto | File | 114 B | 0644 |
|
module.info.nl | File | 24 B | 0644 |
|
module.info.nl.auto | File | 87 B | 0644 |
|
module.info.no | File | 24 B | 0644 |
|
module.info.no.auto | File | 98 B | 0644 |
|
module.info.pl | File | 96 B | 0644 |
|
module.info.pl.auto | File | 17 B | 0644 |
|
module.info.pt | File | 29 B | 0644 |
|
module.info.pt.auto | File | 101 B | 0644 |
|
module.info.pt_BR | File | 32 B | 0644 |
|
module.info.pt_BR.auto | File | 107 B | 0644 |
|
module.info.ro | File | 0 B | 0644 |
|
module.info.ro.auto | File | 131 B | 0644 |
|
module.info.ru | File | 30 B | 0644 |
|
module.info.ru.auto | File | 167 B | 0644 |
|
module.info.sk | File | 0 B | 0644 |
|
module.info.sk.auto | File | 125 B | 0644 |
|
module.info.sl | File | 0 B | 0644 |
|
module.info.sl.auto | File | 128 B | 0644 |
|
module.info.sv | File | 24 B | 0644 |
|
module.info.sv.auto | File | 93 B | 0644 |
|
module.info.th | File | 0 B | 0644 |
|
module.info.th.auto | File | 218 B | 0644 |
|
module.info.tr | File | 26 B | 0644 |
|
module.info.tr.auto | File | 121 B | 0644 |
|
module.info.uk | File | 0 B | 0644 |
|
module.info.uk.auto | File | 197 B | 0644 |
|
module.info.ur | File | 0 B | 0644 |
|
module.info.ur.auto | File | 193 B | 0644 |
|
module.info.vi | File | 0 B | 0644 |
|
module.info.vi.auto | File | 151 B | 0644 |
|
module.info.zh | File | 27 B | 0644 |
|
module.info.zh.auto | File | 83 B | 0644 |
|
module.info.zh_TW | File | 30 B | 0644 |
|
module.info.zh_TW.auto | File | 89 B | 0644 |
|
move_zone.cgi | File | 1.27 KB | 0755 |
|
old_save_controls.cgi | File | 2.13 KB | 0755 |
|
open.cgi | File | 307 B | 0755 |
|
prefs.info | File | 61 B | 0644 |
|
records-lib.pl | File | 26.64 KB | 0755 |
|
refetch.cgi | File | 705 B | 0755 |
|
resign.pl | File | 2.11 KB | 0755 |
|
resign_zone.cgi | File | 708 B | 0755 |
|
restart.cgi | File | 819 B | 0755 |
|
restart_zone.cgi | File | 655 B | 0755 |
|
save_acls.cgi | File | 1.6 KB | 0755 |
|
save_controls.cgi | File | 2.3 KB | 0755 |
|
save_dnssec.cgi | File | 1.29 KB | 0755 |
|
save_dnssectools.cgi | File | 1.39 KB | 0755 |
|
save_files.cgi | File | 831 B | 0755 |
|
save_forward.cgi | File | 847 B | 0755 |
|
save_forwarding.cgi | File | 1.08 KB | 0755 |
|
save_gen.cgi | File | 3.79 KB | 0755 |
|
save_keys.cgi | File | 1.15 KB | 0755 |
|
save_logging.cgi | File | 2.97 KB | 0755 |
|
save_manual.cgi | File | 774 B | 0755 |
|
save_master.cgi | File | 1.06 KB | 0755 |
|
save_misc.cgi | File | 1.3 KB | 0755 |
|
save_net.cgi | File | 3.16 KB | 0755 |
|
save_record.cgi | File | 23.06 KB | 0755 |
|
save_rndc.cgi | File | 2.93 KB | 0755 |
|
save_servers.cgi | File | 1.73 KB | 0755 |
|
save_slave.cgi | File | 1.6 KB | 0755 |
|
save_soa.cgi | File | 2.58 KB | 0755 |
|
save_text.cgi | File | 1.12 KB | 0755 |
|
save_trusted.cgi | File | 2.76 KB | 0755 |
|
save_view.cgi | File | 1.36 KB | 0755 |
|
save_zonedef.cgi | File | 3.05 KB | 0755 |
|
sign_zone.cgi | File | 770 B | 0755 |
|
slave_add.cgi | File | 4.97 KB | 0755 |
|
slave_delete.cgi | File | 651 B | 0755 |
|
slave_form.cgi | File | 2.16 KB | 0755 |
|
start.cgi | File | 467 B | 0755 |
|
stop.cgi | File | 341 B | 0755 |
|
stub_form.cgi | File | 2.16 KB | 0755 |
|
syslog_logs.pl | File | 708 B | 0755 |
|
system_info.pl | File | 1.11 KB | 0644 |
|
unfreeze_zone.cgi | File | 990 B | 0755 |
|
view_form.cgi | File | 1.11 KB | 0755 |
|
view_text.cgi | File | 1.05 KB | 0755 |
|
whois.cgi | File | 1.14 KB | 0755 |
|
xfer.cgi | File | 1.66 KB | 0755 |
|
zone_dnssecmgt_dt.cgi | File | 1.37 KB | 0755 |
|
zone_dnssecmigrate_dt.cgi | File | 2.32 KB | 0755 |
|