update-serial
changeset 30 5ac92c1ffdf9
child 31 1cea07056124
equal deleted inserted replaced
29:ef4b45dd7618 30:5ac92c1ffdf9
       
     1 #! /usr/bin/perl
       
     2 # (c) 1998 Heiko Schlittermann <heiko@datom.de>
       
     3 #
       
     4 # … work in progress do integrate dnssec (branch suess)
       
     5 #
       
     6 # Update the serial numbers in zone files
       
     7 # The serial number needs to match a specified pattern (see 
       
     8 # the line marked w/ PATTERN.
       
     9 # 
       
    10 # ToDo:
       
    11 # . test against an md5 sum, not just the date of the stamp file
       
    12 # . FIXME: handle `/' in file names (currently only working in 
       
    13 #   the current directory)
       
    14 # . optionally reload the named
       
    15 
       
    16 
       
    17 use strict;
       
    18 use warnings;
       
    19 
       
    20 use File::Basename;
       
    21 use File::Copy;
       
    22 use FindBin;
       
    23 
       
    24 my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
       
    25 my @dnssec_signs = ( "$FindBin::Bin/dnssec-sign", "/usr/bin/dnstools/dnssec-sign");
       
    26 my %config;
       
    27 my $dnssec_sign;
       
    28 
       
    29 foreach ( grep {-f} @configs ) {
       
    30     open( CONFIG, $_ ) or die "Can't open $_: $!\n";
       
    31 }
       
    32 
       
    33 unless ( seek( CONFIG, 0, 0 ) ) {
       
    34     die "Can't open config (searched: @configs)\n";
       
    35 }
       
    36 foreach ( grep {-f} @dnssec_signs ) {
       
    37 	if (-x $_) {
       
    38 		$dnssec_sign = $_;
       
    39 	}
       
    40 	else {
       
    41 		die "Can't run $_\n"
       
    42 	}
       
    43 }
       
    44 
       
    45 
       
    46 while (<CONFIG>) {
       
    47     chomp;
       
    48     s/#.*//;
       
    49     s/\t//g;
       
    50     s/\s//g;
       
    51     next unless length;
       
    52     my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
       
    53     $config{$cname} = $ccont;
       
    54 }
       
    55 close(CONFIG);
       
    56 
       
    57 my $bind_dir   = $config{bind_dir};
       
    58 my $conf_dir   = $config{zone_conf_dir};
       
    59 my $master_dir = $config{master_dir};
       
    60 
       
    61 my $ME = basename $0;
       
    62 my @tmpfiles;
       
    63 my $verbose = 0;
       
    64 my $opt_yes = 0;
       
    65 my @Zones;
       
    66 my $file;
       
    67 
       
    68 sub cleanup() { unlink @tmpfiles; }
       
    69 END { cleanup(); }
       
    70 
       
    71 for (@ARGV) {
       
    72 	if ($_ eq "-y") {
       
    73 		$opt_yes = 1;
       
    74 		shift @ARGV;
       
    75 	}
       
    76 }
       
    77 
       
    78 @Zones = @ARGV ? @ARGV : glob("$master_dir/*");
       
    79 
       
    80 
       
    81 MAIN: {
       
    82 	my $changed;
       
    83 	my ($dd, $mm, $yy) =(localtime())[3..5];
       
    84 	my $date;
       
    85 	$mm++;
       
    86 
       
    87 	foreach ($dd, $mm) { s/^\d$/0$&/; }
       
    88 	$yy += 1900;
       
    89 	$date = "$yy$mm$dd";
       
    90 
       
    91 
       
    92 	while (my $file = shift @Zones) {
       
    93 
       
    94 		my $file_basename = basename($file);
       
    95 
       
    96 		$file =~ s#($master_dir)(/.*)#$1$2$2#;
       
    97 		local (*I, *O);
       
    98 		my $done = 0;
       
    99 
       
   100 		my $new = "$file.$$.tmp";
       
   101 		my $bak = "$file.bak";
       
   102 		my $stamp = $master_dir . "/.stamp/" . basename($file);	
       
   103 
       
   104 		$file =~ /(\.bak|~)$/ and next;
       
   105 		$file !~ /\./ and next;
       
   106 
       
   107 		$verbose && print "$file:";
       
   108 
       
   109 
       
   110 		if (-f $stamp && ((stat($stamp))[9] >= (stat($file))[9])) {
       
   111 			$verbose && print " fresh, skipping.\n";
       
   112 			next;
       
   113 		}
       
   114 
       
   115 		$done = 0;
       
   116 		push @tmpfiles, $new;
       
   117 		open(*I, "<$file") or die("Can't open < $file: $!\n");
       
   118 		open(*O, ">$new") or die("Can't open > $new: $!\n");
       
   119 
       
   120 		while (<I>) {
       
   121 			/^\s+((\d+)(\d{2}))\s*;\s*serial/i and do {		# PATTERN
       
   122 				my ($sdate, $scount, $serial) = ($2, $3, $1);
       
   123 				$done = 1;
       
   124 				print " [$file] serial $sdate$scount";
       
   125 
       
   126 				if ($date eq $sdate) { $scount++; }
       
   127 				else { $sdate = $date; $scount = "00"; }
       
   128 
       
   129 				print " bumping to $sdate$scount \n";
       
   130 				s/$serial/$sdate$scount/;
       
   131 
       
   132 			};
       
   133 			print O;
       
   134 		}
       
   135 
       
   136 		close(O); close(I);
       
   137 
       
   138 		if ($done) {
       
   139 			# copy($file, $bak) or die("Can't copy $file -> $bak: $!\n");
       
   140 
       
   141 			open(I, "<$new") or die("Can't open <$new: $!\n");
       
   142 			open(O, ">$file") or die("Can't open >$file: $!\n");
       
   143 			while (<I>) { print O or die("Can't write to $file: $!\n"); }
       
   144 			close(I) or die("Can't close $new: $!\n");
       
   145 			close(O) or die("Can't close $file: $!\n");
       
   146 
       
   147 			unlink $new;
       
   148 
       
   149 			open(O, ">$stamp") or die("Can't open >$stamp: $!\n");
       
   150 			close(O);
       
   151 			$changed++;
       
   152 
       
   153 			# dnssec - new sign
       
   154 			system "$dnssec_sign $file_basename";
       
   155 			die "$dnssec_sign not found ($!)" if $? == -1;
       
   156 			exit 1 if $?;
       
   157 
       
   158 		} else {
       
   159 			print " $file: no serial number found: no zone file?";
       
   160 		}
       
   161 		print "\n";
       
   162 	}
       
   163 
       
   164 	if ($changed) {
       
   165 		my $pidfile;
       
   166 
       
   167 		print "** Changed $changed files, the nameserver needs to be reloaded!\n";
       
   168 		foreach (qw(/var/run/bind/run/named.pid /var/run/named.pid /etc/named.pid)) { 
       
   169 			-f $_ and $pidfile = $_ and last; }
       
   170 
       
   171 		if ($pidfile) {
       
   172 			if ($opt_yes) { $_ = "y"; print "** Nameserver will be reloaded\n"; } 
       
   173 			else { print "** Reload now? [Y/n]: "; $_ = <STDIN>; }
       
   174 			/^y|^$/i and system "rndc reload";
       
   175 		} else {
       
   176 			print "** No PID of a running named found.  Please reload manually.\n";
       
   177 		}
       
   178 
       
   179 	}
       
   180 }
       
   181 
       
   182 # vim:ts=4:sw=4:ai:aw: