#!/usr/local/bin/perl -U $ver = "1.1.1"; $progname = "soa++"; $ext = ".bak"; # Specifiy an input file, or get a description of the funtion # unless($INfilename = shift){ print<<"INFO"; $progname v.$ver Usage: $progname filename [filename] where filename is a valid BIND configuration file (eg db.erols.com) and [filename] is an optional destination (use '-' for STDOUT). If the given file name has a SOA record $progname updates the SOA serial number. INFO exit(); } # Specify an output file, or use a temp file # based on input file. # $OUTfilename = $INfilename.$ext unless $OUTfilename = shift; # protect ourselves from foolishnes.. if (-e $OUTfilename) { die "$progname: $OUTfilename already exists! \n"; } # Lets not be clever... # if ($INfilename eq $OUTfilename){ die "$progname: Use '$progname $INfilename' to update $INfilename.\n"; } open(IN,$INfilename) || die "$progname: Unable to open $INfilename for input!\n"; open(OUT,">".$OUTfilename) || die "$progname: Unable to open $OUTfilename for output!\n"; # Is first line id'able as a SOA record? # (note - this assumes the SOA record is split into two lines) # $FoundSOA = ''; while(){ if ( /\bDNS\b/ ){ next; } if ( /\bTTL\b/ ){ $ttl = $_; print OUT "$ttl"; next; } if ( /\bORIGIN\b/ ){ $origin = $_; print OUT "$origin"; next; } if (!/\bSOA\b/ ){ close(OUT); unlink($OUTfilename); die "$progname: $INfilename is not a BIND file!\n"; }else{ print OUT $_; last; } } while(){ # Find and replace the existing SOA record # # print STDOUT "NextSOA is $sNextSOA", "\n"; # if (($sNextSOA eq '' ) && (/\)$/)){ <==THIS IS THE OLD WAY. if (($sNextSOA eq '' )) { # && (/\)$/)){ $sCurrentSOA = (split)[0]; unless( $sNextSOA = &NextSOASerialNum($sCurrentSOA)){ unlink($OUTfilename); die "$progname: bad SOA serial number\n" } s/$sCurrentSOA/$sNextSOA/; # Don't muck up the standard output print STDERR "[$sCurrentSOA] => [$sNextSOA]\n"; } # send it to output. # print OUT $_; } close(IN); close(OUT); # if user did not specify output file, # replace input file. # if($OUTfilename eq $INfilename.$ext){ rename($OUTfilename,$INfilename); } #------------------------------------- # Takes a serial number as sole argument. Returns the next valid serial # number # sub NextSOASerialNum{ local($sBaseSOA); local($sNextSOA); local($sCurrentSOA) = $_[0]; chop($sBaseSOA = `date '+%Y%m%d'`); if($sCurrentSOA =~ /^$sBaseSOA/ ){ $sNextSOA = $sCurrentSOA + 1; }else{ $sNextSOA = $sBaseSOA."01"; } if ($sCurrentSOA > $sNextSOA){ print STDERR "$progname: Badly formed current SOA #: $sCurrentSOA. \nShould be in form: YYYYMMDDnn where nn is a *two* digit \nnumber ranging from 01 to 99.\n"; return ""; }elsif($sNextSOA > 2**32){ # this is a BIND restriction.. # print STDERR "$progname: Next number in sequence is greater than 2^32!\n"; return ""; }else{ return $sNextSOA; } }