NAME
   DNS::ZoneSerialNumber - Manipulate DNS zone serial numbers.

SYNOPSIS
     use DNS::ZoneSerialNumber;
     my $zsn = DNS::ZoneSerialNumber->new(100);
     $zsn->increment();
     print "The new serial number is ", $zsn->serial, "\n";

DESCRIPTION
   DNS::ZoneSerialNumber encapsulates a DNS zone serial number and provides
   RFC 1982, 1912, and 2136 compliant manipulation, comparison, and
   validation methods. This module automatically handles serial number
   overflows, underflows, and invalid comparisons, as well as simple
   increments and decrements.

METHODS
 new
   Constructor for the DNS::ZoneSerialNumber object. Accepts a single
   optional parameter, the serial number that the object should represent.
   If not specified, defaults to 1. If an invalid serial number is
   specified, the method will croak.

   On success, returns the DNS::ZoneSerialNumber object.

 valid
   Accepts a single parameter, the serial number to test for validity.

   Returns true or false depending representing whether or not the
   specified serial number represents a valid serial number. Valid serial
   numbers are positive integers between 1 and SERIAL_MAX (inclusive). See
   CONSTANTS for details.

   Note: This method may be called statically or as an instance method.

 serial
   Accepts no parameters. Returns the represented serial number as a Perl
   scalar.

   Note: In string or numeric context, a DNS::ZoneSerialNumber object will
   return an appropriate representation of its serial number automatically.

 set
   Accepts a single parameter, the new serial number. Returns the
   DNS::ZoneSerialNumber object with the updated serial number.

   Sets the serial number represented by the object to the specified serial
   number. If the specified serial number is invalid the method will croak.

 set_from_date
   Accepts a single optional parameter, the revision count of the new
   date-based serial number. If an invalid revision count is specified (< 0
   or > 99), the method will croak. Returns the DNS::ZoneSerialNumber with
   the updated serial number.

   Sets the serial number represented by the object to a serial number
   based on the current date in the format specified by RFC 1912
   (YYYYMMDDnn). This format allows for a two-digit revision count (nn)
   which defaults to "00" unless specified.

 steps_to_set
   Accepts a single parameter, the new serial number. If the specified
   serial number is invalid, the method will croak. In array context,
   returns an in-order array of DNS::ZoneSerialNumber objects representing
   the serial numbers that must be set in order to safely set the specified
   serial number. In scalar context the number of required steps is
   returned.

   Due to the way RFC 1982 defines serial number comparisons, it is not
   possible to simply set a zone's serial number to any number considered
   less than the current serial number. If this is done, DNS servers will
   assume that the new serial number is older than the prior serial number.
   In order to set the serial number to a lower value without DNS servers
   believing the serial number is lower, it must first be set to a higher
   number (and eventually overflowed) and propagated out. This method
   generates the list of serial numbers that must be set, in order, to
   allow a serial number to be set to a lower value without DNS servers
   believing the serial number is older. On success, this method
   necessarily returns an array of 1 or 2 elements (or the numbers 1 or 2
   in scalar context).

   If the specified serial number is greater than or equal to the
   represented serial number, no additional steps are required and an array
   of a single element (or the number 1 in scalar context) is returned.

   Please note that because this module always avoids the serial number 0,
   it may compute a different set of increments to arrive at the specified
   serial number than other tools.

   For more information see RFC 1982.

 incomparable
   Accepts no parameters. Returns a DNS::ZoneSerialNumber object
   representing the incomparable value for the currently represented serial
   number.

   See RFC 1982 for more information about incomparable serial numbers.

 is_incomparable
   Accepts a single parameter, the serial number against which the
   represented serial number should be checked for incomparability. If the
   specified serial number is invalid, the method will croak.

   Returns true if the serial numbers are incomparable or false otherwise.

   See RFC 1982 for more information about incomparable serial numbers.

 next
   Accepts a single optional parameter, the amount to increment by (n). If
   no parameter is specified, the amount defaults to 1. If an invalid
   amount is specified, the method will croak. Please see CONSTANTS for
   details. Returns the next nth serial number in sequence as a
   DNS::ZoneSerialNumber object. The currently represented serial number is
   unchanged.

   If the serial number overflows the serial maximum it will automatically
   roll over through the serial minimum.

   This method is also available as the overloaded operator "+". Please
   note that the protections against invalid increments can be circumvented
   via compound addition using the overloaded methods. For example, the
   following will succeed even though it results in an invalid increment
   due to the fact the addition was done in multiple steps:

    my $new_zsn = $zsn + DNS::ZoneSerialNumber::INCREMENT_MAX + 1;

   However, the following will (correctly) generate an error:

    my $new_zsn = $zsn + ( DNS::ZoneSerialNumber::INCREMENT_MAX + 1 );

 previous
   Accepts a single optional parameter, the amount to decrement by (n). If
   no parameter is specified, the amount defaults to 1. If an invalid
   amount is specified, the method will croak. Please see CONSTANTS for
   details. Returns the prior nth serial number in sequence as a
   DNS::ZoneSerialNumber object. The currently represented serial number is
   unchanged.

   If the serial number underflows the serial minimum it will automatically
   roll over through the serial maximum.

   This method is also available as the overloaded operator "-".

 increment
   Accepts a single optional parameter, the amount to increment by (n). If
   no parameter is specified, the amount defaults to 1. If an invalid
   amount is specified, the method will croak. Please see CONSTANTS for
   details. Sets the currently represented serial number to the nth next
   serial number in sequence and returns the DNS::ZoneSerialNumber object
   with the updated value.

   If the serial number overflows the serial maximum it will automatically
   roll over through the serial minimum.

   This method is also available as the overloaded operator "++".

 decrement
   Accepts a single optional parameter, the amount to decrement by (n). If
   no parameter is specified, the amount defaults to 1. If an invalid
   amount is specified, the method will croak. Please see CONSTANTS for
   details. Sets the currently represented serial number to the nth prior
   serial number in sequence and returns the DNS::ZoneSerialNumber object
   with the updated value.

   If the serial number underflows the serial minimum it will automatically
   roll over through the serial maximum.

   This method is also available as the overloaded operator "--".

 compare
   Accepts a single parameter, the serial number to be compared against the
   one represented by the DNS::ZoneSerialNumber object. If the supplied
   serial number is invalid, the method will croak.

   This method's behavior is the same as the <=> operator, however in the
   case of incomparable numbers undef is returned. This method is also
   available as the overloaded operator "<=>".

 Overloaded Comparison Methods
   All of the following methods accept a single argument, the serial number
   to be compared against the one represented by the DNS::ZoneSerialNumber
   object. If the supplied serial number is invalid, the method will croak.

   Each method true or false as a result of the comparison. In the case of
   incomparable numbers, false is returned by all methods except "ne (!=)".
   All of the following methods are also available as overloaded comparison
   operators.

   The comparison is performed with the encapsulated serial number treated
   as the left operand. For example:

    $zsn->gt(100)

   Is the equivalent of writing:

    $zsn > 100

   The following methods are available:

  gt (>)
  gte (>=)
  lt (<)
  lte (<=)
  eq (==)
  ne (!=)
