#!/usr/bin/perl -w # # $Id: //pentools/main/incsoa/incsoa#2 $ # # written by : Stephen J. Friedl # Software Consultant # Southern California USA # steve@unixwiz.net / www.unixwiz.net # # This program is used for incrementing the serial number in the SOA # record of a BIND zone configuration file. The serial number must # be incremented when any changes are made, and though it's not so hard # to do by hand, this makes it easier. # # It was *specifically* designed to be used from vi with the "filter # through" command. # # @ IN SOA unixwiz.net. root.unixwiz.net. ( # 2002051001 ; Serial # 1h ; Refresh # 30m ; Retry # 4w ; Expire # 20m ) ; Minimum TTL # # Here, the cursor would be placed anywhere on the "Serial" line, and # # !!incsoa # # would be typed: this filters the current line through the program, and # the serial number digits are incremented in place. There is probably # a way to do this in emacs, but we don't use it. # # Incrementing the serial number is done intelligently: if the file uses # the convention with YYYYMMDDsss, with "sss" being a per-day sequence # number, this program will recognize that. If the existing serial # represents the current date, only the sequence number is incremented, # otherwise today's date is used with a sequence of 1. use strict; use warnings; die "ERROR: no command-line params allowed\n" if @ARGV; my $line = ; die "ERROR: cannot read SOA from input\n" if not $line; if ( $line =~ m/^ \s+ (\d+)/x ) { my $oldsoa = $1; # original my $newsoa = $oldsoa + 1; # ---------------------------------------------------------------- # Special case for the date-based serial numbers. # if ( $oldsoa =~ m/^(20\d\d) # year (\d\d) # month (\d\d) # day (\d+)/x ) # additional { my $yyyy = $1; # YEAR my $mm = $2; # MONTH my $dd = $3; # DAY OF MONTH my $seq = $4; # per-day sequence my $seqlen = length $4; # how many digits? # figure out the old YYYYMMDD (without the sequence number # part), as well as *today's* date. my $oldyymmdd = sprintf("%04d%02d%02d", $yyyy, $mm, $dd ); my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime; my $newyymmdd = sprintf("%04d%02d%02d", 1900 + $year, 1 + $mon, $mday ); if ( $oldyymmdd > $newyymmdd ) { die "ERROR: $oldyymmdd is past today's date\n"; } elsif ( $newyymmdd > $oldyymmdd ) { $seq = 1; } else { $seq++; } $newsoa = sprintf("%s%0*d", $newyymmdd, $seqlen, $seq); } $line =~ s/$oldsoa/$newsoa/; print $line; } else { die "ERROR: could not read serial number\n"; }