Paranoid

 view release on metacpan or  search on metacpan

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


use 5.008;

use strict;
use warnings;
use vars qw($VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS);
use base qw(Exporter);
use Paranoid;
use Paranoid::Debug qw(:all);
use Paranoid::Network::Socket;

my @base      = qw(ipv4NetConvert ipv4NetIntersect);
my @constants = qw(MAXIPV4CIDR IPV4REGEX IPV4CIDRRGX IPV4BASE IPV4BRDCST
    IPV4MASK);
my @ipv4sort = qw(ipv4NumSort ipv4StrSort ipv4PackedSort);

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

use constant MAXIPV4CIDR => 32;
use constant IPV4REGEX =>
    qr/(?:(?:25[0-5]|2[0-4][0-9]|1?\d\d?)\.){3}(?:25[0-5]|2[0-4][0-9]|1?\d\d?)/s;
use constant IPV4CIDRRGX =>
    qr#@{[ IPV4REGEX ]}/(?:(?:3[0-2]|[12]?\d)|@{[ IPV4REGEX ]})#s;
use constant FULLMASK   => 0xffffffff;
use constant IPV4BASE   => 0;
use constant IPV4BRDCST => 1;
use constant IPV4MASK   => 2;

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

sub ipv4NetConvert {

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

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

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

    # Extract net address, mask
    if ( defined $netAddr ) {
        ($t) = ( $netAddr =~ m#^(@{[ IPV4CIDRRGX ]}|@{[ IPV4REGEX ]})$#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 'N', inet_aton($bnet);

        if ( defined $bnet and length $bnet ) {

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

            if ( defined $bmask and length $bmask ) {

                # Convert netmask
                $bmask =
                      $bmask !~ /^\d+$/s ? unpack 'N', inet_aton($bmask)
                    : $bmask <= MAXIPV4CIDR
                    ? FULLMASK - ( ( 2**( MAXIPV4CIDR - $bmask ) ) - 1 )
                    : undef;

                if ( defined $bmask and length $bmask ) {

                    # Apply the mask to the base address
                    $rv[IPV4BASE] = $rv[IPV4BASE] & $bmask;

                    # Calculate and save our broadcast address
                    push @rv, $bnet | ( $bmask ^ FULLMASK );

                    # Save our mask
                    push @rv, $bmask;

                } else {
                    pdebug( 'invalid netmask passed', PDLEVEL1 );
                }
            }
        } else {
            pdebug( 'failed to convert IPv4 address', PDLEVEL1 );
        }
    } else {
        pdebug( 'failed to extract an IPv4 address', PDLEVEL1 );
    }

    subPostamble( PDLEVEL1, '@', @rv );

    return @rv;
}

sub ipv4NetIntersect {

    # Purpose:  Tests whether network address ranges intersect
    # Returns:  Integer, denoting whether an intersection exists, and what
    #           kind:
    #
    #              -1: destination range encompasses target range
    #               0: both ranges do not intersect at all
    #               1: target range encompasses destination range
    #
    # Usage:    $rv = ipv4NetIntersect($net1, $net2);



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