CONSTANTS
   DNS::ZoneSerialNumber contains the following internal constants
   representing definitions and rules used by DNS::ZoneSerialNumber and RFC
   1982. These constants are not exported but are available if accessed via
   the full namespace (eg, DNS::ZoneSerialNumber::SERIAL_BITS).

 SERIAL_BITS
   The number of bits used to represent a DNS zone serial number. Set at
   32.

 SERIAL_MAX
   The maximum value a serial number of SERIAL_BITS size can store.
   Computed as:

    ( 2 ** SERIAL_MAX ) - 1

 SERIAL_HALF
   Approximately half the serial maximum value as used in RFC 1982 equality
   calculations. This value is used in serial number comparisons and in
   calculating incomparable serial numbers. Computed as:

    2 ** ( SERIAL_BITS - 1 )

 INCREMENT_MAX
   The maximum amount by which a serial number can be incremented in a
   single step. If incremented by more than this amount, the serial number
   would appear to have gone "backwards", see RFC 1982 for details.
   Computed as:

    ( 2 ** ( SERIAL_BITS - 1 ) ) - 1

SERIAL NUMBER 0
   As per RFC 2136, the serial number 0 is not used and is skipped for all
   additive and subtractive calculations. For example, if a
   DNS::ZoneSerialNumber object representing the serial number SERIAL_MAX
   is then incremented by 1, the new serial number will be set to 1 rather
   than 0.

   Comparisons will still take serial number 0 into account as expected.

INVALID COMPARISONS
   The serial number logic provided by RFC 1982 defines two serial numbers
   with a difference of ( 2 ** SERIAL_MAX ) to be considered neither
   greater than, less than, nor equal to each other. The RFC provides no
   recommendations on how to handle comparisons of these numbers and
   suggests they not be compared directly or used together in the same
   environment. DNS::ZoneSerialNumber attempts to compare these serial
   numbers using the same logic that BIND uses: all comparison methods will
   return false for any comparison of these serial number pairs, except for
   "ne (!=)" which returns true, and compare (<=>) which returns undef.

OPERATOR OVERLOADING
   DNS::ZoneSerialNumber provides overloaded operators for many of its
   provided methods. The author is currently unsure as to whether or not
   this is a good idea. If it proves to be problematic, the overloads may
   be removed (or made optional) in a future version.

CHANGES
 1.01 - 20120120, jeagle
   Minor documentation updates.

 1.00 - 20120118, jeagle
   Initial release to CPAN.

SEE ALSO
   DNS::ZoneParse, Net::DNS, RFC 1982, RFC 1912, RFC 2136

AUTHOR
   John Eaglesham

COPYRIGHT AND LICENSE
   Copyright (C) 2011-2012 by John Eaglesham

   This library is free software; you can redistribute it and/or modify it
   under the same terms as Perl itself, either Perl version 5.6.0 or, at
   your option, any later version of Perl 5 you may have available.