update-serial
changeset 32 d1addc2ec712
parent 31 1cea07056124
child 33 d3269961e944
equal deleted inserted replaced
31:1cea07056124 32:d1addc2ec712
     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 use strict;
       
    17 use warnings;
       
    18 
       
    19 use File::Basename;
       
    20 use File::Copy;
       
    21 use FindBin;
       
    22 
       
    23 my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
       
    24 my @dnssec_signs
       
    25     = ( "$FindBin::Bin/dnssec-sign", "/usr/bin/dnstools/dnssec-sign" );
       
    26 my %config;
       
    27 my $dnssec_sign;
       
    28 my @change_names = ();
       
    29 
       
    30 foreach ( grep {-f} @configs ) {
       
    31     open( CONFIG, $_ ) or die "Can't open $_: $!\n";
       
    32 }
       
    33 
       
    34 unless ( seek( CONFIG, 0, 0 ) ) {
       
    35     die "Can't open config (searched: @configs)\n";
       
    36 }
       
    37 foreach ( grep {-f} @dnssec_signs ) {
       
    38     if ( -x $_ ) {
       
    39         $dnssec_sign = $_;
       
    40     }
       
    41     else {
       
    42         die "Can't run $_\n";
       
    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 MAIN: {
       
    81     my $changed;
       
    82     my ( $dd, $mm, $yy ) = ( localtime() )[ 3 .. 5 ];
       
    83     my $date;
       
    84     $mm++;
       
    85 
       
    86     foreach ( $dd, $mm ) { s/^\d$/0$&/; }
       
    87     $yy += 1900;
       
    88     $date = "$yy$mm$dd";
       
    89 
       
    90     while ( my $file = shift @Zones ) {
       
    91 
       
    92         my $file_basename = basename($file);
       
    93 
       
    94         $file =~ s#($master_dir)(/.*)#$1$2$2#;
       
    95         local ( *I, *O );
       
    96         my $done = 0;
       
    97 
       
    98         my $new   = "$file.$$.tmp";
       
    99         my $bak   = "$file.bak";
       
   100         my $stamp = $master_dir . "/.stamp/" . basename($file);
       
   101 
       
   102         $file =~ /(\.bak|~)$/ and next;
       
   103         $file !~ /\./ and next;
       
   104 
       
   105         $verbose && print "$file:";
       
   106 
       
   107         if ( -f $stamp && ( ( stat($stamp) )[9] >= ( stat($file) )[9] ) ) {
       
   108             $verbose && print " fresh, skipping.\n";
       
   109             next;
       
   110         }
       
   111 
       
   112         $done = 0;
       
   113         push @tmpfiles, $new;
       
   114         open( *I, "<$file" ) or die("Can't open < $file: $!\n");
       
   115         open( *O, ">$new" )  or die("Can't open > $new: $!\n");
       
   116 
       
   117         while (<I>) {
       
   118             /^\s+((\d+)(\d{2}))\s*;\s*serial/i and do {    # PATTERN
       
   119                 my ( $sdate, $scount, $serial ) = ( $2, $3, $1 );
       
   120                 $done = 1;
       
   121                 print " [$file] serial $sdate$scount";
       
   122 
       
   123                 if   ( $date eq $sdate ) { $scount++; }
       
   124                 else                     { $sdate = $date; $scount = "00"; }
       
   125 
       
   126                 print " bumping to $sdate$scount";
       
   127                 s/$serial/$sdate$scount/;
       
   128 
       
   129             };
       
   130             print O;
       
   131         }
       
   132 
       
   133         close(O);
       
   134         close(I);
       
   135 
       
   136         if ($done) {
       
   137 
       
   138             # copy($file, $bak) or die("Can't copy $file -> $bak: $!\n");
       
   139 
       
   140             open( I, "<$new" )  or die("Can't open <$new: $!\n");
       
   141             open( O, ">$file" ) or die("Can't open >$file: $!\n");
       
   142             while (<I>) { print O or die("Can't write to $file: $!\n"); }
       
   143             close(I) or die("Can't close $new: $!\n");
       
   144             close(O) or die("Can't close $file: $!\n");
       
   145 
       
   146             unlink $new;
       
   147 
       
   148             open( O, ">$stamp" ) or die("Can't open >$stamp: $!\n");
       
   149             close(O);
       
   150             $changed++;
       
   151 
       
   152             push @change_names, $file_basename;
       
   153 
       
   154         }
       
   155         else {
       
   156             print " $file: no serial number found: no zone file?";
       
   157         }
       
   158         print "\n";
       
   159     }
       
   160 
       
   161     if ($changed) {
       
   162         my $pidfile;
       
   163 
       
   164         # dnssec - new sign
       
   165         system "$dnssec_sign @change_names";
       
   166         die "$dnssec_sign not found ($!)" if $? == -1;
       
   167         exit 1 if $?;
       
   168 
       
   169         print
       
   170             "** Changed $changed files, the nameserver needs to be reloaded!\n";
       
   171         foreach (
       
   172             qw(/var/run/bind/run/named.pid /var/run/named.pid /etc/named.pid))
       
   173         {
       
   174             -f $_ and $pidfile = $_ and last;
       
   175         }
       
   176 
       
   177         if ($pidfile) {
       
   178             if ($opt_yes) {
       
   179                 $_ = "y";
       
   180                 print "** Nameserver will be reloaded\n";
       
   181             }
       
   182             else { print "** Reload now? [Y/n]: "; $_ = <STDIN>; }
       
   183             /^y|^$/i and system "rndc reload";
       
   184         }
       
   185         else {
       
   186             print
       
   187                 "** No PID of a running named found.  Please reload manually.\n";
       
   188         }
       
   189 
       
   190     }
       
   191 }
       
   192 
       
   193 # vim:ts=4:sw=4:ai:aw: