NAME
    NetAddr::IP::Util -- IPv4/6 and 128 bit number utilities

SYNOPSIS
      use NetAddr::IP::Util qw(
            inet_aton
            inet_ntoa
            ipv6_aton
            ipv6_n2x
            ipv6_n2d
            inet_any2n
            hasbits
            isIPv4
            inet_n2dx
            inet_n2ad
            ipv4to6
            mask4to6
            ipanyto6
            maskanyto6
            ipv6to4
            shiftleft
            addconst
            add128
            sub128
            notcontiguous
            bin2bcd
            bcd2bin
            mode
      );

      use NetAddr::IP::Util qw(:all :inet :ipv4 :ipv6 :math)

      :inet   =>    inet_aton, inet_ntoa, ipv6_aton,
                    ipv6_n2x, ipv6_n2d, inet_any2n, 
                    inet_n2dx, inet_n2ad, ipv4to6,
                    mask4to6, ipanyto6, maskanyto6,
                    ipv6to4

      :ipv4   =>    inet_aton, inet_ntoa

      :ipv6   =>    ipv6_aton, ipv6_n2x, ipv6_n2d,
                    inet_any2n, inet_n2dx, inet_n2ad
                    ipv4to6, mask4to6, ipanyto6,
                    maskanyto6, ipv6to4

      :math   =>    hasbits, isIPv4, addconst,
                    add128, sub128, notcontiguous,
                    bin2bcd, bcd2bin, shiftleft

      $dotquad = inet_ntoa($netaddr);
      $netaddr = inet_aton($dotquad);
      $ipv6naddr = ipv6_aton($ipv6_text);
      $hex_text = ipv6_n2x($ipv6naddr);
      $dec_text = ipv6_n2d($ipv6naddr);
      $ipv6naddr = inet_any2n($dotquad or $ipv6_text);
      $rv = hasbits($bits128);
      $rv = isIPv4($bits128);
      $dotquad or $hex_text = inet_n2dx($ipv6naddr);
      $dotquad or $dec_text = inet_n2ad($ipv6naddr);
      $ipv6naddr = ipv4to6($netaddr);
      $ipv6naddr = mask4to6($netaddr);
      $ipv6naddr = ipanyto6($netaddr);
      $ipv6naddr = maskanyto6($netaddr);
      $netaddr = ipv6to4($pv6naddr);
      $bitsX2 = shiftleft($bits128,$n);
      $carry = addconst($ipv6naddr,$signed_32con);
      ($carry,$ipv6naddr)=addconst($ipv6naddr,$signed_32con);
      $carry = add128($ipv6naddr1,$ipv6naddr2);
      ($carry,$ipv6naddr)=add128($ipv6naddr1,$ipv6naddr2);
      $carry = sub128($ipv6naddr1,$ipv6naddr2);
      ($carry,$ipv6naddr)=sub128($ipv6naddr1,$ipv6naddr2);
      ($spurious,$cidr) = notcontiguous($mask128);
      $bcdtext = bin2bcd($bits128);
      $bits128 = bcd2bin($bcdtxt);
      $modetext = mode;

INSTALLATION
    Un-tar the distribution in an appropriate directory and type:

            perl Makefile.PL
            make
            make test
            make install

    NetAddr::IP::Util installs by default with its primary functions
    compiled using Perl's XS extensions to build a 'C' library. If you do
    not have a 'C' complier available or would like the slower Pure Perl
    version for some other reason, then type:

            perl Makefile.PL -noxs
            make
            make test
            make install

