Paranoid

 view release on metacpan or  search on metacpan

lib/Paranoid/Network/IPv6.pm  view on Meta::CPAN

my @base      = qw(ipv6NetConvert ipv6NetPacked ipv6NetIntersect);
my @constants = qw(MAXIPV6CIDR IPV6REGEX IPV6CIDRRGX IPV6BASE IPV6BRDCST
    IPV6MASK);
my @ipv6sort = qw(ipv6StrSort ipv6PackedSort ipv6NumSort);

($VERSION) = ( q$Revision: 2.10 $ =~ /(\d+(?:\.\d+)+)/sm );
@EXPORT      = @base;
@EXPORT_OK   = ( @base, @constants, @ipv6sort );
%EXPORT_TAGS = (
    all       => [@EXPORT_OK],
    base      => [@base],
    constants => [@constants],
    ipv6Sort  => [@ipv6sort],
    );

use constant MAXIPV6CIDR => 128;
use constant IPV6REGEX   => qr/
                            :(?::[abcdef\d]{1,4}){1,7}                   | 
                            \b[abcdef\d]{1,4}(?:::?[abcdef\d]{1,4}){1,7} | 
                            (?:\b[abcdef\d]{1,4}:){1,7}: 
                            /six;
use constant IPV6CIDRRGX =>
    qr#@{[ IPV6REGEX ]}/(?:1(?:[01]\d|2[0-8])|\d\d?)#s;
use constant IPV6BASE   => 0;
use constant IPV6BRDCST => 1;
use constant IPV6MASK   => 2;
use constant CHUNKMASK  => 0xffffffff;
use constant CHUNK      => 32;
use constant IPV6CHUNKS => 4;
use constant IPV6LENGTH => 16;

#####################################################################
#
# Module code follows
#
#####################################################################

sub ipv6NetConvert {

    # Purpose:  Takes a string representation of an IPv6 network
    #           address and returns a list of lists containing
    #           the binary network address, broadcast address,
    #           and netmask, each broken into 32bit chunks.
    #           Also allows for a plain IP being passed, in which
    #           case it only returns the binary IP.
    # Returns:  Array, empty on errors
    # Usage:    @network = ipv6NetConvert($netAddr);

    my $netAddr = shift;
    my ( $bnet, $bmask, $t, @tmp, @rv );

    subPreamble( PDLEVEL1, '$', $netAddr );

    if ( has_ipv6() or $] >= 5.012 ) {

        # Extract net address, mask
        if ( defined $netAddr ) {
            ($t) =
                ( $netAddr =~ m#^(@{[ IPV6CIDRRGX ]}|@{[ IPV6REGEX ]})$#s )
                [0];
            ( $bnet, $bmask ) = split m#/#s, $t if defined $t;
        }

        if ( defined $bnet and length $bnet ) {

            # First, convert $bnet to see if we have a valid IP address
            $bnet = [ unpack 'NNNN', inet_pton( AF_INET6(), $bnet ) ];

            if ( defined $bnet and length $bnet ) {

                # Save our network address
                push @rv, $bnet;

                if ( defined $bmask and length $bmask ) {

                    # Convert netmask
                    if ( $bmask <= MAXIPV6CIDR ) {

                        # Add the mask in 32-bit chunks
                        @tmp = ();
                        while ( $bmask >= CHUNK ) {
                            push @tmp, CHUNKMASK;
                            $bmask -= CHUNK;
                        }

                        # Push the final segment if there's a remainder
                        if ($bmask) {
                            push @tmp,
                                CHUNKMASK - ( ( 2**( CHUNK - $bmask ) ) - 1 );
                        }

                        # Add zero'd chunks to fill it out
                        while ( @tmp < IPV6CHUNKS ) {
                            push @tmp, 0x0;
                        }

                        # Finally, save the chunks
                        $bmask = [@tmp];

                    } else {
                        $bmask = undef;
                    }

                    if ( defined $bmask ) {

                        # Apply the mask to the base address
                        foreach ( 0 .. ( IPV6CHUNKS - 1 ) ) {
                            $$bnet[$_] &= $$bmask[$_];
                        }

                        # Calculate and save our broadcast address
                        @tmp = ();
                        foreach ( 0 .. ( IPV6CHUNKS - 1 ) ) {
                            $tmp[$_] =
                                $$bnet[$_] | ( $$bmask[$_] ^ CHUNKMASK );
                        }
                        push @rv, [@tmp];

                        # Save our mask
                        push @rv, $bmask;



( run in 0.579 second using v1.01-cache-2.11-cpan-71847e10f99 )