DESCRIPTION
    NetAddr::IP::Util provides a suite of tools for manipulating and
    converting IPv4 and IPv6 addresses into 128 bit string context and back
    to text. The strings can be manipulated with Perl's logical operators:

            and     &
            or      |
            xor     ^

    in the same manner as 'vec' strings.

    The IPv6 functions support all rfc1884 formats.

      i.e.  x:x:x:x:x:x:x:x:x
            x:x:x:x:x:x:x:d.d.d.d
            ::x:x:x
            ::x:d.d.d.d
      and so on...

    * $dotquad = inet_ntoa($netaddr);
        Convert a packed IPv4 network address to a dot-quad IP address.

          input:        packed network address
          returns:      IP address i.e. 10.4.12.123

    * $netaddr = inet_aton($dotquad);
        Convert a dot-quad IP address into an IPv4 packed network address.

          input:        IP address i.e. 192.5.16.32
          returns:      packed network address

    * $ipv6addr = ipv6_aton($ipv6_text);
        Takes an IPv6 address of the form described in rfc1884 and returns a
        128 bit binary RDATA string.

          input:        ipv6 text
          returns:      128 bit RDATA string

    * $hex_text = ipv6_n2x($ipv6addr);
        Takes an IPv6 RDATA string and returns an 8 segment IPv6 hex address

          input:        128 bit RDATA string
          returns:      x:x:x:x:x:x:x:x

    * $dec_text = ipv6_n2d($ipv6addr);
        Takes an IPv6 RDATA string and returns a mixed hex - decimal IPv6
        address with the 6 uppermost chunks in hex and the lower 32 bits in
        dot-quad representation.

          input:        128 bit RDATA string
          returns:      x:x:x:x:x:x:d.d.d.d

    * $ipv6naddr = inet_any2n($dotquad or $ipv6_text);
        This function converts a text IPv4 or IPv6 address in text format in
        any standard notation into a 128 bit IPv6 string address. It
        prefixes any dot-quad address (if found) with '::' and passes it to
        ipv6_aton.

          input:        dot-quad or rfc1844 address
          returns:      128 bit IPv6 string

    * $rv = hasbits($bits128);
        This function returns true if there are one's present in the 128 bit
        string and false if all the bits are zero.

          i.e.  if (hasbits($bits128)) {
                  &do_something;
                }

          or    if (hasbits($bits128 & $mask128) {
                  &do_something;
                }

        This allows the implementation of logical functions of the form of:

                if ($bits128 & $mask128) {
                    ...

          input:        128 bit IPv6 string
          returns:      true if any bits are present

    * $rv = isIPv4($bits128);
        This function returns true if there are no on bits present in the
        IPv6 portion of the 128 bit string and false otherwise.

    * $dotquad or $hex_text = inet_n2dx($ipv6naddr);
        This function does the right thing and returns the text for either a
        dot-quad IPv4 or a hex notation IPv6 address.

          input:        128 bit IPv6 string
          returns:      ddd.ddd.ddd.ddd
                    or  x:x:x:x:x:x:x:x

    * $dotquad or $dec_text = inet_n2ad($ipv6naddr);
        This function does the right thing and returns the text for either a
        dot-quad IPv4 or a hex::decimal notation IPv6 address.

          input:        128 bit IPv6 string
          returns:      ddd.ddd.ddd.ddd
                    or  x:x:x:x:x:x:ddd.ddd.ddd.dd

    * $ipv6naddr = ipv4to6($netaddr);
        Convert an ipv4 network address into an ipv6 network address.

          input:        32 bit network address
          returns:      128 bit network address

    * $ipv6naddr = mask4to6($netaddr);
        Convert an ipv4 netowrk address into an ipv6 network mask.

          input:        32 bit network/mask address
          returns:      128 bit network/mask address

        NOTE: returns the high 96 bits as one's

    * $ipv6naddr = ipanyto6($netaddr);
        Similar to ipv4to6 except that this function takes either an IPv4 or
        IPv6 input and always returns a 128 bit IPv6 network address.

          input:        32 or 128 bit network address
          returns:      128 bit network address

    * $ipv6naddr = maskanyto6($netaddr);
        Similar to mask4to6 except that this function takes either an IPv4
        or IPv6 netmask and always returns a 128 bit IPv6 netmask.

          input:        32 or 128 bit network mask
          returns:      128 bit network mask

    * $netaddr = ipv6to4($pv6naddr);
        Truncate the upper 96 bits of a 128 bit address and return the lower
        32 bits. Returns an IPv4 address as returned by inet_aton.

          input:        128 bit network address
          returns:      32 bit inet_aton network address

    * $bitsXn = shiftleft($bits128,$n);
          input:        128 bit string variable,
                        number of shifts [optional]
          returns:      bits X n shifts

          NOTE: a single shift is performed 
                if $n is not specified

    * addconst($ipv6naddr,$signed_32con);
        Add a signed constant to a 128 bit string variable.

          input:        128 bit IPv6 string,
                        signed 32 bit integer
          returns:  scalar      carry
                    array       (carry, result)

    * add128($ipv6naddr1,$ipv6naddr2);
        Add two 128 bit string variables.

          input:        128 bit string var1,
                        128 bit string var2
          returns:  scalar      carry
                    array       (carry, result)

    * sub128($ipv6naddr1,$ipv6naddr2);
        Subtract two 128 bit string variables.

          input:        128 bit string var1,
                        128 bit string var2
          returns:  scalar      carry
                    array       (carry, result)
    
        Note: The carry from this operation is the result of adding the
        one's complement of ARG2 +1 to the ARG1. It is logically NOT borrow.

                i.e.    if ARG1 >= ARG2 then carry = 1
                or      if ARG1  < ARG2 then carry = 0

    * ($spurious,$cidr) = notcontiguous($mask128);
        This function counts the bit positions remaining in the mask when
        the rightmost '0's are removed.

                input:  128 bit netmask
                returns true if there are spurious
                            zero bits remaining in the
                            mask, false if the mask is
                            contiguous one's,
                        128 bit cidr number

    * $bcdtext = bin2bcd($bits128);
        Convert a 128 bit binary string into binary coded decimal text
        digits.

          input:        128 bit string variable
          returns:      string of bcd text digits

    * $bits128 = bcd2bin($bcdtxt);
        Convert a bcd text string to 128 bit string variable

          input:        string of bcd text digits
          returns:      128 bit string variable

    * $modetext = mode;
        Returns the operating mode of this module.

                input:          none
                returns:        "Pure Perl"
                           or   "CC XS"

EXAMPLES
      # convert any textual IP address into a 128 bit vector
      #
      sub text2vec {
        my($anyIP,$anyMask) = @_;

      # not IPv4 bit mask
        my $notiv4 = ipv6_aton('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::');

        my $vecip   = inet_any2n($anyIP);
        my $mask    = inet_any2n($anyMask);

      # extend mask bits for IPv4
        my $bits = 128;     # default
        unless (hasbits($mask & $notiv4)) {
          $mask |= $notiv4;
          $bits = 32;
        }
        return ($vecip, $mask, $bits);
      }

      ... alternate implementation, a little faster

      sub text2vec {
        my($anyIP,$anyMask) = @_;

      # not IPv4 bit mask
        my $notiv4 = ipv6_aton('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::');

        my $vecip   = inet_any2n($anyIP);
        my $mask    = inet_any2n($anyMask);

      # extend mask bits for IPv4
        my $bits = 128;     # default
        if (isIPv4($mask)) {
          $mask |= $notiv4;
          $bits = 32;
        }
        return ($vecip, $mask, $bits);
      }

      ... elsewhere
        $nip = {
            addr    => $vecip,
            mask    => $mask,
            bits    => $bits,
        };

      # return network and broadcast addresses from IP and Mask
      #
      sub netbroad {
        my($nip) = shift;
        my $notmask = ~ $nip->{mask};
        my $bcast   = $nip->{addr} | $notmask;
        my $network = $nip->{addr} & $nip->{mask};
        return ($network, $broadcast);
      }

      # check if address is within a network
      #
      sub within {
        my($nip,$net) = @_;
        my $addr = $nip->{addr}
        my($nw,$bc) = netbroad($net);
      # arg1 >= arg2, sub128 returns true
        return (sub128($addr,$nw) && sub128($bc,$addr))
            ? 1 : 0;
      }

      # add a constant, wrapping at netblock boundries
      # to subtract the constant, negate it before calling 
      # 'addwrap' since 'addconst' will extend the sign bits
      #
      sub addwrap {
        my($nip,$const) = @_;
        my $mask    = $nip->{addr};
        my $bits    = $nip->{bits};
        my $notmask = ~ $mask;
        my $hibits  = $addr & $mask;
        my $addr = addconst($addr,$const);
        my $wraponly = $addr & $notmask;
        my $newip = {
            addr    => $hibits | $wraponly,
            mask    => $mask,
            bits    => $bits,
        };
        # bless $newip as appropriate
        return $newip;
      }     
    
EXPORT_OK
            inet_aton
            inet_ntoa
            ipv6_aton
            ipv6_n2x
            ipv6_n2d
            inet_any2n
            hasbits
            isIPv4
            inet_n2dx
            inet_n2ad
            ipv4to6
            mask4to6
            ipanyto6
            maskanyto6
            ipv6to4
            shiftleft
            addconst
            add128
            sub128
            notcontiguous
            bin2bcd
            bcd2bin
            mode

AUTHOR
    Michael Robinton <michael@bizsystems.com>

ACKNOWLEDGEMENTS
    The following functions are used in whole or in part as include files to
    Util.xs. The copyright is include in the file.

      file:              function:

      miniSocket.inc  inet_aton, inet_ntoa

    inet_aton, inet_ntoa are from the perl-5.8.0 release by Larry Wall,
    copyright 1989-2002. inet_aton, inet_ntoa code is current through
    perl-5.9.3 release. Thank you Larry for making PERL possible for all of
    us.

COPYRIGHT
    Copyright 2003 - 2006, Michael Robinton <michael@bizsystems.com>

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License (except as noted
    otherwise in individuals sub modules) published by the Free Software
    Foundation; either version 2 of the License, or (at your option) any
    later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
    Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

AUTHOR
    Michael Robinton <michael@bizsystems.com>

